2 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Author: Kamil Debski <k.debski@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/delay.h>
14 #include <linux/phy/phy.h>
15 #include <linux/regmap.h>
16 #include "phy-samsung-usb2.h"
18 /* Exynos USB PHY registers */
19 #define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0
20 #define EXYNOS_5250_REFCLKSEL_XO 0x1
21 #define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2
23 #define EXYNOS_5250_FSEL_9MHZ6 0x0
24 #define EXYNOS_5250_FSEL_10MHZ 0x1
25 #define EXYNOS_5250_FSEL_12MHZ 0x2
26 #define EXYNOS_5250_FSEL_19MHZ2 0x3
27 #define EXYNOS_5250_FSEL_20MHZ 0x4
28 #define EXYNOS_5250_FSEL_24MHZ 0x5
29 #define EXYNOS_5250_FSEL_50MHZ 0x7
32 #define EXYNOS_5250_HOSTPHYCTRL0 0x0
34 #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)
35 #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19
36 #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
37 (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
38 #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16
39 #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
40 (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
41 #define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)
42 #define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)
43 #define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)
44 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)
45 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)
46 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)
47 #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)
48 #define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)
49 #define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)
50 #define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)
51 #define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)
52 #define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)
53 #define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)
54 #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)
57 #define EXYNOS_5250_HSICPHYCTRL1 0x10
58 #define EXYNOS_5250_HSICPHYCTRL2 0x20
60 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)
61 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)
62 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)
63 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)
64 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)
65 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)
66 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)
67 #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)
68 #define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)
69 #define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)
70 #define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)
71 #define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)
72 #define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)
73 #define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)
76 #define EXYNOS_5250_HOSTEHCICTRL 0x30
77 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)
78 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)
79 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)
80 #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)
81 #define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)
82 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19
83 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
84 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
85 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13
86 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
87 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
88 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7
89 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
90 (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
91 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1
92 #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
93 (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
94 #define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)
97 #define EXYNOS_5250_HOSTOHCICTRL 0x34
98 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1
99 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
100 (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
101 #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)
104 #define EXYNOS_5250_USBOTGSYS 0x38
105 #define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)
106 #define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)
107 #define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)
108 #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9
109 #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
110 (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
111 #define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)
112 #define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)
113 #define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4
114 #define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
115 (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
116 #define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)
117 #define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)
118 #define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)
119 #define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)
121 /* Isolation, configured in the power management unit */
122 #define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704
123 #define EXYNOS_5250_USB_ISOL_OTG BIT(0)
124 #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708
125 #define EXYNOS_5250_USB_ISOL_HOST BIT(0)
127 /* Mode swtich register */
128 #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
129 #define EXYNOS_5250_MODE_SWITCH_MASK 1
130 #define EXYNOS_5250_MODE_SWITCH_DEVICE 0
131 #define EXYNOS_5250_MODE_SWITCH_HOST 1
133 enum exynos4x12_phy_id
{
142 * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
143 * can be written to the phy register.
145 static int exynos5250_rate_to_clk(unsigned long rate
, u32
*reg
)
147 /* EXYNOS_5250_FSEL_MASK */
151 *reg
= EXYNOS_5250_FSEL_9MHZ6
;
154 *reg
= EXYNOS_5250_FSEL_10MHZ
;
157 *reg
= EXYNOS_5250_FSEL_12MHZ
;
160 *reg
= EXYNOS_5250_FSEL_19MHZ2
;
163 *reg
= EXYNOS_5250_FSEL_20MHZ
;
166 *reg
= EXYNOS_5250_FSEL_24MHZ
;
169 *reg
= EXYNOS_5250_FSEL_50MHZ
;
178 static void exynos5250_isol(struct samsung_usb2_phy_instance
*inst
, bool on
)
180 struct samsung_usb2_phy_driver
*drv
= inst
->drv
;
184 switch (inst
->cfg
->id
) {
185 case EXYNOS5250_DEVICE
:
186 offset
= EXYNOS_5250_USB_ISOL_OTG_OFFSET
;
187 mask
= EXYNOS_5250_USB_ISOL_OTG
;
189 case EXYNOS5250_HOST
:
190 offset
= EXYNOS_5250_USB_ISOL_HOST_OFFSET
;
191 mask
= EXYNOS_5250_USB_ISOL_HOST
;
197 regmap_update_bits(drv
->reg_pmu
, offset
, mask
, on
? 0 : mask
);
200 static int exynos5250_power_on(struct samsung_usb2_phy_instance
*inst
)
202 struct samsung_usb2_phy_driver
*drv
= inst
->drv
;
209 switch (inst
->cfg
->id
) {
210 case EXYNOS5250_DEVICE
:
211 regmap_update_bits(drv
->reg_sys
,
212 EXYNOS_5250_MODE_SWITCH_OFFSET
,
213 EXYNOS_5250_MODE_SWITCH_MASK
,
214 EXYNOS_5250_MODE_SWITCH_DEVICE
);
216 /* OTG configuration */
217 otg
= readl(drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
219 otg
&= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK
;
220 otg
|= drv
->ref_reg_val
<< EXYNOS_5250_USBOTGSYS_FSEL_SHIFT
;
222 otg
&= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND
|
223 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP
|
224 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG
);
225 otg
|= EXYNOS_5250_USBOTGSYS_PHY_SW_RST
|
226 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET
|
227 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG
|
228 EXYNOS_5250_USBOTGSYS_OTGDISABLE
;
230 otg
&= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK
;
231 otg
|= EXYNOS_5250_REFCLKSEL_CLKCORE
<<
232 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT
;
233 writel(otg
, drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
235 otg
&= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST
|
236 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG
|
237 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET
|
238 EXYNOS_5250_USBOTGSYS_OTGDISABLE
);
239 writel(otg
, drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
243 case EXYNOS5250_HOST
:
244 case EXYNOS5250_HSIC0
:
245 case EXYNOS5250_HSIC1
:
246 /* Host registers configuration */
247 ctrl0
= readl(drv
->reg_phy
+ EXYNOS_5250_HOSTPHYCTRL0
);
249 ctrl0
&= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK
;
250 ctrl0
|= drv
->ref_reg_val
<<
251 EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT
;
254 ctrl0
&= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST
|
255 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL
|
256 EXYNOS_5250_HOSTPHYCTRL0_SIDDQ
|
257 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND
|
258 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP
);
259 ctrl0
|= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST
|
260 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST
|
261 EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N
;
262 writel(ctrl0
, drv
->reg_phy
+ EXYNOS_5250_HOSTPHYCTRL0
);
264 ctrl0
&= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST
|
265 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST
);
266 writel(ctrl0
, drv
->reg_phy
+ EXYNOS_5250_HOSTPHYCTRL0
);
268 /* OTG configuration */
269 otg
= readl(drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
271 otg
&= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK
;
272 otg
|= drv
->ref_reg_val
<< EXYNOS_5250_USBOTGSYS_FSEL_SHIFT
;
274 otg
&= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND
|
275 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP
|
276 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG
);
277 otg
|= EXYNOS_5250_USBOTGSYS_PHY_SW_RST
|
278 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET
|
279 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG
|
280 EXYNOS_5250_USBOTGSYS_OTGDISABLE
;
282 otg
&= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK
;
283 otg
|= EXYNOS_5250_REFCLKSEL_CLKCORE
<<
284 EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT
;
285 writel(otg
, drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
287 otg
&= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST
|
288 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG
|
289 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET
);
291 /* HSIC phy configuration */
292 hsic
= (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12
|
293 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT
|
294 EXYNOS_5250_HSICPHYCTRLX_PHYSWRST
);
295 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL1
);
296 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL2
);
298 hsic
&= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST
;
299 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL1
);
300 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL2
);
301 /* The following delay is necessary for the reset sequence to be
305 /* Enable EHCI DMA burst */
306 ehci
= readl(drv
->reg_phy
+ EXYNOS_5250_HOSTEHCICTRL
);
307 ehci
|= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN
|
308 EXYNOS_5250_HOSTEHCICTRL_ENAINCR4
|
309 EXYNOS_5250_HOSTEHCICTRL_ENAINCR8
|
310 EXYNOS_5250_HOSTEHCICTRL_ENAINCR16
;
311 writel(ehci
, drv
->reg_phy
+ EXYNOS_5250_HOSTEHCICTRL
);
314 ohci
= readl(drv
->reg_phy
+ EXYNOS_5250_HOSTOHCICTRL
);
315 /* Following code is based on the old driver */
317 writel(ohci
, drv
->reg_phy
+ EXYNOS_5250_HOSTOHCICTRL
);
321 exynos5250_isol(inst
, 0);
326 static int exynos5250_power_off(struct samsung_usb2_phy_instance
*inst
)
328 struct samsung_usb2_phy_driver
*drv
= inst
->drv
;
333 exynos5250_isol(inst
, 1);
335 switch (inst
->cfg
->id
) {
336 case EXYNOS5250_DEVICE
:
337 otg
= readl(drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
338 otg
|= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND
|
339 EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG
|
340 EXYNOS_5250_USBOTGSYS_FORCE_SLEEP
);
341 writel(otg
, drv
->reg_phy
+ EXYNOS_5250_USBOTGSYS
);
343 case EXYNOS5250_HOST
:
344 ctrl0
= readl(drv
->reg_phy
+ EXYNOS_5250_HOSTPHYCTRL0
);
345 ctrl0
|= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ
|
346 EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND
|
347 EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP
|
348 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST
|
349 EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL
);
350 writel(ctrl0
, drv
->reg_phy
+ EXYNOS_5250_HOSTPHYCTRL0
);
352 case EXYNOS5250_HSIC0
:
353 case EXYNOS5250_HSIC1
:
354 hsic
= (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12
|
355 EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT
|
356 EXYNOS_5250_HSICPHYCTRLX_SIDDQ
|
357 EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP
|
358 EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
360 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL1
);
361 writel(hsic
, drv
->reg_phy
+ EXYNOS_5250_HSICPHYCTRL2
);
369 static const struct samsung_usb2_common_phy exynos5250_phys
[] = {
372 .id
= EXYNOS5250_DEVICE
,
373 .power_on
= exynos5250_power_on
,
374 .power_off
= exynos5250_power_off
,
378 .id
= EXYNOS5250_HOST
,
379 .power_on
= exynos5250_power_on
,
380 .power_off
= exynos5250_power_off
,
384 .id
= EXYNOS5250_HSIC0
,
385 .power_on
= exynos5250_power_on
,
386 .power_off
= exynos5250_power_off
,
390 .id
= EXYNOS5250_HSIC1
,
391 .power_on
= exynos5250_power_on
,
392 .power_off
= exynos5250_power_off
,
396 const struct samsung_usb2_phy_config exynos5250_usb2_phy_config
= {
397 .has_mode_switch
= 1,
398 .num_phys
= EXYNOS5250_NUM_PHYS
,
399 .phys
= exynos5250_phys
,
400 .rate_to_clk
= exynos5250_rate_to_clk
,