99 * Copyright (C) 2014 Cogent Embedded, Inc.
1010 */
1111
12+ #include <linux/bitfield.h>
13+ #include <linux/bits.h>
1214#include <linux/cleanup.h>
1315#include <linux/extcon-provider.h>
1416#include <linux/interrupt.h>
6971#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
7072
7173/* OBINTSTA and OBINTEN */
74+ #define USB2_OBINTSTA_CLEAR GENMASK(31, 0)
7275#define USB2_OBINT_SESSVLDCHG BIT(12)
7376#define USB2_OBINT_IDDIGCHG BIT(11)
77+ #define USB2_OBINT_VBSTAINT BIT(3)
7478#define USB2_OBINT_IDCHG_EN BIT(0) /* RZ/G2L specific */
7579
7680/* VBCTRL */
81+ #define USB2_VBCTRL_VBSTA_MASK GENMASK(31, 28)
82+ #define USB2_VBCTRL_VBSTA_DEFAULT 2
83+ #define USB2_VBCTRL_VBLVL_MASK GENMASK(23, 20)
84+ #define USB2_VBCTRL_VBLVL (m ) FIELD_PREP_CONST(USB2_VBCTRL_VBLVL_MASK, (m))
7785#define USB2_VBCTRL_OCCLREN BIT(16)
7886#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
87+ #define USB2_VBCTRL_SIDDQREL BIT(2)
7988#define USB2_VBCTRL_VBOUT BIT(0)
8089
8190/* LINECTRL1 */
8897/* ADPCTRL */
8998#define USB2_ADPCTRL_OTGSESSVLD BIT(20)
9099#define USB2_ADPCTRL_IDDIG BIT(19)
100+ #define USB2_ADPCTRL_VBUSVALID BIT(18)
91101#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
92102#define USB2_ADPCTRL_DRVVBUS BIT(4)
93103
@@ -138,6 +148,7 @@ struct rcar_gen3_phy_drv_data {
138148 bool no_adp_ctrl ;
139149 bool init_bus ;
140150 bool utmi_ctrl ;
151+ bool vblvl_ctrl ;
141152 u32 obint_enable_bits ;
142153};
143154
@@ -201,7 +212,7 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
201212 u32 val ;
202213
203214 dev_vdbg (ch -> dev , "%s: %08x, %d\n" , __func__ , val , vbus );
204- if (ch -> phy_data -> no_adp_ctrl ) {
215+ if (ch -> phy_data -> no_adp_ctrl || ch -> phy_data -> vblvl_ctrl ) {
205216 if (ch -> vbus )
206217 regulator_hardware_enable (ch -> vbus , vbus );
207218
@@ -284,6 +295,16 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch)
284295
285296static bool rcar_gen3_check_id (struct rcar_gen3_chan * ch )
286297{
298+ if (ch -> phy_data -> vblvl_ctrl ) {
299+ bool vbus_valid ;
300+ bool device ;
301+
302+ device = !!(readl (ch -> base + USB2_ADPCTRL ) & USB2_ADPCTRL_IDDIG );
303+ vbus_valid = !!(readl (ch -> base + USB2_ADPCTRL ) & USB2_ADPCTRL_VBUSVALID );
304+
305+ return !(device && !vbus_valid );
306+ }
307+
287308 if (!ch -> uses_otg_pins )
288309 return (ch -> dr_mode == USB_DR_MODE_HOST ) ? false : true;
289310
@@ -419,11 +440,20 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
419440 writel (val , usb2_base + USB2_LINECTRL1 );
420441
421442 if (!ch -> phy_data -> no_adp_ctrl ) {
422- val = readl (usb2_base + USB2_VBCTRL );
423- val &= ~USB2_VBCTRL_OCCLREN ;
424- writel (val | USB2_VBCTRL_DRVVBUSSEL , usb2_base + USB2_VBCTRL );
425- val = readl (usb2_base + USB2_ADPCTRL );
426- writel (val | USB2_ADPCTRL_IDPULLUP , usb2_base + USB2_ADPCTRL );
443+ if (ch -> phy_data -> vblvl_ctrl ) {
444+ val = readl (usb2_base + USB2_VBCTRL );
445+ val = (val & ~USB2_VBCTRL_VBLVL_MASK ) | USB2_VBCTRL_VBLVL (2 );
446+ writel (val , usb2_base + USB2_VBCTRL );
447+ val = readl (usb2_base + USB2_ADPCTRL );
448+ writel (val | USB2_ADPCTRL_IDPULLUP | USB2_ADPCTRL_DRVVBUS ,
449+ usb2_base + USB2_ADPCTRL );
450+ } else {
451+ val = readl (usb2_base + USB2_VBCTRL );
452+ val &= ~USB2_VBCTRL_OCCLREN ;
453+ writel (val | USB2_VBCTRL_DRVVBUSSEL , usb2_base + USB2_VBCTRL );
454+ val = readl (usb2_base + USB2_ADPCTRL );
455+ writel (val | USB2_ADPCTRL_IDPULLUP , usb2_base + USB2_ADPCTRL );
456+ }
427457 }
428458 mdelay (20 );
429459
@@ -433,6 +463,23 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
433463 rcar_gen3_device_recognition (ch );
434464}
435465
466+ static void rcar_gen3_configure_vblvl_ctrl (struct rcar_gen3_chan * ch )
467+ {
468+ void __iomem * usb2_base = ch -> base ;
469+ u32 val ;
470+
471+ if (!ch -> phy_data -> vblvl_ctrl )
472+ return ;
473+
474+ val = readl (usb2_base + USB2_VBCTRL );
475+ if ((val & USB2_VBCTRL_VBSTA_MASK ) ==
476+ FIELD_PREP_CONST (USB2_VBCTRL_VBSTA_MASK , USB2_VBCTRL_VBSTA_DEFAULT ))
477+ val &= ~USB2_VBCTRL_VBLVL_MASK ;
478+ else
479+ val |= USB2_VBCTRL_VBLVL (USB2_VBCTRL_VBSTA_DEFAULT );
480+ writel (val , usb2_base + USB2_VBCTRL );
481+ }
482+
436483static irqreturn_t rcar_gen3_phy_usb2_irq (int irq , void * _ch )
437484{
438485 struct rcar_gen3_chan * ch = _ch ;
@@ -450,8 +497,12 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
450497 status = readl (usb2_base + USB2_OBINTSTA );
451498 if (status & ch -> phy_data -> obint_enable_bits ) {
452499 dev_vdbg (dev , "%s: %08x\n" , __func__ , status );
453- writel (ch -> phy_data -> obint_enable_bits , usb2_base + USB2_OBINTSTA );
500+ if (ch -> phy_data -> vblvl_ctrl )
501+ writel (USB2_OBINTSTA_CLEAR , usb2_base + USB2_OBINTSTA );
502+ else
503+ writel (ch -> phy_data -> obint_enable_bits , usb2_base + USB2_OBINTSTA );
454504 rcar_gen3_device_recognition (ch );
505+ rcar_gen3_configure_vblvl_ctrl (ch );
455506 ret = IRQ_HANDLED ;
456507 }
457508 }
@@ -484,6 +535,13 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
484535 if (rphy -> int_enable_bits )
485536 rcar_gen3_init_otg (channel );
486537
538+ if (channel -> phy_data -> vblvl_ctrl ) {
539+ /* SIDDQ mode release */
540+ writel (readl (usb2_base + USB2_VBCTRL ) | USB2_VBCTRL_SIDDQREL ,
541+ usb2_base + USB2_VBCTRL );
542+ udelay (250 );
543+ }
544+
487545 if (channel -> phy_data -> utmi_ctrl ) {
488546 val = readl (usb2_base + USB2_REGEN_CG_CTRL ) | USB2_REGEN_CG_CTRL_UPHY_WEN ;
489547 writel (val , usb2_base + USB2_REGEN_CG_CTRL );
@@ -613,6 +671,12 @@ static const struct rcar_gen3_phy_drv_data rz_g3s_phy_usb2_data = {
613671 .obint_enable_bits = USB2_OBINT_IDCHG_EN ,
614672};
615673
674+ static const struct rcar_gen3_phy_drv_data rz_t2h_phy_usb2_data = {
675+ .phy_usb2_ops = & rcar_gen3_phy_usb2_ops ,
676+ .vblvl_ctrl = true,
677+ .obint_enable_bits = USB2_OBINT_IDCHG_EN | USB2_OBINT_VBSTAINT ,
678+ };
679+
616680static const struct rcar_gen3_phy_drv_data rz_v2h_phy_usb2_data = {
617681 .phy_usb2_ops = & rcar_gen3_phy_usb2_ops ,
618682 .no_adp_ctrl = true,
@@ -645,6 +709,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
645709 .compatible = "renesas,usb2-phy-r9a09g057" ,
646710 .data = & rz_v2h_phy_usb2_data ,
647711 },
712+ {
713+ .compatible = "renesas,usb2-phy-r9a09g077" ,
714+ .data = & rz_t2h_phy_usb2_data ,
715+ },
648716 {
649717 .compatible = "renesas,rzg2l-usb2-phy" ,
650718 .data = & rz_g2l_phy_usb2_data ,
0 commit comments