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