~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-exynos/setup-usb-phy.c

Version: ~ [ linux-5.6-rc1 ] ~ [ linux-5.5.2 ] ~ [ linux-5.4.17 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.102 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.170 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.213 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.213 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 24 static int exynos4_usb_host_phy_is_on(void)
 25 {
 26         return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
 27 }
 28 
 29 static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
 30 {
 31         struct clk *xusbxti_clk;
 32         u32 phyclk;
 33 
 34         xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
 35         if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
 36                 if (soc_is_exynos4210()) {
 37                         /* set clock frequency for PLL */
 38                         phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4210_CLKSEL_MASK;
 39 
 40                         switch (clk_get_rate(xusbxti_clk)) {
 41                         case 12 * MHZ:
 42                                 phyclk |= EXYNOS4210_CLKSEL_12M;
 43                                 break;
 44                         case 48 * MHZ:
 45                                 phyclk |= EXYNOS4210_CLKSEL_48M;
 46                                 break;
 47                         default:
 48                         case 24 * MHZ:
 49                                 phyclk |= EXYNOS4210_CLKSEL_24M;
 50                                 break;
 51                         }
 52                         writel(phyclk, EXYNOS4_PHYCLK);
 53                 } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
 54                         /* set clock frequency for PLL */
 55                         phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4X12_CLKSEL_MASK;
 56 
 57                         switch (clk_get_rate(xusbxti_clk)) {
 58                         case 9600 * KHZ:
 59                                 phyclk |= EXYNOS4X12_CLKSEL_9600K;
 60                                 break;
 61                         case 10 * MHZ:
 62                                 phyclk |= EXYNOS4X12_CLKSEL_10M;
 63                                 break;
 64                         case 12 * MHZ:
 65                                 phyclk |= EXYNOS4X12_CLKSEL_12M;
 66                                 break;
 67                         case 19200 * KHZ:
 68                                 phyclk |= EXYNOS4X12_CLKSEL_19200K;
 69                                 break;
 70                         case 20 * MHZ:
 71                                 phyclk |= EXYNOS4X12_CLKSEL_20M;
 72                                 break;
 73                         default:
 74                         case 24 * MHZ:
 75                                 /* default reference clock */
 76                                 phyclk |= EXYNOS4X12_CLKSEL_24M;
 77                                 break;
 78                         }
 79                         writel(phyclk, EXYNOS4_PHYCLK);
 80                 }
 81                 clk_put(xusbxti_clk);
 82         }
 83 }
 84 
 85 static int exynos4210_usb_phy0_init(struct platform_device *pdev)
 86 {
 87         u32 rstcon;
 88 
 89         writel(readl(S5P_USBDEVICE_PHY_CONTROL) | S5P_USBDEVICE_PHY_ENABLE,
 90                         S5P_USBDEVICE_PHY_CONTROL);
 91 
 92         exynos4210_usb_phy_clkset(pdev);
 93 
 94         /* set to normal PHY0 */
 95         writel((readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK), EXYNOS4_PHYPWR);
 96 
 97         /* reset PHY0 and Link */
 98         rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK;
 99         writel(rstcon, EXYNOS4_RSTCON);
100         udelay(10);
101 
102         rstcon &= ~PHY0_SWRST_MASK;
103         writel(rstcon, EXYNOS4_RSTCON);
104 
105         return 0;
106 }
107 
108 static int exynos4210_usb_phy0_exit(struct platform_device *pdev)
109 {
110         writel((readl(EXYNOS4_PHYPWR) | PHY0_ANALOG_POWERDOWN |
111                                 PHY0_OTG_DISABLE), EXYNOS4_PHYPWR);
112 
113         writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~S5P_USBDEVICE_PHY_ENABLE,
114                         S5P_USBDEVICE_PHY_CONTROL);
115 
116         return 0;
117 }
118 
119 static int exynos4210_usb_phy1_init(struct platform_device *pdev)
120 {
121         struct clk *otg_clk;
122         u32 rstcon;
123         int err;
124 
125         atomic_inc(&host_usage);
126 
127         otg_clk = clk_get(&pdev->dev, "otg");
128         if (IS_ERR(otg_clk)) {
129                 dev_err(&pdev->dev, "Failed to get otg clock\n");
130                 return PTR_ERR(otg_clk);
131         }
132 
133         err = clk_enable(otg_clk);
134         if (err) {
135                 clk_put(otg_clk);
136                 return err;
137         }
138 
139         if (exynos4_usb_host_phy_is_on())
140                 return 0;
141 
142         writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
143                         S5P_USBHOST_PHY_CONTROL);
144 
145         exynos4210_usb_phy_clkset(pdev);
146 
147         /* floating prevention logic: disable */
148         writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
149 
150         /* set to normal HSIC 0 and 1 of PHY1 */
151         writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
152                         EXYNOS4_PHYPWR);
153 
154         /* set to normal standard USB of PHY1 */
155         writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
156 
157         /* reset all ports of both PHY and Link */
158         rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
159                 PHY1_SWRST_MASK;
160         writel(rstcon, EXYNOS4_RSTCON);
161         udelay(10);
162 
163         rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
164         writel(rstcon, EXYNOS4_RSTCON);
165         udelay(80);
166 
167         clk_disable(otg_clk);
168         clk_put(otg_clk);
169 
170         return 0;
171 }
172 
173 static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
174 {
175         struct clk *otg_clk;
176         int err;
177 
178         if (atomic_dec_return(&host_usage) > 0)
179                 return 0;
180 
181         otg_clk = clk_get(&pdev->dev, "otg");
182         if (IS_ERR(otg_clk)) {
183                 dev_err(&pdev->dev, "Failed to get otg clock\n");
184                 return PTR_ERR(otg_clk);
185         }
186 
187         err = clk_enable(otg_clk);
188         if (err) {
189                 clk_put(otg_clk);
190                 return err;
191         }
192 
193         writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
194                         EXYNOS4_PHYPWR);
195 
196         writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
197                         S5P_USBHOST_PHY_CONTROL);
198 
199         clk_disable(otg_clk);
200         clk_put(otg_clk);
201 
202         return 0;
203 }
204 
205 int s5p_usb_phy_init(struct platform_device *pdev, int type)
206 {
207         if (type == S5P_USB_PHY_DEVICE)
208                 return exynos4210_usb_phy0_init(pdev);
209         else if (type == S5P_USB_PHY_HOST)
210                 return exynos4210_usb_phy1_init(pdev);
211 
212         return -EINVAL;
213 }
214 
215 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
216 {
217         if (type == S5P_USB_PHY_DEVICE)
218                 return exynos4210_usb_phy0_exit(pdev);
219         else if (type == S5P_USB_PHY_HOST)
220                 return exynos4210_usb_phy1_exit(pdev);
221 
222         return -EINVAL;
223 }
224 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp