blob: b278f995f373e3edb4e22f3b6a454b0ca858c319 [file] [log] [blame]
Marek Vasutc31c4b12018-10-02 22:31:47 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Renesas RCar Gen3 USB PHY driver
4 *
5 * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
6 */
7
Marek Vasutc31c4b12018-10-02 22:31:47 +02008#include <clk.h>
9#include <div64.h>
10#include <dm.h>
Marek Vasute4b53162024-09-08 23:09:04 +020011#include <dm/device_compat.h>
Marek Vasutc31c4b12018-10-02 22:31:47 +020012#include <fdtdec.h>
13#include <generic-phy.h>
Simon Glass9bc15642020-02-03 07:36:16 -070014#include <malloc.h>
Marek Vasutc31c4b12018-10-02 22:31:47 +020015#include <reset.h>
16#include <syscon.h>
17#include <usb.h>
18#include <asm/io.h>
19#include <linux/bitops.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060020#include <linux/printk.h>
Marek Vasutc31c4b12018-10-02 22:31:47 +020021#include <power/regulator.h>
22
23/* USB2.0 Host registers (original offset is +0x200) */
24#define USB2_INT_ENABLE 0x000
25#define USB2_USBCTR 0x00c
26#define USB2_SPD_RSM_TIMSET 0x10c
27#define USB2_OC_TIMSET 0x110
28#define USB2_COMMCTRL 0x600
29#define USB2_OBINTSTA 0x604
30#define USB2_OBINTEN 0x608
31#define USB2_VBCTRL 0x60c
32#define USB2_LINECTRL1 0x610
33#define USB2_ADPCTRL 0x630
34
Marek Vasute4b53162024-09-08 23:09:04 +020035/* INT_ENABLE */
36#define USB2_INT_ENABLE_UCOM_INTEN BIT(3)
37#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2)
38#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1)
39
Marek Vasutc31c4b12018-10-02 22:31:47 +020040/* USBCTR */
Marek Vasute4b53162024-09-08 23:09:04 +020041#define USB2_USBCTR_PLL_RST BIT(1)
Marek Vasutc31c4b12018-10-02 22:31:47 +020042
43/* SPD_RSM_TIMSET */
44#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b
45
46/* OC_TIMSET */
47#define USB2_OC_TIMSET_INIT 0x000209ab
48
49/* COMMCTRL */
50#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
51
Marek Vasute4b53162024-09-08 23:09:04 +020052/* OBINTSTA and OBINTEN */
53#define USB2_OBINT_SESSVLDCHG BIT(12)
54#define USB2_OBINT_IDDIGCHG BIT(11)
55
56/* VBCTRL */
57#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
58
Marek Vasutc31c4b12018-10-02 22:31:47 +020059/* LINECTRL1 */
Marek Vasute4b53162024-09-08 23:09:04 +020060#define USB2_LINECTRL1_DPRPD_EN BIT(19)
Marek Vasutc31c4b12018-10-02 22:31:47 +020061#define USB2_LINECTRL1_DP_RPD BIT(18)
Marek Vasute4b53162024-09-08 23:09:04 +020062#define USB2_LINECTRL1_DMRPD_EN BIT(17)
Marek Vasutc31c4b12018-10-02 22:31:47 +020063#define USB2_LINECTRL1_DM_RPD BIT(16)
64
65/* ADPCTRL */
Marek Vasute4b53162024-09-08 23:09:04 +020066#define USB2_ADPCTRL_OTGSESSVLD BIT(20)
67#define USB2_ADPCTRL_IDDIG BIT(19)
68#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
Marek Vasutc31c4b12018-10-02 22:31:47 +020069#define USB2_ADPCTRL_DRVVBUS BIT(4)
70
71struct rcar_gen3_phy {
72 fdt_addr_t regs;
73 struct clk clk;
74 struct udevice *vbus_supply;
75};
76
77static int rcar_gen3_phy_phy_init(struct phy *phy)
78{
79 struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
80
81 /* Initialize USB2 part */
82 writel(0, priv->regs + USB2_INT_ENABLE);
83 writel(USB2_SPD_RSM_TIMSET_INIT, priv->regs + USB2_SPD_RSM_TIMSET);
84 writel(USB2_OC_TIMSET_INIT, priv->regs + USB2_OC_TIMSET);
85
Marek Vasute4b53162024-09-08 23:09:04 +020086 return 0;
87}
Marek Vasutc31c4b12018-10-02 22:31:47 +020088
Marek Vasute4b53162024-09-08 23:09:04 +020089static int rcar_gen3_phy_phy_exit(struct phy *phy)
90{
91 struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
Marek Vasutc31c4b12018-10-02 22:31:47 +020092
Marek Vasute4b53162024-09-08 23:09:04 +020093 writel(0, priv->regs + USB2_INT_ENABLE);
Marek Vasutc31c4b12018-10-02 22:31:47 +020094
95 return 0;
96}
97
98static int rcar_gen3_phy_phy_power_on(struct phy *phy)
99{
100 struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
101 int ret;
102
103 if (priv->vbus_supply) {
104 ret = regulator_set_enable(priv->vbus_supply, true);
105 if (ret)
106 return ret;
107 }
108
109 setbits_le32(priv->regs + USB2_USBCTR, USB2_USBCTR_PLL_RST);
110 clrbits_le32(priv->regs + USB2_USBCTR, USB2_USBCTR_PLL_RST);
111
112 return 0;
113}
114
115static int rcar_gen3_phy_phy_power_off(struct phy *phy)
116{
117 struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
118
119 if (!priv->vbus_supply)
120 return 0;
121
122 return regulator_set_enable(priv->vbus_supply, false);
123}
124
Marek Vasute4b53162024-09-08 23:09:04 +0200125static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode,
126 int submode)
127{
128 const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD;
129 struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
130 u32 adpctrl;
131
132 if (mode == PHY_MODE_USB_OTG) {
133 if (submode) {
134 /* OTG submode is used as initialization indicator */
135 writel(USB2_INT_ENABLE_UCOM_INTEN |
136 USB2_INT_ENABLE_USBH_INTB_EN |
137 USB2_INT_ENABLE_USBH_INTA_EN,
138 priv->regs + USB2_INT_ENABLE);
139 setbits_le32(priv->regs + USB2_VBCTRL,
140 USB2_VBCTRL_DRVVBUSSEL);
141 writel(USB2_OBINT_SESSVLDCHG | USB2_OBINT_IDDIGCHG,
142 priv->regs + USB2_OBINTSTA);
143 setbits_le32(priv->regs + USB2_OBINTEN,
144 USB2_OBINT_SESSVLDCHG |
145 USB2_OBINT_IDDIGCHG);
146 setbits_le32(priv->regs + USB2_ADPCTRL,
147 USB2_ADPCTRL_IDPULLUP);
148 clrsetbits_le32(priv->regs + USB2_LINECTRL1,
149 USB2_LINECTRL1_DP_RPD |
150 USB2_LINECTRL1_DM_RPD |
151 USB2_LINECTRL1_DPRPD_EN |
152 USB2_LINECTRL1_DMRPD_EN,
153 USB2_LINECTRL1_DPRPD_EN |
154 USB2_LINECTRL1_DMRPD_EN);
155 }
156
157 adpctrl = readl(priv->regs + USB2_ADPCTRL);
158 if ((adpctrl & adpdevmask) == adpdevmask)
159 mode = PHY_MODE_USB_DEVICE;
160 else
161 mode = PHY_MODE_USB_HOST;
162 }
163
164 if (mode == PHY_MODE_USB_HOST) {
165 clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
166 setbits_le32(priv->regs + USB2_LINECTRL1,
167 USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
168 setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
169 } else if (mode == PHY_MODE_USB_DEVICE) {
170 setbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
171 clrsetbits_le32(priv->regs + USB2_LINECTRL1,
172 USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD,
173 USB2_LINECTRL1_DM_RPD);
174 clrbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
175 } else {
176 dev_err(phy->dev, "Unknown mode %d\n", mode);
177 return -EINVAL;
178 }
179
180 return 0;
181}
182
Marek Vasutc31c4b12018-10-02 22:31:47 +0200183static const struct phy_ops rcar_gen3_phy_phy_ops = {
184 .init = rcar_gen3_phy_phy_init,
Marek Vasute4b53162024-09-08 23:09:04 +0200185 .exit = rcar_gen3_phy_phy_exit,
Marek Vasutc31c4b12018-10-02 22:31:47 +0200186 .power_on = rcar_gen3_phy_phy_power_on,
187 .power_off = rcar_gen3_phy_phy_power_off,
Marek Vasute4b53162024-09-08 23:09:04 +0200188 .set_mode = rcar_gen3_phy_phy_set_mode,
Marek Vasutc31c4b12018-10-02 22:31:47 +0200189};
190
191static int rcar_gen3_phy_probe(struct udevice *dev)
192{
193 struct rcar_gen3_phy *priv = dev_get_priv(dev);
194 int ret;
195
196 priv->regs = dev_read_addr(dev);
197 if (priv->regs == FDT_ADDR_T_NONE)
198 return -EINVAL;
199
200 ret = device_get_supply_regulator(dev, "vbus-supply",
201 &priv->vbus_supply);
202 if (ret && ret != -ENOENT) {
203 pr_err("Failed to get PHY regulator\n");
204 return ret;
205 }
206
207 /* Enable clock */
208 ret = clk_get_by_index(dev, 0, &priv->clk);
209 if (ret)
210 return ret;
211
212 ret = clk_enable(&priv->clk);
213 if (ret)
214 return ret;
215
216 return 0;
217}
218
219static int rcar_gen3_phy_remove(struct udevice *dev)
220{
221 struct rcar_gen3_phy *priv = dev_get_priv(dev);
222
223 clk_disable(&priv->clk);
Marek Vasutc31c4b12018-10-02 22:31:47 +0200224
225 return 0;
226}
227
228static const struct udevice_id rcar_gen3_phy_of_match[] = {
229 { .compatible = "renesas,rcar-gen3-usb2-phy", },
230 { },
231};
232
233U_BOOT_DRIVER(rcar_gen3_phy) = {
234 .name = "rcar-gen3-phy",
235 .id = UCLASS_PHY,
236 .of_match = rcar_gen3_phy_of_match,
237 .ops = &rcar_gen3_phy_phy_ops,
238 .probe = rcar_gen3_phy_probe,
239 .remove = rcar_gen3_phy_remove,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700240 .priv_auto = sizeof(struct rcar_gen3_phy),
Marek Vasutc31c4b12018-10-02 22:31:47 +0200241};