1 /*
2  * Copyright (C) 2011 Samsung Electronics Co.Ltd
3  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
4  *
5  *  This program is free software; you can redistribute  it and/or modify it
6  *  under  the terms of  the GNU General  Public License as published by the
7  *  Free Software Foundation;  either version 2 of the  License, or (at your
8  *  option) any later version.
9  *
10  */
11 
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <linux/err.h>
15 #include <linux/io.h>
16 #include <linux/platform_device.h>
17 #include <mach/regs-pmu.h>
18 #include <mach/regs-usb-phy.h>
19 #include <plat/cpu.h>
20 #include <plat/usb-phy.h>
21 
22 static atomic_t host_usage;
23 
exynos4_usb_host_phy_is_on(void)24 static int exynos4_usb_host_phy_is_on(void)
25 {
26 	return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
27 }
28 
exynos4_usb_phy1_init(struct platform_device * pdev)29 static int exynos4_usb_phy1_init(struct platform_device *pdev)
30 {
31 	struct clk *otg_clk;
32 	struct clk *xusbxti_clk;
33 	u32 phyclk;
34 	u32 rstcon;
35 	int err;
36 
37 	atomic_inc(&host_usage);
38 
39 	otg_clk = clk_get(&pdev->dev, "otg");
40 	if (IS_ERR(otg_clk)) {
41 		dev_err(&pdev->dev, "Failed to get otg clock\n");
42 		return PTR_ERR(otg_clk);
43 	}
44 
45 	err = clk_enable(otg_clk);
46 	if (err) {
47 		clk_put(otg_clk);
48 		return err;
49 	}
50 
51 	if (exynos4_usb_host_phy_is_on())
52 		return 0;
53 
54 	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
55 			S5P_USBHOST_PHY_CONTROL);
56 
57 	/* set clock frequency for PLL */
58 	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
59 
60 	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
61 	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
62 		switch (clk_get_rate(xusbxti_clk)) {
63 		case 12 * MHZ:
64 			phyclk |= CLKSEL_12M;
65 			break;
66 		case 24 * MHZ:
67 			phyclk |= CLKSEL_24M;
68 			break;
69 		default:
70 		case 48 * MHZ:
71 			/* default reference clock */
72 			break;
73 		}
74 		clk_put(xusbxti_clk);
75 	}
76 
77 	writel(phyclk, EXYNOS4_PHYCLK);
78 
79 	/* floating prevention logic: disable */
80 	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
81 
82 	/* set to normal HSIC 0 and 1 of PHY1 */
83 	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
84 			EXYNOS4_PHYPWR);
85 
86 	/* set to normal standard USB of PHY1 */
87 	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
88 
89 	/* reset all ports of both PHY and Link */
90 	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
91 		PHY1_SWRST_MASK;
92 	writel(rstcon, EXYNOS4_RSTCON);
93 	udelay(10);
94 
95 	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
96 	writel(rstcon, EXYNOS4_RSTCON);
97 	udelay(80);
98 
99 	clk_disable(otg_clk);
100 	clk_put(otg_clk);
101 
102 	return 0;
103 }
104 
exynos4_usb_phy1_exit(struct platform_device * pdev)105 static int exynos4_usb_phy1_exit(struct platform_device *pdev)
106 {
107 	struct clk *otg_clk;
108 	int err;
109 
110 	if (atomic_dec_return(&host_usage) > 0)
111 		return 0;
112 
113 	otg_clk = clk_get(&pdev->dev, "otg");
114 	if (IS_ERR(otg_clk)) {
115 		dev_err(&pdev->dev, "Failed to get otg clock\n");
116 		return PTR_ERR(otg_clk);
117 	}
118 
119 	err = clk_enable(otg_clk);
120 	if (err) {
121 		clk_put(otg_clk);
122 		return err;
123 	}
124 
125 	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
126 			EXYNOS4_PHYPWR);
127 
128 	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
129 			S5P_USBHOST_PHY_CONTROL);
130 
131 	clk_disable(otg_clk);
132 	clk_put(otg_clk);
133 
134 	return 0;
135 }
136 
s5p_usb_phy_init(struct platform_device * pdev,int type)137 int s5p_usb_phy_init(struct platform_device *pdev, int type)
138 {
139 	if (type == S5P_USB_PHY_HOST)
140 		return exynos4_usb_phy1_init(pdev);
141 
142 	return -EINVAL;
143 }
144 
s5p_usb_phy_exit(struct platform_device * pdev,int type)145 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
146 {
147 	if (type == S5P_USB_PHY_HOST)
148 		return exynos4_usb_phy1_exit(pdev);
149 
150 	return -EINVAL;
151 }
152