blob: 86cf6312febc30b7e142146c3b4763a6a871d5a6 [file] [log] [blame]
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +05301/*
Rajeshwari Shinde7590d3c2012-05-21 16:38:03 +05302 * SAMSUNG EXYNOS USB HOST EHCI Controller
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +05303 *
4 * Copyright (C) 2012 Samsung Electronics Co.Ltd
5 * Vivek Gautam <gautam.vivek@samsung.com>
6 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +05308 */
9
10#include <common.h>
Simon Glassaae04d02015-03-25 12:22:44 -060011#include <dm.h>
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000012#include <fdtdec.h>
13#include <libfdt.h>
14#include <malloc.h>
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +053015#include <usb.h>
16#include <asm/arch/cpu.h>
Rajeshwari Shinde7590d3c2012-05-21 16:38:03 +053017#include <asm/arch/ehci.h>
Rajeshwari Shinde71045da2012-05-14 05:52:02 +000018#include <asm/arch/system.h>
Rajeshwari Shindec48ac112012-05-14 05:52:03 +000019#include <asm/arch/power.h>
Julius Werner4a271cb2013-09-14 14:02:52 +053020#include <asm/gpio.h>
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000021#include <asm-generic/errno.h>
22#include <linux/compat.h>
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +053023#include "ehci.h"
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +053024
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000025/* Declare global data pointer */
26DECLARE_GLOBAL_DATA_PTR;
27
Simon Glassaae04d02015-03-25 12:22:44 -060028#ifdef CONFIG_DM_USB
29struct exynos_ehci_platdata {
30 struct usb_platdata usb_plat;
31 fdt_addr_t hcd_base;
32 fdt_addr_t phy_base;
33 struct gpio_desc vbus_gpio;
34};
35#endif
36
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000037/**
38 * Contains pointers to register base addresses
39 * for the usb controller.
40 */
41struct exynos_ehci {
Simon Glassaae04d02015-03-25 12:22:44 -060042 struct ehci_ctrl ctrl;
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000043 struct exynos_usb_phy *usb;
Vivek Gautam24a47752013-03-06 14:18:32 +053044 struct ehci_hccr *hcd;
Simon Glassaae04d02015-03-25 12:22:44 -060045#ifndef CONFIG_DM_USB
Simon Glass46927e12015-01-05 20:05:39 -070046 struct gpio_desc vbus_gpio;
Simon Glassaae04d02015-03-25 12:22:44 -060047#endif
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000048};
49
Simon Glassaae04d02015-03-25 12:22:44 -060050#ifndef CONFIG_DM_USB
Vivek Gautam24a47752013-03-06 14:18:32 +053051static struct exynos_ehci exynos;
Simon Glassaae04d02015-03-25 12:22:44 -060052#endif
Vivek Gautam24a47752013-03-06 14:18:32 +053053
Simon Glassaae04d02015-03-25 12:22:44 -060054#ifdef CONFIG_DM_USB
55static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
56{
57 struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
58 const void *blob = gd->fdt_blob;
59 unsigned int node;
60 int depth;
61
62 /*
63 * Get the base address for XHCI controller from the device node
64 */
65 plat->hcd_base = dev_get_addr(dev);
66 if (plat->hcd_base == FDT_ADDR_T_NONE) {
67 debug("Can't get the XHCI register base address\n");
68 return -ENXIO;
69 }
70
71 depth = 0;
72 node = fdtdec_next_compatible_subnode(blob, dev->of_offset,
73 COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
74 if (node <= 0) {
75 debug("XHCI: Can't get device node for usb3-phy controller\n");
76 return -ENODEV;
77 }
78
79 /*
80 * Get the base address for usbphy from the device node
81 */
82 plat->phy_base = fdtdec_get_addr(blob, node, "reg");
83 if (plat->phy_base == FDT_ADDR_T_NONE) {
84 debug("Can't get the usbphy register address\n");
85 return -ENXIO;
86 }
87
88 /* Vbus gpio */
89 gpio_request_by_name(dev, "samsung,vbus-gpio", 0,
90 &plat->vbus_gpio, GPIOD_IS_OUT);
91
92 return 0;
93}
94#else
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000095static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
96{
Vivek Gautam24a47752013-03-06 14:18:32 +053097 fdt_addr_t addr;
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +000098 unsigned int node;
99 int depth;
100
101 node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_EHCI);
102 if (node <= 0) {
103 debug("EHCI: Can't get device node for ehci\n");
104 return -ENODEV;
105 }
106
107 /*
108 * Get the base address for EHCI controller from the device node
109 */
Vivek Gautam24a47752013-03-06 14:18:32 +0530110 addr = fdtdec_get_addr(blob, node, "reg");
111 if (addr == FDT_ADDR_T_NONE) {
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +0000112 debug("Can't get the EHCI register address\n");
113 return -ENXIO;
114 }
115
Vivek Gautam24a47752013-03-06 14:18:32 +0530116 exynos->hcd = (struct ehci_hccr *)addr;
117
Julius Werner4a271cb2013-09-14 14:02:52 +0530118 /* Vbus gpio */
Simon Glass46927e12015-01-05 20:05:39 -0700119 gpio_request_by_name_nodev(blob, node, "samsung,vbus-gpio", 0,
120 &exynos->vbus_gpio, GPIOD_IS_OUT);
Julius Werner4a271cb2013-09-14 14:02:52 +0530121
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +0000122 depth = 0;
123 node = fdtdec_next_compatible_subnode(blob, node,
124 COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
125 if (node <= 0) {
126 debug("EHCI: Can't get device node for usb-phy controller\n");
127 return -ENODEV;
128 }
129
130 /*
131 * Get the base address for usbphy from the device node
132 */
133 exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr(blob, node,
134 "reg");
135 if (exynos->usb == NULL) {
136 debug("Can't get the usbphy register address\n");
137 return -ENXIO;
138 }
139
140 return 0;
141}
Vivek Gautamc74b0112013-03-06 14:18:33 +0530142#endif
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +0000143
Suriyan Ramasami6a23c652014-10-29 09:22:43 -0700144static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530145{
Inderpal Singh16f94802014-01-08 09:19:56 +0530146 u32 hsic_ctrl;
147
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530148 clrbits_le32(&usb->usbphyctrl0,
149 HOST_CTRL0_FSEL_MASK |
150 HOST_CTRL0_COMMONON_N |
151 /* HOST Phy setting */
152 HOST_CTRL0_PHYSWRST |
153 HOST_CTRL0_PHYSWRSTALL |
154 HOST_CTRL0_SIDDQ |
155 HOST_CTRL0_FORCESUSPEND |
156 HOST_CTRL0_FORCESLEEP);
157
158 setbits_le32(&usb->usbphyctrl0,
159 /* Setting up the ref freq */
160 (CLK_24MHZ << 16) |
161 /* HOST Phy setting */
162 HOST_CTRL0_LINKSWRST |
163 HOST_CTRL0_UTMISWRST);
164 udelay(10);
165 clrbits_le32(&usb->usbphyctrl0,
166 HOST_CTRL0_LINKSWRST |
167 HOST_CTRL0_UTMISWRST);
Inderpal Singh16f94802014-01-08 09:19:56 +0530168
169 /* HSIC Phy Setting */
170 hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
171 HSIC_CTRL_FORCESLEEP |
172 HSIC_CTRL_SIDDQ);
173
174 clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
175 clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
176
177 hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK)
178 << HSIC_CTRL_REFCLKDIV_SHIFT)
179 | ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK)
180 << HSIC_CTRL_REFCLKSEL_SHIFT)
181 | HSIC_CTRL_UTMISWRST);
182
183 setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
184 setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
185
186 udelay(10);
187
188 clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST |
189 HSIC_CTRL_UTMISWRST);
190
191 clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST |
192 HSIC_CTRL_UTMISWRST);
193
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530194 udelay(20);
195
196 /* EHCI Ctrl setting */
197 setbits_le32(&usb->ehcictrl,
198 EHCICTRL_ENAINCRXALIGN |
199 EHCICTRL_ENAINCR4 |
200 EHCICTRL_ENAINCR8 |
201 EHCICTRL_ENAINCR16);
202}
203
Suriyan Ramasami6a23c652014-10-29 09:22:43 -0700204static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
205{
206 writel(CLK_24MHZ, &usb->usbphyclk);
207
208 clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
209 PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
210 PHYPWR_NORMAL_MASK_PHY0));
211
212 setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
213 udelay(10);
214 clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
215}
216
217static void setup_usb_phy(struct exynos_usb_phy *usb)
218{
219 set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
220
221 set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
222
223 if (cpu_is_exynos5())
224 exynos5_setup_usb_phy(usb);
225 else if (cpu_is_exynos4())
226 if (proid_is_exynos4412())
227 exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)
228 usb);
229}
230
231static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530232{
Inderpal Singh16f94802014-01-08 09:19:56 +0530233 u32 hsic_ctrl;
234
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530235 /* HOST_PHY reset */
236 setbits_le32(&usb->usbphyctrl0,
237 HOST_CTRL0_PHYSWRST |
238 HOST_CTRL0_PHYSWRSTALL |
239 HOST_CTRL0_SIDDQ |
240 HOST_CTRL0_FORCESUSPEND |
241 HOST_CTRL0_FORCESLEEP);
Rajeshwari Shindec48ac112012-05-14 05:52:03 +0000242
Inderpal Singh16f94802014-01-08 09:19:56 +0530243 /* HSIC Phy reset */
244 hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
245 HSIC_CTRL_FORCESLEEP |
246 HSIC_CTRL_SIDDQ |
247 HSIC_CTRL_PHYSWRST);
248
249 setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
250 setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
Suriyan Ramasami6a23c652014-10-29 09:22:43 -0700251}
252
253static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
254{
255 setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
256 PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
257 PHYPWR_NORMAL_MASK_PHY0));
258}
259
260/* Reset the EHCI host controller. */
261static void reset_usb_phy(struct exynos_usb_phy *usb)
262{
263 if (cpu_is_exynos5())
264 exynos5_reset_usb_phy(usb);
265 else if (cpu_is_exynos4())
266 if (proid_is_exynos4412())
267 exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)
268 usb);
Inderpal Singh16f94802014-01-08 09:19:56 +0530269
Rajeshwari Shindec48ac112012-05-14 05:52:03 +0000270 set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530271}
272
Simon Glassaae04d02015-03-25 12:22:44 -0600273#ifndef CONFIG_DM_USB
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530274/*
275 * EHCI-initialization
276 * Create the appropriate control structures to manage
277 * a new EHCI host controller.
278 */
Troy Kisky127efc42013-10-10 15:27:57 -0700279int ehci_hcd_init(int index, enum usb_init_type init,
280 struct ehci_hccr **hccr, struct ehci_hcor **hcor)
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530281{
Vivek Gautam24a47752013-03-06 14:18:32 +0530282 struct exynos_ehci *ctx = &exynos;
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530283
Vivek Gautamc74b0112013-03-06 14:18:33 +0530284#ifdef CONFIG_OF_CONTROL
Vivek Gautam24a47752013-03-06 14:18:32 +0530285 if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) {
286 debug("Unable to parse device tree for ehci-exynos\n");
287 return -ENODEV;
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +0000288 }
Vivek Gautamc74b0112013-03-06 14:18:33 +0530289#else
290 ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
291 ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci();
292#endif
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530293
Julius Werner4a271cb2013-09-14 14:02:52 +0530294#ifdef CONFIG_OF_CONTROL
295 /* setup the Vbus gpio here */
Simon Glass46927e12015-01-05 20:05:39 -0700296 if (dm_gpio_is_valid(&ctx->vbus_gpio))
297 dm_gpio_set_value(&ctx->vbus_gpio, 1);
Julius Werner4a271cb2013-09-14 14:02:52 +0530298#endif
299
Vivek Gautam24a47752013-03-06 14:18:32 +0530300 setup_usb_phy(ctx->usb);
Rajeshwari Shindee18bf1f2013-01-07 23:35:03 +0000301
Inderpal Singh7da76512014-01-08 09:19:57 +0530302 board_usb_init(index, init);
303
Vivek Gautam24a47752013-03-06 14:18:32 +0530304 *hccr = ctx->hcd;
Lucas Stach676ae062012-09-26 00:14:35 +0200305 *hcor = (struct ehci_hcor *)((uint32_t) *hccr
306 + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530307
308 debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n",
Lucas Stach676ae062012-09-26 00:14:35 +0200309 (uint32_t)*hccr, (uint32_t)*hcor,
310 (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530311
312 return 0;
313}
314
315/*
316 * Destroy the appropriate control structures corresponding
317 * the EHCI host controller.
318 */
Lucas Stach676ae062012-09-26 00:14:35 +0200319int ehci_hcd_stop(int index)
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530320{
Vivek Gautam24a47752013-03-06 14:18:32 +0530321 struct exynos_ehci *ctx = &exynos;
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530322
Vivek Gautam24a47752013-03-06 14:18:32 +0530323 reset_usb_phy(ctx->usb);
Rajeshwari Shinde5f0ffea2012-05-02 19:18:51 +0530324
325 return 0;
326}
Simon Glassaae04d02015-03-25 12:22:44 -0600327#endif
328
329#ifdef CONFIG_DM_USB
330static int ehci_usb_probe(struct udevice *dev)
331{
332 struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
333 struct exynos_ehci *ctx = dev_get_priv(dev);
334 struct ehci_hcor *hcor;
335
336 ctx->hcd = (struct ehci_hccr *)plat->hcd_base;
337 ctx->usb = (struct exynos_usb_phy *)plat->phy_base;
338 hcor = (struct ehci_hcor *)((uint32_t)ctx->hcd +
339 HC_LENGTH(ehci_readl(&ctx->hcd->cr_capbase)));
340
341 /* setup the Vbus gpio here */
342 if (dm_gpio_is_valid(&plat->vbus_gpio))
343 dm_gpio_set_value(&plat->vbus_gpio, 1);
344
345 setup_usb_phy(ctx->usb);
346
347 return ehci_register(dev, ctx->hcd, hcor, NULL, 0, USB_INIT_HOST);
348}
349
350static int ehci_usb_remove(struct udevice *dev)
351{
352 struct exynos_ehci *ctx = dev_get_priv(dev);
353 int ret;
354
355 ret = ehci_deregister(dev);
356 if (ret)
357 return ret;
358 reset_usb_phy(ctx->usb);
359
360 return 0;
361}
362
363static const struct udevice_id ehci_usb_ids[] = {
364 { .compatible = "samsung,exynos-ehci" },
365 { }
366};
367
368U_BOOT_DRIVER(usb_ehci) = {
369 .name = "ehci_exynos",
370 .id = UCLASS_USB,
371 .of_match = ehci_usb_ids,
372 .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
373 .probe = ehci_usb_probe,
374 .remove = ehci_usb_remove,
375 .ops = &ehci_usb_ops,
376 .priv_auto_alloc_size = sizeof(struct exynos_ehci),
377 .platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata),
378 .flags = DM_FLAG_ALLOC_PRIV_DMA,
379};
380#endif