]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/usb/host/ehci-exynos.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / drivers / usb / host / ehci-exynos.c
1 /*
2  * SAMSUNG EXYNOS USB HOST EHCI Controller
3  *
4  * Copyright (C) 2012 Samsung Electronics Co.Ltd
5  *      Vivek Gautam <gautam.vivek@samsung.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <fdtdec.h>
12 #include <libfdt.h>
13 #include <malloc.h>
14 #include <usb.h>
15 #include <asm/arch/cpu.h>
16 #include <asm/arch/ehci.h>
17 #include <asm/arch/system.h>
18 #include <asm/arch/power.h>
19 #include <asm-generic/errno.h>
20 #include <linux/compat.h>
21 #include "ehci.h"
22
23 /* Declare global data pointer */
24 DECLARE_GLOBAL_DATA_PTR;
25
26 /**
27  * Contains pointers to register base addresses
28  * for the usb controller.
29  */
30 struct exynos_ehci {
31         struct exynos_usb_phy *usb;
32         struct ehci_hccr *hcd;
33 };
34
35 static struct exynos_ehci exynos;
36
37 #ifdef CONFIG_OF_CONTROL
38 static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
39 {
40         fdt_addr_t addr;
41         unsigned int node;
42         int depth;
43
44         node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_EHCI);
45         if (node <= 0) {
46                 debug("EHCI: Can't get device node for ehci\n");
47                 return -ENODEV;
48         }
49
50         /*
51          * Get the base address for EHCI controller from the device node
52          */
53         addr = fdtdec_get_addr(blob, node, "reg");
54         if (addr == FDT_ADDR_T_NONE) {
55                 debug("Can't get the EHCI register address\n");
56                 return -ENXIO;
57         }
58
59         exynos->hcd = (struct ehci_hccr *)addr;
60
61         depth = 0;
62         node = fdtdec_next_compatible_subnode(blob, node,
63                                         COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
64         if (node <= 0) {
65                 debug("EHCI: Can't get device node for usb-phy controller\n");
66                 return -ENODEV;
67         }
68
69         /*
70          * Get the base address for usbphy from the device node
71          */
72         exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr(blob, node,
73                                                                 "reg");
74         if (exynos->usb == NULL) {
75                 debug("Can't get the usbphy register address\n");
76                 return -ENXIO;
77         }
78
79         return 0;
80 }
81 #endif
82
83 /* Setup the EHCI host controller. */
84 static void setup_usb_phy(struct exynos_usb_phy *usb)
85 {
86         set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
87
88         set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
89
90         clrbits_le32(&usb->usbphyctrl0,
91                         HOST_CTRL0_FSEL_MASK |
92                         HOST_CTRL0_COMMONON_N |
93                         /* HOST Phy setting */
94                         HOST_CTRL0_PHYSWRST |
95                         HOST_CTRL0_PHYSWRSTALL |
96                         HOST_CTRL0_SIDDQ |
97                         HOST_CTRL0_FORCESUSPEND |
98                         HOST_CTRL0_FORCESLEEP);
99
100         setbits_le32(&usb->usbphyctrl0,
101                         /* Setting up the ref freq */
102                         (CLK_24MHZ << 16) |
103                         /* HOST Phy setting */
104                         HOST_CTRL0_LINKSWRST |
105                         HOST_CTRL0_UTMISWRST);
106         udelay(10);
107         clrbits_le32(&usb->usbphyctrl0,
108                         HOST_CTRL0_LINKSWRST |
109                         HOST_CTRL0_UTMISWRST);
110         udelay(20);
111
112         /* EHCI Ctrl setting */
113         setbits_le32(&usb->ehcictrl,
114                         EHCICTRL_ENAINCRXALIGN |
115                         EHCICTRL_ENAINCR4 |
116                         EHCICTRL_ENAINCR8 |
117                         EHCICTRL_ENAINCR16);
118 }
119
120 /* Reset the EHCI host controller. */
121 static void reset_usb_phy(struct exynos_usb_phy *usb)
122 {
123         /* HOST_PHY reset */
124         setbits_le32(&usb->usbphyctrl0,
125                         HOST_CTRL0_PHYSWRST |
126                         HOST_CTRL0_PHYSWRSTALL |
127                         HOST_CTRL0_SIDDQ |
128                         HOST_CTRL0_FORCESUSPEND |
129                         HOST_CTRL0_FORCESLEEP);
130
131         set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
132 }
133
134 /*
135  * EHCI-initialization
136  * Create the appropriate control structures to manage
137  * a new EHCI host controller.
138  */
139 int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
140 {
141         struct exynos_ehci *ctx = &exynos;
142
143 #ifdef CONFIG_OF_CONTROL
144         if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) {
145                 debug("Unable to parse device tree for ehci-exynos\n");
146                 return -ENODEV;
147         }
148 #else
149         ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
150         ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci();
151 #endif
152
153         setup_usb_phy(ctx->usb);
154
155         *hccr = ctx->hcd;
156         *hcor = (struct ehci_hcor *)((uint32_t) *hccr
157                                 + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
158
159         debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n",
160                 (uint32_t)*hccr, (uint32_t)*hcor,
161                 (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
162
163         return 0;
164 }
165
166 /*
167  * Destroy the appropriate control structures corresponding
168  * the EHCI host controller.
169  */
170 int ehci_hcd_stop(int index)
171 {
172         struct exynos_ehci *ctx = &exynos;
173
174         reset_usb_phy(ctx->usb);
175
176         return 0;
177 }