Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: rcar-gen3-usb2: add runtime ID/VBUS pin detection

This patch adds support for runtime ID/VBUS pin detection if
the channel 0 of R-Car gen3 is used. So, we are able to use
the channel as both host and peripheral.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Yoshihiro Shimoda and committed by
Kishon Vijay Abraham I
9f391c57 1114e2d3

+44 -1
+2
Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
··· 18 18 peripheral at that channel: 19 19 - reg: offset and length of the partial HSUSB register block. 20 20 - reg-names: must be "hsusb". 21 + - interrupts: interrupt specifier for the PHY. 21 22 22 23 Example (R-Car H3): 23 24 ··· 26 25 compatible = "renesas,usb2-phy-r8a7795"; 27 26 reg = <0 0xee080200 0 0x700>, <0 0xe6590100 0 0x100>; 28 27 reg-names = "usb2_host", "hsusb"; 28 + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; 29 29 clocks = <&mstp7_clks R8A7795_CLK_EHCI0>, 30 30 <&mstp7_clks R8A7795_CLK_HSUSB>; 31 31 };
+42 -1
drivers/phy/phy-rcar-gen3-usb2.c
··· 12 12 * published by the Free Software Foundation. 13 13 */ 14 14 15 + #include <linux/interrupt.h> 15 16 #include <linux/io.h> 16 17 #include <linux/module.h> 17 18 #include <linux/of.h> ··· 26 25 #define USB2_SPD_RSM_TIMSET 0x10c 27 26 #define USB2_OC_TIMSET 0x110 28 27 #define USB2_COMMCTRL 0x600 28 + #define USB2_OBINTSTA 0x604 29 + #define USB2_OBINTEN 0x608 29 30 #define USB2_VBCTRL 0x60c 30 31 #define USB2_LINECTRL1 0x610 31 32 #define USB2_ADPCTRL 0x630 32 33 33 34 /* INT_ENABLE */ 35 + #define USB2_INT_ENABLE_UCOM_INTEN BIT(3) 34 36 #define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) 35 37 #define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) 36 - #define USB2_INT_ENABLE_INIT (USB2_INT_ENABLE_USBH_INTB_EN | \ 38 + #define USB2_INT_ENABLE_INIT (USB2_INT_ENABLE_UCOM_INTEN | \ 39 + USB2_INT_ENABLE_USBH_INTB_EN | \ 37 40 USB2_INT_ENABLE_USBH_INTA_EN) 38 41 39 42 /* USBCTR */ ··· 52 47 53 48 /* COMMCTRL */ 54 49 #define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */ 50 + 51 + /* OBINTSTA and OBINTEN */ 52 + #define USB2_OBINT_SESSVLDCHG BIT(12) 53 + #define USB2_OBINT_IDDIGCHG BIT(11) 54 + #define USB2_OBINT_BITS (USB2_OBINT_SESSVLDCHG | \ 55 + USB2_OBINT_IDDIGCHG) 55 56 56 57 /* VBCTRL */ 57 58 #define USB2_VBCTRL_DRVVBUSSEL BIT(8) ··· 185 174 186 175 val = readl(usb2_base + USB2_VBCTRL); 187 176 writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); 177 + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); 178 + val = readl(usb2_base + USB2_OBINTEN); 179 + writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); 188 180 val = readl(usb2_base + USB2_ADPCTRL); 189 181 writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); 190 182 val = readl(usb2_base + USB2_LINECTRL1); ··· 284 270 .owner = THIS_MODULE, 285 271 }; 286 272 273 + static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch) 274 + { 275 + struct rcar_gen3_chan *ch = _ch; 276 + void __iomem *usb2_base = ch->usb2.base; 277 + u32 status = readl(usb2_base + USB2_OBINTSTA); 278 + irqreturn_t ret = IRQ_NONE; 279 + 280 + if (status & USB2_OBINT_BITS) { 281 + dev_vdbg(&ch->phy->dev, "%s: %08x\n", __func__, status); 282 + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); 283 + rcar_gen3_device_recognition(ch); 284 + ret = IRQ_HANDLED; 285 + } 286 + 287 + return ret; 288 + } 289 + 287 290 static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = { 288 291 { .compatible = "renesas,usb2-phy-r8a7795" }, 289 292 { } ··· 333 302 334 303 /* To avoid error message by devm_ioremap_resource() */ 335 304 if (res) { 305 + int irq; 306 + 336 307 channel->hsusb.base = devm_ioremap_resource(dev, res); 337 308 if (IS_ERR(channel->hsusb.base)) 338 309 channel->hsusb.base = NULL; 310 + /* call request_irq for OTG */ 311 + irq = platform_get_irq(pdev, 0); 312 + if (irq >= 0) 313 + irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, 314 + IRQF_SHARED, dev_name(dev), 315 + channel); 316 + if (irq < 0) 317 + dev_err(dev, "No irq handler (%d)\n", irq); 339 318 } 340 319 341 320 /* devm_phy_create() will call pm_runtime_enable(dev); */