]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/phy/phy-exynos5250-usb2.c
brcmfmac: fix possible buffer overflow in brcmf_cfg80211_mgmt_tx()
[mirror_ubuntu-zesty-kernel.git] / drivers / phy / phy-exynos5250-usb2.c
CommitLineData
64bf2b23
KD
1/*
2 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Author: Kamil Debski <k.debski@samsung.com>
6 *
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.
10 */
11
12#include <linux/delay.h>
13#include <linux/io.h>
14#include <linux/phy/phy.h>
15#include <linux/regmap.h>
16#include "phy-samsung-usb2.h"
17
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
22
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
30
31/* Normal host */
32#define EXYNOS_5250_HOSTPHYCTRL0 0x0
33
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)
55
56/* HSIC0 & HSIC1 */
57#define EXYNOS_5250_HSICPHYCTRL1 0x10
58#define EXYNOS_5250_HSICPHYCTRL2 0x20
59
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)
74
75/* EHCI control */
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)
95
96/* OHCI control */
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)
102
103/* USBOTG */
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)
120
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)
126
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
132
133enum exynos4x12_phy_id {
134 EXYNOS5250_DEVICE,
135 EXYNOS5250_HOST,
136 EXYNOS5250_HSIC0,
137 EXYNOS5250_HSIC1,
138 EXYNOS5250_NUM_PHYS,
139};
140
141/*
142 * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
143 * can be written to the phy register.
144 */
145static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
146{
147 /* EXYNOS_5250_FSEL_MASK */
148
149 switch (rate) {
150 case 9600 * KHZ:
151 *reg = EXYNOS_5250_FSEL_9MHZ6;
152 break;
153 case 10 * MHZ:
154 *reg = EXYNOS_5250_FSEL_10MHZ;
155 break;
156 case 12 * MHZ:
157 *reg = EXYNOS_5250_FSEL_12MHZ;
158 break;
159 case 19200 * KHZ:
160 *reg = EXYNOS_5250_FSEL_19MHZ2;
161 break;
162 case 20 * MHZ:
163 *reg = EXYNOS_5250_FSEL_20MHZ;
164 break;
165 case 24 * MHZ:
166 *reg = EXYNOS_5250_FSEL_24MHZ;
167 break;
168 case 50 * MHZ:
169 *reg = EXYNOS_5250_FSEL_50MHZ;
170 break;
171 default:
172 return -EINVAL;
173 }
174
175 return 0;
176}
177
178static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
179{
180 struct samsung_usb2_phy_driver *drv = inst->drv;
181 u32 offset;
182 u32 mask;
183
184 switch (inst->cfg->id) {
185 case EXYNOS5250_DEVICE:
186 offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
187 mask = EXYNOS_5250_USB_ISOL_OTG;
188 break;
189 case EXYNOS5250_HOST:
190 offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
191 mask = EXYNOS_5250_USB_ISOL_HOST;
192 break;
193 default:
194 return;
0e65ba28 195 }
64bf2b23
KD
196
197 regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
198}
199
200static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
201{
202 struct samsung_usb2_phy_driver *drv = inst->drv;
203 u32 ctrl0;
204 u32 otg;
205 u32 ehci;
206 u32 ohci;
207 u32 hsic;
208
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);
215
216 /* OTG configuration */
217 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
218 /* The clock */
219 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
220 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
221 /* Reset */
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;
229 /* Ref clock */
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);
234 udelay(100);
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);
240
241
242 break;
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);
248 /* The clock */
249 ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
250 ctrl0 |= drv->ref_reg_val <<
251 EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
252
253 /* Reset */
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);
263 udelay(10);
264 ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
265 EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
266 writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
267
268 /* OTG configuration */
269 otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
270 /* The clock */
271 otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
272 otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
273 /* Reset */
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;
281 /* Ref clock */
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);
286 udelay(10);
287 otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
288 EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
289 EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
290
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);
297 udelay(10);
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
302 * completed */
303 udelay(80);
304
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);
312
313 /* OHCI settings */
314 ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
315 /* Following code is based on the old driver */
316 ohci |= 0x1 << 3;
317 writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
318
319 break;
320 }
64bf2b23
KD
321 exynos5250_isol(inst, 0);
322
323 return 0;
324}
325
326static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
327{
328 struct samsung_usb2_phy_driver *drv = inst->drv;
329 u32 ctrl0;
330 u32 otg;
331 u32 hsic;
332
64bf2b23
KD
333 exynos5250_isol(inst, 1);
334
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);
342 break;
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);
351 break;
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
359 );
360 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
361 writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
362 break;
363 }
364
365 return 0;
366}
367
368
369static const struct samsung_usb2_common_phy exynos5250_phys[] = {
370 {
371 .label = "device",
372 .id = EXYNOS5250_DEVICE,
373 .power_on = exynos5250_power_on,
374 .power_off = exynos5250_power_off,
375 },
376 {
377 .label = "host",
378 .id = EXYNOS5250_HOST,
379 .power_on = exynos5250_power_on,
380 .power_off = exynos5250_power_off,
381 },
382 {
383 .label = "hsic0",
384 .id = EXYNOS5250_HSIC0,
385 .power_on = exynos5250_power_on,
386 .power_off = exynos5250_power_off,
387 },
388 {
389 .label = "hsic1",
390 .id = EXYNOS5250_HSIC1,
391 .power_on = exynos5250_power_on,
392 .power_off = exynos5250_power_off,
393 },
64bf2b23
KD
394};
395
396const 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,
401};