usb: phy: rename all phy drivers to phy-$name-usb.c
[deliverable/linux.git] / drivers / usb / phy / phy-samsung-usb.c
1 /* linux/drivers/usb/phy/samsung-usbphy.c
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 *
6 * Author: Praveen Paneri <p.paneri@samsung.com>
7 *
8 * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
9 * OHCI-EXYNOS controllers.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/clk.h>
24 #include <linux/delay.h>
25 #include <linux/device.h>
26 #include <linux/err.h>
27 #include <linux/io.h>
28 #include <linux/of.h>
29 #include <linux/of_address.h>
30 #include <linux/usb/otg.h>
31 #include <linux/usb/samsung_usb_phy.h>
32 #include <linux/platform_data/samsung-usbphy.h>
33
34 /* Register definitions */
35
36 #define SAMSUNG_PHYPWR (0x00)
37
38 #define PHYPWR_NORMAL_MASK (0x19 << 0)
39 #define PHYPWR_OTG_DISABLE (0x1 << 4)
40 #define PHYPWR_ANALOG_POWERDOWN (0x1 << 3)
41 #define PHYPWR_FORCE_SUSPEND (0x1 << 1)
42 /* For Exynos4 */
43 #define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0)
44 #define PHYPWR_SLEEP_PHY0 (0x1 << 5)
45
46 #define SAMSUNG_PHYCLK (0x04)
47
48 #define PHYCLK_MODE_USB11 (0x1 << 6)
49 #define PHYCLK_EXT_OSC (0x1 << 5)
50 #define PHYCLK_COMMON_ON_N (0x1 << 4)
51 #define PHYCLK_ID_PULL (0x1 << 2)
52 #define PHYCLK_CLKSEL_MASK (0x3 << 0)
53 #define PHYCLK_CLKSEL_48M (0x0 << 0)
54 #define PHYCLK_CLKSEL_12M (0x2 << 0)
55 #define PHYCLK_CLKSEL_24M (0x3 << 0)
56
57 #define SAMSUNG_RSTCON (0x08)
58
59 #define RSTCON_PHYLINK_SWRST (0x1 << 2)
60 #define RSTCON_HLINK_SWRST (0x1 << 1)
61 #define RSTCON_SWRST (0x1 << 0)
62
63 /* EXYNOS5 */
64 #define EXYNOS5_PHY_HOST_CTRL0 (0x00)
65
66 #define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
67
68 #define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19)
69 #define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19)
70 #define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19)
71 #define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19)
72
73 #define HOST_CTRL0_FSEL_MASK (0x7 << 16)
74 #define HOST_CTRL0_FSEL(_x) ((_x) << 16)
75
76 #define FSEL_CLKSEL_50M (0x7)
77 #define FSEL_CLKSEL_24M (0x5)
78 #define FSEL_CLKSEL_20M (0x4)
79 #define FSEL_CLKSEL_19200K (0x3)
80 #define FSEL_CLKSEL_12M (0x2)
81 #define FSEL_CLKSEL_10M (0x1)
82 #define FSEL_CLKSEL_9600K (0x0)
83
84 #define HOST_CTRL0_TESTBURNIN (0x1 << 11)
85 #define HOST_CTRL0_RETENABLE (0x1 << 10)
86 #define HOST_CTRL0_COMMONON_N (0x1 << 9)
87 #define HOST_CTRL0_SIDDQ (0x1 << 6)
88 #define HOST_CTRL0_FORCESLEEP (0x1 << 5)
89 #define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
90 #define HOST_CTRL0_WORDINTERFACE (0x1 << 3)
91 #define HOST_CTRL0_UTMISWRST (0x1 << 2)
92 #define HOST_CTRL0_LINKSWRST (0x1 << 1)
93 #define HOST_CTRL0_PHYSWRST (0x1 << 0)
94
95 #define EXYNOS5_PHY_HOST_TUNE0 (0x04)
96
97 #define EXYNOS5_PHY_HSIC_CTRL1 (0x10)
98
99 #define EXYNOS5_PHY_HSIC_TUNE1 (0x14)
100
101 #define EXYNOS5_PHY_HSIC_CTRL2 (0x20)
102
103 #define EXYNOS5_PHY_HSIC_TUNE2 (0x24)
104
105 #define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23)
106 #define HSIC_CTRL_REFCLKSEL (0x2 << 23)
107
108 #define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16)
109 #define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16)
110 #define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16)
111 #define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16)
112 #define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16)
113 #define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16)
114 #define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16)
115
116 #define HSIC_CTRL_SIDDQ (0x1 << 6)
117 #define HSIC_CTRL_FORCESLEEP (0x1 << 5)
118 #define HSIC_CTRL_FORCESUSPEND (0x1 << 4)
119 #define HSIC_CTRL_WORDINTERFACE (0x1 << 3)
120 #define HSIC_CTRL_UTMISWRST (0x1 << 2)
121 #define HSIC_CTRL_PHYSWRST (0x1 << 0)
122
123 #define EXYNOS5_PHY_HOST_EHCICTRL (0x30)
124
125 #define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29)
126 #define HOST_EHCICTRL_ENAINCR4 (0x1 << 28)
127 #define HOST_EHCICTRL_ENAINCR8 (0x1 << 27)
128 #define HOST_EHCICTRL_ENAINCR16 (0x1 << 26)
129
130 #define EXYNOS5_PHY_HOST_OHCICTRL (0x34)
131
132 #define HOST_OHCICTRL_SUSPLGCY (0x1 << 3)
133 #define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2)
134 #define HOST_OHCICTRL_CNTSEL (0x1 << 1)
135 #define HOST_OHCICTRL_CLKCKTRST (0x1 << 0)
136
137 #define EXYNOS5_PHY_OTG_SYS (0x38)
138
139 #define OTG_SYS_PHYLINK_SWRESET (0x1 << 14)
140 #define OTG_SYS_LINKSWRST_UOTG (0x1 << 13)
141 #define OTG_SYS_PHY0_SWRST (0x1 << 12)
142
143 #define OTG_SYS_REFCLKSEL_MASK (0x3 << 9)
144 #define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9)
145 #define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9)
146 #define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9)
147
148 #define OTG_SYS_IDPULLUP_UOTG (0x1 << 8)
149 #define OTG_SYS_COMMON_ON (0x1 << 7)
150
151 #define OTG_SYS_FSEL_MASK (0x7 << 4)
152 #define OTG_SYS_FSEL(_x) ((_x) << 4)
153
154 #define OTG_SYS_FORCESLEEP (0x1 << 3)
155 #define OTG_SYS_OTGDISABLE (0x1 << 2)
156 #define OTG_SYS_SIDDQ_UOTG (0x1 << 1)
157 #define OTG_SYS_FORCESUSPEND (0x1 << 0)
158
159 #define EXYNOS5_PHY_OTG_TUNE (0x40)
160
161 #ifndef MHZ
162 #define MHZ (1000*1000)
163 #endif
164
165 #ifndef KHZ
166 #define KHZ (1000)
167 #endif
168
169 #define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4)
170 #define S3C64XX_USBPHY_ENABLE (0x1 << 16)
171 #define EXYNOS_USBPHY_ENABLE (0x1 << 0)
172 #define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0)
173
174 enum samsung_cpu_type {
175 TYPE_S3C64XX,
176 TYPE_EXYNOS4210,
177 TYPE_EXYNOS5250,
178 };
179
180 /*
181 * struct samsung_usbphy_drvdata - driver data for various SoC variants
182 * @cpu_type: machine identifier
183 * @devphy_en_mask: device phy enable mask for PHY CONTROL register
184 * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
185 * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
186 * mapped address of system controller.
187 * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
188 * mapped address of system controller.
189 *
190 * Here we have a separate mask for device type phy.
191 * Having different masks for host and device type phy helps
192 * in setting independent masks in case of SoCs like S5PV210,
193 * in which PHY0 and PHY1 enable bits belong to same register
194 * placed at position 0 and 1 respectively.
195 * Although for newer SoCs like exynos these bits belong to
196 * different registers altogether placed at position 0.
197 */
198 struct samsung_usbphy_drvdata {
199 int cpu_type;
200 int devphy_en_mask;
201 int hostphy_en_mask;
202 u32 devphy_reg_offset;
203 u32 hostphy_reg_offset;
204 };
205
206 /*
207 * struct samsung_usbphy - transceiver driver state
208 * @phy: transceiver structure
209 * @plat: platform data
210 * @dev: The parent device supplied to the probe function
211 * @clk: usb phy clock
212 * @regs: usb phy controller registers memory base
213 * @pmuregs: USB device PHY_CONTROL register memory base
214 * @sysreg: USB2.0 PHY_CFG register memory base
215 * @ref_clk_freq: reference clock frequency selection
216 * @drv_data: driver data available for different SoCs
217 * @phy_type: Samsung SoCs specific phy types: #HOST
218 * #DEVICE
219 * @phy_usage: usage count for phy
220 * @lock: lock for phy operations
221 */
222 struct samsung_usbphy {
223 struct usb_phy phy;
224 struct samsung_usbphy_data *plat;
225 struct device *dev;
226 struct clk *clk;
227 void __iomem *regs;
228 void __iomem *pmuregs;
229 void __iomem *sysreg;
230 int ref_clk_freq;
231 const struct samsung_usbphy_drvdata *drv_data;
232 enum samsung_usb_phy_type phy_type;
233 atomic_t phy_usage;
234 spinlock_t lock;
235 };
236
237 #define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
238
239 int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
240 {
241 if (!otg)
242 return -ENODEV;
243
244 if (!otg->host)
245 otg->host = host;
246
247 return 0;
248 }
249
250 static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
251 {
252 struct device_node *usbphy_sys;
253
254 /* Getting node for system controller interface for usb-phy */
255 usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
256 if (!usbphy_sys) {
257 dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
258 return -ENODEV;
259 }
260
261 sphy->pmuregs = of_iomap(usbphy_sys, 0);
262
263 if (sphy->pmuregs == NULL) {
264 dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
265 goto err0;
266 }
267
268 sphy->sysreg = of_iomap(usbphy_sys, 1);
269
270 /*
271 * Not returning error code here, since this situation is not fatal.
272 * Few SoCs may not have this switch available
273 */
274 if (sphy->sysreg == NULL)
275 dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
276
277 of_node_put(usbphy_sys);
278
279 return 0;
280
281 err0:
282 of_node_put(usbphy_sys);
283 return -ENXIO;
284 }
285
286 /*
287 * Set isolation here for phy.
288 * Here 'on = true' would mean USB PHY block is isolated, hence
289 * de-activated and vice-versa.
290 */
291 static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
292 {
293 void __iomem *reg = NULL;
294 u32 reg_val;
295 u32 en_mask = 0;
296
297 if (!sphy->pmuregs) {
298 dev_warn(sphy->dev, "Can't set pmu isolation\n");
299 return;
300 }
301
302 switch (sphy->drv_data->cpu_type) {
303 case TYPE_S3C64XX:
304 /*
305 * Do nothing: We will add here once S3C64xx goes for DT support
306 */
307 break;
308 case TYPE_EXYNOS4210:
309 /*
310 * Fall through since exynos4210 and exynos5250 have similar
311 * register architecture: two separate registers for host and
312 * device phy control with enable bit at position 0.
313 */
314 case TYPE_EXYNOS5250:
315 if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
316 reg = sphy->pmuregs +
317 sphy->drv_data->devphy_reg_offset;
318 en_mask = sphy->drv_data->devphy_en_mask;
319 } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
320 reg = sphy->pmuregs +
321 sphy->drv_data->hostphy_reg_offset;
322 en_mask = sphy->drv_data->hostphy_en_mask;
323 }
324 break;
325 default:
326 dev_err(sphy->dev, "Invalid SoC type\n");
327 return;
328 }
329
330 reg_val = readl(reg);
331
332 if (on)
333 reg_val &= ~en_mask;
334 else
335 reg_val |= en_mask;
336
337 writel(reg_val, reg);
338 }
339
340 /*
341 * Configure the mode of working of usb-phy here: HOST/DEVICE.
342 */
343 static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
344 {
345 u32 reg;
346
347 if (!sphy->sysreg) {
348 dev_warn(sphy->dev, "Can't configure specified phy mode\n");
349 return;
350 }
351
352 reg = readl(sphy->sysreg);
353
354 if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
355 reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
356 else if (sphy->phy_type == USB_PHY_TYPE_HOST)
357 reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
358
359 writel(reg, sphy->sysreg);
360 }
361
362 /*
363 * PHYs are different for USB Device and USB Host.
364 * This make sure that correct PHY type is selected before
365 * any operation on PHY.
366 */
367 static int samsung_usbphy_set_type(struct usb_phy *phy,
368 enum samsung_usb_phy_type phy_type)
369 {
370 struct samsung_usbphy *sphy = phy_to_sphy(phy);
371
372 sphy->phy_type = phy_type;
373
374 return 0;
375 }
376
377 /*
378 * Returns reference clock frequency selection value
379 */
380 static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
381 {
382 struct clk *ref_clk;
383 int refclk_freq = 0;
384
385 /*
386 * In exynos5250 USB host and device PHY use
387 * external crystal clock XXTI
388 */
389 if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
390 ref_clk = clk_get(sphy->dev, "ext_xtal");
391 else
392 ref_clk = clk_get(sphy->dev, "xusbxti");
393 if (IS_ERR(ref_clk)) {
394 dev_err(sphy->dev, "Failed to get reference clock\n");
395 return PTR_ERR(ref_clk);
396 }
397
398 if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
399 /* set clock frequency for PLL */
400 switch (clk_get_rate(ref_clk)) {
401 case 9600 * KHZ:
402 refclk_freq = FSEL_CLKSEL_9600K;
403 break;
404 case 10 * MHZ:
405 refclk_freq = FSEL_CLKSEL_10M;
406 break;
407 case 12 * MHZ:
408 refclk_freq = FSEL_CLKSEL_12M;
409 break;
410 case 19200 * KHZ:
411 refclk_freq = FSEL_CLKSEL_19200K;
412 break;
413 case 20 * MHZ:
414 refclk_freq = FSEL_CLKSEL_20M;
415 break;
416 case 50 * MHZ:
417 refclk_freq = FSEL_CLKSEL_50M;
418 break;
419 case 24 * MHZ:
420 default:
421 /* default reference clock */
422 refclk_freq = FSEL_CLKSEL_24M;
423 break;
424 }
425 } else {
426 switch (clk_get_rate(ref_clk)) {
427 case 12 * MHZ:
428 refclk_freq = PHYCLK_CLKSEL_12M;
429 break;
430 case 24 * MHZ:
431 refclk_freq = PHYCLK_CLKSEL_24M;
432 break;
433 case 48 * MHZ:
434 refclk_freq = PHYCLK_CLKSEL_48M;
435 break;
436 default:
437 if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
438 refclk_freq = PHYCLK_CLKSEL_48M;
439 else
440 refclk_freq = PHYCLK_CLKSEL_24M;
441 break;
442 }
443 }
444 clk_put(ref_clk);
445
446 return refclk_freq;
447 }
448
449 static bool exynos5_phyhost_is_on(void *regs)
450 {
451 u32 reg;
452
453 reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
454
455 return !(reg & HOST_CTRL0_SIDDQ);
456 }
457
458 static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
459 {
460 void __iomem *regs = sphy->regs;
461 u32 phyclk = sphy->ref_clk_freq;
462 u32 phyhost;
463 u32 phyotg;
464 u32 phyhsic;
465 u32 ehcictrl;
466 u32 ohcictrl;
467
468 /*
469 * phy_usage helps in keeping usage count for phy
470 * so that the first consumer enabling the phy is also
471 * the last consumer to disable it.
472 */
473
474 atomic_inc(&sphy->phy_usage);
475
476 if (exynos5_phyhost_is_on(regs)) {
477 dev_info(sphy->dev, "Already power on PHY\n");
478 return;
479 }
480
481 /* Host configuration */
482 phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
483
484 /* phy reference clock configuration */
485 phyhost &= ~HOST_CTRL0_FSEL_MASK;
486 phyhost |= HOST_CTRL0_FSEL(phyclk);
487
488 /* host phy reset */
489 phyhost &= ~(HOST_CTRL0_PHYSWRST |
490 HOST_CTRL0_PHYSWRSTALL |
491 HOST_CTRL0_SIDDQ |
492 /* Enable normal mode of operation */
493 HOST_CTRL0_FORCESUSPEND |
494 HOST_CTRL0_FORCESLEEP);
495
496 /* Link reset */
497 phyhost |= (HOST_CTRL0_LINKSWRST |
498 HOST_CTRL0_UTMISWRST |
499 /* COMMON Block configuration during suspend */
500 HOST_CTRL0_COMMONON_N);
501 writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
502 udelay(10);
503 phyhost &= ~(HOST_CTRL0_LINKSWRST |
504 HOST_CTRL0_UTMISWRST);
505 writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
506
507 /* OTG configuration */
508 phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
509
510 /* phy reference clock configuration */
511 phyotg &= ~OTG_SYS_FSEL_MASK;
512 phyotg |= OTG_SYS_FSEL(phyclk);
513
514 /* Enable normal mode of operation */
515 phyotg &= ~(OTG_SYS_FORCESUSPEND |
516 OTG_SYS_SIDDQ_UOTG |
517 OTG_SYS_FORCESLEEP |
518 OTG_SYS_REFCLKSEL_MASK |
519 /* COMMON Block configuration during suspend */
520 OTG_SYS_COMMON_ON);
521
522 /* OTG phy & link reset */
523 phyotg |= (OTG_SYS_PHY0_SWRST |
524 OTG_SYS_LINKSWRST_UOTG |
525 OTG_SYS_PHYLINK_SWRESET |
526 OTG_SYS_OTGDISABLE |
527 /* Set phy refclk */
528 OTG_SYS_REFCLKSEL_CLKCORE);
529
530 writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
531 udelay(10);
532 phyotg &= ~(OTG_SYS_PHY0_SWRST |
533 OTG_SYS_LINKSWRST_UOTG |
534 OTG_SYS_PHYLINK_SWRESET);
535 writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
536
537 /* HSIC phy configuration */
538 phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
539 HSIC_CTRL_REFCLKSEL |
540 HSIC_CTRL_PHYSWRST);
541 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
542 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
543 udelay(10);
544 phyhsic &= ~HSIC_CTRL_PHYSWRST;
545 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
546 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
547
548 udelay(80);
549
550 /* enable EHCI DMA burst */
551 ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
552 ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
553 HOST_EHCICTRL_ENAINCR4 |
554 HOST_EHCICTRL_ENAINCR8 |
555 HOST_EHCICTRL_ENAINCR16);
556 writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
557
558 /* set ohci_suspend_on_n */
559 ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
560 ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
561 writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
562 }
563
564 static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
565 {
566 void __iomem *regs = sphy->regs;
567 u32 phypwr;
568 u32 phyclk;
569 u32 rstcon;
570
571 /* set clock frequency for PLL */
572 phyclk = sphy->ref_clk_freq;
573 phypwr = readl(regs + SAMSUNG_PHYPWR);
574 rstcon = readl(regs + SAMSUNG_RSTCON);
575
576 switch (sphy->drv_data->cpu_type) {
577 case TYPE_S3C64XX:
578 phyclk &= ~PHYCLK_COMMON_ON_N;
579 phypwr &= ~PHYPWR_NORMAL_MASK;
580 rstcon |= RSTCON_SWRST;
581 break;
582 case TYPE_EXYNOS4210:
583 phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
584 rstcon |= RSTCON_SWRST;
585 default:
586 break;
587 }
588
589 writel(phyclk, regs + SAMSUNG_PHYCLK);
590 /* Configure PHY0 for normal operation*/
591 writel(phypwr, regs + SAMSUNG_PHYPWR);
592 /* reset all ports of PHY and Link */
593 writel(rstcon, regs + SAMSUNG_RSTCON);
594 udelay(10);
595 rstcon &= ~RSTCON_SWRST;
596 writel(rstcon, regs + SAMSUNG_RSTCON);
597 }
598
599 static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
600 {
601 void __iomem *regs = sphy->regs;
602 u32 phyhost;
603 u32 phyotg;
604 u32 phyhsic;
605
606 if (atomic_dec_return(&sphy->phy_usage) > 0) {
607 dev_info(sphy->dev, "still being used\n");
608 return;
609 }
610
611 phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
612 HSIC_CTRL_REFCLKSEL |
613 HSIC_CTRL_SIDDQ |
614 HSIC_CTRL_FORCESLEEP |
615 HSIC_CTRL_FORCESUSPEND);
616 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
617 writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
618
619 phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
620 phyhost |= (HOST_CTRL0_SIDDQ |
621 HOST_CTRL0_FORCESUSPEND |
622 HOST_CTRL0_FORCESLEEP |
623 HOST_CTRL0_PHYSWRST |
624 HOST_CTRL0_PHYSWRSTALL);
625 writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
626
627 phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
628 phyotg |= (OTG_SYS_FORCESUSPEND |
629 OTG_SYS_SIDDQ_UOTG |
630 OTG_SYS_FORCESLEEP);
631 writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
632 }
633
634 static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
635 {
636 void __iomem *regs = sphy->regs;
637 u32 phypwr;
638
639 phypwr = readl(regs + SAMSUNG_PHYPWR);
640
641 switch (sphy->drv_data->cpu_type) {
642 case TYPE_S3C64XX:
643 phypwr |= PHYPWR_NORMAL_MASK;
644 break;
645 case TYPE_EXYNOS4210:
646 phypwr |= PHYPWR_NORMAL_MASK_PHY0;
647 default:
648 break;
649 }
650
651 /* Disable analog and otg block power */
652 writel(phypwr, regs + SAMSUNG_PHYPWR);
653 }
654
655 /*
656 * The function passed to the usb driver for phy initialization
657 */
658 static int samsung_usbphy_init(struct usb_phy *phy)
659 {
660 struct samsung_usbphy *sphy;
661 struct usb_bus *host = NULL;
662 unsigned long flags;
663 int ret = 0;
664
665 sphy = phy_to_sphy(phy);
666
667 host = phy->otg->host;
668
669 /* Enable the phy clock */
670 ret = clk_prepare_enable(sphy->clk);
671 if (ret) {
672 dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
673 return ret;
674 }
675
676 spin_lock_irqsave(&sphy->lock, flags);
677
678 if (host) {
679 /* setting default phy-type for USB 2.0 */
680 if (!strstr(dev_name(host->controller), "ehci") ||
681 !strstr(dev_name(host->controller), "ohci"))
682 samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
683 } else {
684 samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
685 }
686
687 /* Disable phy isolation */
688 if (sphy->plat && sphy->plat->pmu_isolation)
689 sphy->plat->pmu_isolation(false);
690 else
691 samsung_usbphy_set_isolation(sphy, false);
692
693 /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
694 samsung_usbphy_cfg_sel(sphy);
695
696 /* Initialize usb phy registers */
697 if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
698 samsung_exynos5_usbphy_enable(sphy);
699 else
700 samsung_usbphy_enable(sphy);
701
702 spin_unlock_irqrestore(&sphy->lock, flags);
703
704 /* Disable the phy clock */
705 clk_disable_unprepare(sphy->clk);
706
707 return ret;
708 }
709
710 /*
711 * The function passed to the usb driver for phy shutdown
712 */
713 static void samsung_usbphy_shutdown(struct usb_phy *phy)
714 {
715 struct samsung_usbphy *sphy;
716 struct usb_bus *host = NULL;
717 unsigned long flags;
718
719 sphy = phy_to_sphy(phy);
720
721 host = phy->otg->host;
722
723 if (clk_prepare_enable(sphy->clk)) {
724 dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
725 return;
726 }
727
728 spin_lock_irqsave(&sphy->lock, flags);
729
730 if (host) {
731 /* setting default phy-type for USB 2.0 */
732 if (!strstr(dev_name(host->controller), "ehci") ||
733 !strstr(dev_name(host->controller), "ohci"))
734 samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
735 } else {
736 samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
737 }
738
739 /* De-initialize usb phy registers */
740 if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
741 samsung_exynos5_usbphy_disable(sphy);
742 else
743 samsung_usbphy_disable(sphy);
744
745 /* Enable phy isolation */
746 if (sphy->plat && sphy->plat->pmu_isolation)
747 sphy->plat->pmu_isolation(true);
748 else
749 samsung_usbphy_set_isolation(sphy, true);
750
751 spin_unlock_irqrestore(&sphy->lock, flags);
752
753 clk_disable_unprepare(sphy->clk);
754 }
755
756 static const struct of_device_id samsung_usbphy_dt_match[];
757
758 static inline const struct samsung_usbphy_drvdata
759 *samsung_usbphy_get_driver_data(struct platform_device *pdev)
760 {
761 if (pdev->dev.of_node) {
762 const struct of_device_id *match;
763 match = of_match_node(samsung_usbphy_dt_match,
764 pdev->dev.of_node);
765 return match->data;
766 }
767
768 return (struct samsung_usbphy_drvdata *)
769 platform_get_device_id(pdev)->driver_data;
770 }
771
772 static int samsung_usbphy_probe(struct platform_device *pdev)
773 {
774 struct samsung_usbphy *sphy;
775 struct usb_otg *otg;
776 struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
777 const struct samsung_usbphy_drvdata *drv_data;
778 struct device *dev = &pdev->dev;
779 struct resource *phy_mem;
780 void __iomem *phy_base;
781 struct clk *clk;
782 int ret;
783
784 phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
785 if (!phy_mem) {
786 dev_err(dev, "%s: missing mem resource\n", __func__);
787 return -ENODEV;
788 }
789
790 phy_base = devm_ioremap_resource(dev, phy_mem);
791 if (IS_ERR(phy_base))
792 return PTR_ERR(phy_base);
793
794 sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
795 if (!sphy)
796 return -ENOMEM;
797
798 otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
799 if (!otg)
800 return -ENOMEM;
801
802 drv_data = samsung_usbphy_get_driver_data(pdev);
803
804 if (drv_data->cpu_type == TYPE_EXYNOS5250)
805 clk = devm_clk_get(dev, "usbhost");
806 else
807 clk = devm_clk_get(dev, "otg");
808
809 if (IS_ERR(clk)) {
810 dev_err(dev, "Failed to get otg clock\n");
811 return PTR_ERR(clk);
812 }
813
814 sphy->dev = dev;
815
816 if (dev->of_node) {
817 ret = samsung_usbphy_parse_dt(sphy);
818 if (ret < 0)
819 return ret;
820 } else {
821 if (!pdata) {
822 dev_err(dev, "no platform data specified\n");
823 return -EINVAL;
824 }
825 }
826
827 sphy->plat = pdata;
828 sphy->regs = phy_base;
829 sphy->clk = clk;
830 sphy->drv_data = drv_data;
831 sphy->phy.dev = sphy->dev;
832 sphy->phy.label = "samsung-usbphy";
833 sphy->phy.init = samsung_usbphy_init;
834 sphy->phy.shutdown = samsung_usbphy_shutdown;
835 sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
836
837 sphy->phy.otg = otg;
838 sphy->phy.otg->phy = &sphy->phy;
839 sphy->phy.otg->set_host = samsung_usbphy_set_host;
840
841 spin_lock_init(&sphy->lock);
842
843 platform_set_drvdata(pdev, sphy);
844
845 return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
846 }
847
848 static int samsung_usbphy_remove(struct platform_device *pdev)
849 {
850 struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
851
852 usb_remove_phy(&sphy->phy);
853
854 if (sphy->pmuregs)
855 iounmap(sphy->pmuregs);
856 if (sphy->sysreg)
857 iounmap(sphy->sysreg);
858
859 return 0;
860 }
861
862 static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
863 .cpu_type = TYPE_S3C64XX,
864 .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
865 };
866
867 static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
868 .cpu_type = TYPE_EXYNOS4210,
869 .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
870 .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
871 };
872
873 static struct samsung_usbphy_drvdata usbphy_exynos5 = {
874 .cpu_type = TYPE_EXYNOS5250,
875 .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
876 .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
877 };
878
879 #ifdef CONFIG_OF
880 static const struct of_device_id samsung_usbphy_dt_match[] = {
881 {
882 .compatible = "samsung,s3c64xx-usbphy",
883 .data = &usbphy_s3c64xx,
884 }, {
885 .compatible = "samsung,exynos4210-usbphy",
886 .data = &usbphy_exynos4,
887 }, {
888 .compatible = "samsung,exynos5250-usbphy",
889 .data = &usbphy_exynos5
890 },
891 {},
892 };
893 MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
894 #endif
895
896 static struct platform_device_id samsung_usbphy_driver_ids[] = {
897 {
898 .name = "s3c64xx-usbphy",
899 .driver_data = (unsigned long)&usbphy_s3c64xx,
900 }, {
901 .name = "exynos4210-usbphy",
902 .driver_data = (unsigned long)&usbphy_exynos4,
903 }, {
904 .name = "exynos5250-usbphy",
905 .driver_data = (unsigned long)&usbphy_exynos5,
906 },
907 {},
908 };
909
910 MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
911
912 static struct platform_driver samsung_usbphy_driver = {
913 .probe = samsung_usbphy_probe,
914 .remove = samsung_usbphy_remove,
915 .id_table = samsung_usbphy_driver_ids,
916 .driver = {
917 .name = "samsung-usbphy",
918 .owner = THIS_MODULE,
919 .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
920 },
921 };
922
923 module_platform_driver(samsung_usbphy_driver);
924
925 MODULE_DESCRIPTION("Samsung USB phy controller");
926 MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
927 MODULE_LICENSE("GPL");
928 MODULE_ALIAS("platform:samsung-usbphy");
This page took 0.069114 seconds and 5 git commands to generate.