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

phy: rcar-gen3-usb2: change the mode to OTG on the combined channel

To use the channel 0 of R-Car gen3 as periperal mode, This patch changes
the mode to OTG instead of HOST. Then, this driver needs to set some
registers to enable host mode and detects ID pin and VBUS pin at
phy_init() timing.

For now, the channel 0 can be used as host mode only.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Yoshihiro Shimoda and committed by
Kishon Vijay Abraham I
1114e2d3 f3b5a8d9

+122 -2
+122 -2
drivers/phy/phy-rcar-gen3-usb2.c
··· 24 24 #define USB2_USBCTR 0x00c 25 25 #define USB2_SPD_RSM_TIMSET 0x10c 26 26 #define USB2_OC_TIMSET 0x110 27 + #define USB2_COMMCTRL 0x600 28 + #define USB2_VBCTRL 0x60c 29 + #define USB2_LINECTRL1 0x610 30 + #define USB2_ADPCTRL 0x630 27 31 28 32 /* INT_ENABLE */ 29 33 #define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) ··· 44 40 45 41 /* OC_TIMSET */ 46 42 #define USB2_OC_TIMSET_INIT 0x000209ab 43 + 44 + /* COMMCTRL */ 45 + #define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */ 46 + 47 + /* VBCTRL */ 48 + #define USB2_VBCTRL_DRVVBUSSEL BIT(8) 49 + 50 + /* LINECTRL1 */ 51 + #define USB2_LINECTRL1_DPRPD_EN BIT(19) 52 + #define USB2_LINECTRL1_DP_RPD BIT(18) 53 + #define USB2_LINECTRL1_DMRPD_EN BIT(17) 54 + #define USB2_LINECTRL1_DM_RPD BIT(16) 55 + 56 + /* ADPCTRL */ 57 + #define USB2_ADPCTRL_OTGSESSVLD BIT(20) 58 + #define USB2_ADPCTRL_IDDIG BIT(19) 59 + #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ 60 + #define USB2_ADPCTRL_DRVVBUS BIT(4) 47 61 48 62 /******* HSUSB registers (original offset is +0x100) *******/ 49 63 #define HSUSB_LPSTS 0x02 ··· 88 66 struct phy *phy; 89 67 }; 90 68 69 + static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) 70 + { 71 + void __iomem *usb2_base = ch->usb2.base; 72 + u32 val = readl(usb2_base + USB2_COMMCTRL); 73 + 74 + dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, host); 75 + if (host) 76 + val &= ~USB2_COMMCTRL_OTG_PERI; 77 + else 78 + val |= USB2_COMMCTRL_OTG_PERI; 79 + writel(val, usb2_base + USB2_COMMCTRL); 80 + } 81 + 82 + static void rcar_gen3_set_linectrl(struct rcar_gen3_chan *ch, int dp, int dm) 83 + { 84 + void __iomem *usb2_base = ch->usb2.base; 85 + u32 val = readl(usb2_base + USB2_LINECTRL1); 86 + 87 + dev_vdbg(&ch->phy->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); 88 + val &= ~(USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); 89 + if (dp) 90 + val |= USB2_LINECTRL1_DP_RPD; 91 + if (dm) 92 + val |= USB2_LINECTRL1_DM_RPD; 93 + writel(val, usb2_base + USB2_LINECTRL1); 94 + } 95 + 96 + static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus) 97 + { 98 + void __iomem *usb2_base = ch->usb2.base; 99 + u32 val = readl(usb2_base + USB2_ADPCTRL); 100 + 101 + dev_vdbg(&ch->phy->dev, "%s: %08x, %d\n", __func__, val, vbus); 102 + if (vbus) 103 + val |= USB2_ADPCTRL_DRVVBUS; 104 + else 105 + val &= ~USB2_ADPCTRL_DRVVBUS; 106 + writel(val, usb2_base + USB2_ADPCTRL); 107 + } 108 + 109 + static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) 110 + { 111 + rcar_gen3_set_linectrl(ch, 1, 1); 112 + rcar_gen3_set_host_mode(ch, 1); 113 + rcar_gen3_enable_vbus_ctrl(ch, 1); 114 + } 115 + 116 + static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) 117 + { 118 + rcar_gen3_set_linectrl(ch, 0, 1); 119 + rcar_gen3_set_host_mode(ch, 0); 120 + rcar_gen3_enable_vbus_ctrl(ch, 0); 121 + } 122 + 123 + static bool rcar_gen3_check_vbus(struct rcar_gen3_chan *ch) 124 + { 125 + return !!(readl(ch->usb2.base + USB2_ADPCTRL) & 126 + USB2_ADPCTRL_OTGSESSVLD); 127 + } 128 + 129 + static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) 130 + { 131 + return !!(readl(ch->usb2.base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); 132 + } 133 + 134 + static void rcar_gen3_device_recognition(struct rcar_gen3_chan *ch) 135 + { 136 + bool is_host = true; 137 + 138 + /* B-device? */ 139 + if (rcar_gen3_check_id(ch) && rcar_gen3_check_vbus(ch)) 140 + is_host = false; 141 + 142 + if (is_host) 143 + rcar_gen3_init_for_host(ch); 144 + else 145 + rcar_gen3_init_for_peri(ch); 146 + } 147 + 148 + static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) 149 + { 150 + void __iomem *usb2_base = ch->usb2.base; 151 + u32 val; 152 + 153 + val = readl(usb2_base + USB2_VBCTRL); 154 + writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); 155 + val = readl(usb2_base + USB2_ADPCTRL); 156 + writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); 157 + val = readl(usb2_base + USB2_LINECTRL1); 158 + rcar_gen3_set_linectrl(ch, 0, 0); 159 + writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN, 160 + usb2_base + USB2_LINECTRL1); 161 + 162 + rcar_gen3_device_recognition(ch); 163 + } 164 + 91 165 static int rcar_gen3_phy_usb2_init(struct phy *p) 92 166 { 93 167 struct rcar_gen3_chan *channel = phy_get_drvdata(p); ··· 198 80 199 81 /* Initialize HSUSB part */ 200 82 if (hsusb_base) { 201 - /* TODO: support "OTG" mode */ 202 83 val = readl(hsusb_base + HSUSB_UGCTRL2); 203 84 val = (val & ~HSUSB_UGCTRL2_USB0SEL) | 204 - HSUSB_UGCTRL2_USB0SEL_HOST; 85 + HSUSB_UGCTRL2_USB0SEL_OTG; 205 86 writel(val & HSUSB_UGCTRL2_MASK, hsusb_base + HSUSB_UGCTRL2); 87 + 88 + /* Initialize otg part */ 89 + rcar_gen3_init_otg(channel); 206 90 } 207 91 208 92 return 0;