Commit ab137d04db5a4b32250ce5ef1b288ce6cf06adf6
Committed by
Stephen Warren
1 parent
40e8b3a690
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
usb: host: tegra: make use of PHY pointer of HCD
As pointer to PHY structure can be stored in struct usb_hcd making use of it, to call Tegra PHY APIs. Call to usb_phy_shutdown() is moved up in tegra_ehci_remove(), so that to avoid dereferencing of hcd after its freed up. Signed-off-by: Venu Byravarasu <vbyravarasu@nvidia.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Felipe Balbi <balbi@ti.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Showing 3 changed files with 29 additions and 22 deletions Inline Diff
drivers/usb/host/ehci-tegra.c
1 | /* | 1 | /* |
2 | * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs | 2 | * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (C) 2009 - 2013 NVIDIA Corporation | 5 | * Copyright (C) 2009 - 2013 NVIDIA Corporation |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
9 | * Free Software Foundation; either version 2 of the License, or (at your | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | 12 | * This program is distributed in the hope that it will be useful, but WITHOUT |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
15 | * more details. | 15 | * more details. |
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/platform_data/tegra_usb.h> | 22 | #include <linux/platform_data/tegra_usb.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/usb/otg.h> | 24 | #include <linux/usb/otg.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/of_gpio.h> | 27 | #include <linux/of_gpio.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/usb/ehci_def.h> | 29 | #include <linux/usb/ehci_def.h> |
30 | #include <linux/usb/tegra_usb_phy.h> | 30 | #include <linux/usb/tegra_usb_phy.h> |
31 | 31 | ||
32 | #define TEGRA_USB_BASE 0xC5000000 | 32 | #define TEGRA_USB_BASE 0xC5000000 |
33 | #define TEGRA_USB2_BASE 0xC5004000 | 33 | #define TEGRA_USB2_BASE 0xC5004000 |
34 | #define TEGRA_USB3_BASE 0xC5008000 | 34 | #define TEGRA_USB3_BASE 0xC5008000 |
35 | 35 | ||
36 | /* PORTSC registers */ | 36 | /* PORTSC registers */ |
37 | #define TEGRA_USB_PORTSC1 0x184 | 37 | #define TEGRA_USB_PORTSC1 0x184 |
38 | #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | 38 | #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) |
39 | #define TEGRA_USB_PORTSC1_PHCD (1 << 23) | 39 | #define TEGRA_USB_PORTSC1_PHCD (1 << 23) |
40 | 40 | ||
41 | #define TEGRA_USB_DMA_ALIGN 32 | 41 | #define TEGRA_USB_DMA_ALIGN 32 |
42 | 42 | ||
43 | struct tegra_ehci_hcd { | 43 | struct tegra_ehci_hcd { |
44 | struct ehci_hcd *ehci; | 44 | struct ehci_hcd *ehci; |
45 | struct tegra_usb_phy *phy; | 45 | struct tegra_usb_phy *phy; |
46 | struct clk *clk; | 46 | struct clk *clk; |
47 | struct usb_phy *transceiver; | 47 | struct usb_phy *transceiver; |
48 | int host_resumed; | 48 | int host_resumed; |
49 | int port_resuming; | 49 | int port_resuming; |
50 | bool needs_double_reset; | 50 | bool needs_double_reset; |
51 | enum tegra_usb_phy_port_speed port_speed; | 51 | enum tegra_usb_phy_port_speed port_speed; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static void tegra_ehci_power_up(struct usb_hcd *hcd) | 54 | static void tegra_ehci_power_up(struct usb_hcd *hcd) |
55 | { | 55 | { |
56 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 56 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
57 | 57 | ||
58 | clk_prepare_enable(tegra->clk); | 58 | clk_prepare_enable(tegra->clk); |
59 | usb_phy_set_suspend(&tegra->phy->u_phy, 0); | 59 | usb_phy_set_suspend(hcd->phy, 0); |
60 | tegra->host_resumed = 1; | 60 | tegra->host_resumed = 1; |
61 | } | 61 | } |
62 | 62 | ||
63 | static void tegra_ehci_power_down(struct usb_hcd *hcd) | 63 | static void tegra_ehci_power_down(struct usb_hcd *hcd) |
64 | { | 64 | { |
65 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 65 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
66 | 66 | ||
67 | tegra->host_resumed = 0; | 67 | tegra->host_resumed = 0; |
68 | usb_phy_set_suspend(&tegra->phy->u_phy, 1); | 68 | usb_phy_set_suspend(hcd->phy, 1); |
69 | clk_disable_unprepare(tegra->clk); | 69 | clk_disable_unprepare(tegra->clk); |
70 | } | 70 | } |
71 | 71 | ||
72 | static int tegra_ehci_internal_port_reset( | 72 | static int tegra_ehci_internal_port_reset( |
73 | struct ehci_hcd *ehci, | 73 | struct ehci_hcd *ehci, |
74 | u32 __iomem *portsc_reg | 74 | u32 __iomem *portsc_reg |
75 | ) | 75 | ) |
76 | { | 76 | { |
77 | u32 temp; | 77 | u32 temp; |
78 | unsigned long flags; | 78 | unsigned long flags; |
79 | int retval = 0; | 79 | int retval = 0; |
80 | int i, tries; | 80 | int i, tries; |
81 | u32 saved_usbintr; | 81 | u32 saved_usbintr; |
82 | 82 | ||
83 | spin_lock_irqsave(&ehci->lock, flags); | 83 | spin_lock_irqsave(&ehci->lock, flags); |
84 | saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); | 84 | saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); |
85 | /* disable USB interrupt */ | 85 | /* disable USB interrupt */ |
86 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 86 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
87 | spin_unlock_irqrestore(&ehci->lock, flags); | 87 | spin_unlock_irqrestore(&ehci->lock, flags); |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * Here we have to do Port Reset at most twice for | 90 | * Here we have to do Port Reset at most twice for |
91 | * Port Enable bit to be set. | 91 | * Port Enable bit to be set. |
92 | */ | 92 | */ |
93 | for (i = 0; i < 2; i++) { | 93 | for (i = 0; i < 2; i++) { |
94 | temp = ehci_readl(ehci, portsc_reg); | 94 | temp = ehci_readl(ehci, portsc_reg); |
95 | temp |= PORT_RESET; | 95 | temp |= PORT_RESET; |
96 | ehci_writel(ehci, temp, portsc_reg); | 96 | ehci_writel(ehci, temp, portsc_reg); |
97 | mdelay(10); | 97 | mdelay(10); |
98 | temp &= ~PORT_RESET; | 98 | temp &= ~PORT_RESET; |
99 | ehci_writel(ehci, temp, portsc_reg); | 99 | ehci_writel(ehci, temp, portsc_reg); |
100 | mdelay(1); | 100 | mdelay(1); |
101 | tries = 100; | 101 | tries = 100; |
102 | do { | 102 | do { |
103 | mdelay(1); | 103 | mdelay(1); |
104 | /* | 104 | /* |
105 | * Up to this point, Port Enable bit is | 105 | * Up to this point, Port Enable bit is |
106 | * expected to be set after 2 ms waiting. | 106 | * expected to be set after 2 ms waiting. |
107 | * USB1 usually takes extra 45 ms, for safety, | 107 | * USB1 usually takes extra 45 ms, for safety, |
108 | * we take 100 ms as timeout. | 108 | * we take 100 ms as timeout. |
109 | */ | 109 | */ |
110 | temp = ehci_readl(ehci, portsc_reg); | 110 | temp = ehci_readl(ehci, portsc_reg); |
111 | } while (!(temp & PORT_PE) && tries--); | 111 | } while (!(temp & PORT_PE) && tries--); |
112 | if (temp & PORT_PE) | 112 | if (temp & PORT_PE) |
113 | break; | 113 | break; |
114 | } | 114 | } |
115 | if (i == 2) | 115 | if (i == 2) |
116 | retval = -ETIMEDOUT; | 116 | retval = -ETIMEDOUT; |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * Clear Connect Status Change bit if it's set. | 119 | * Clear Connect Status Change bit if it's set. |
120 | * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. | 120 | * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. |
121 | */ | 121 | */ |
122 | if (temp & PORT_CSC) | 122 | if (temp & PORT_CSC) |
123 | ehci_writel(ehci, PORT_CSC, portsc_reg); | 123 | ehci_writel(ehci, PORT_CSC, portsc_reg); |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Write to clear any interrupt status bits that might be set | 126 | * Write to clear any interrupt status bits that might be set |
127 | * during port reset. | 127 | * during port reset. |
128 | */ | 128 | */ |
129 | temp = ehci_readl(ehci, &ehci->regs->status); | 129 | temp = ehci_readl(ehci, &ehci->regs->status); |
130 | ehci_writel(ehci, temp, &ehci->regs->status); | 130 | ehci_writel(ehci, temp, &ehci->regs->status); |
131 | 131 | ||
132 | /* restore original interrupt enable bits */ | 132 | /* restore original interrupt enable bits */ |
133 | ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); | 133 | ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); |
134 | return retval; | 134 | return retval; |
135 | } | 135 | } |
136 | 136 | ||
137 | static int tegra_ehci_hub_control( | 137 | static int tegra_ehci_hub_control( |
138 | struct usb_hcd *hcd, | 138 | struct usb_hcd *hcd, |
139 | u16 typeReq, | 139 | u16 typeReq, |
140 | u16 wValue, | 140 | u16 wValue, |
141 | u16 wIndex, | 141 | u16 wIndex, |
142 | char *buf, | 142 | char *buf, |
143 | u16 wLength | 143 | u16 wLength |
144 | ) | 144 | ) |
145 | { | 145 | { |
146 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 146 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
147 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 147 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
148 | u32 __iomem *status_reg; | 148 | u32 __iomem *status_reg; |
149 | u32 temp; | 149 | u32 temp; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | int retval = 0; | 151 | int retval = 0; |
152 | 152 | ||
153 | status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; | 153 | status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; |
154 | 154 | ||
155 | spin_lock_irqsave(&ehci->lock, flags); | 155 | spin_lock_irqsave(&ehci->lock, flags); |
156 | 156 | ||
157 | if (typeReq == GetPortStatus) { | 157 | if (typeReq == GetPortStatus) { |
158 | temp = ehci_readl(ehci, status_reg); | 158 | temp = ehci_readl(ehci, status_reg); |
159 | if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { | 159 | if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { |
160 | /* Resume completed, re-enable disconnect detection */ | 160 | /* Resume completed, re-enable disconnect detection */ |
161 | tegra->port_resuming = 0; | 161 | tegra->port_resuming = 0; |
162 | tegra_usb_phy_postresume(tegra->phy); | 162 | tegra_usb_phy_postresume(hcd->phy); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { | 166 | else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { |
167 | temp = ehci_readl(ehci, status_reg); | 167 | temp = ehci_readl(ehci, status_reg); |
168 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { | 168 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { |
169 | retval = -EPIPE; | 169 | retval = -EPIPE; |
170 | goto done; | 170 | goto done; |
171 | } | 171 | } |
172 | 172 | ||
173 | temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); | 173 | temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); |
174 | temp |= PORT_WKDISC_E | PORT_WKOC_E; | 174 | temp |= PORT_WKDISC_E | PORT_WKOC_E; |
175 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); | 175 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); |
176 | 176 | ||
177 | /* | 177 | /* |
178 | * If a transaction is in progress, there may be a delay in | 178 | * If a transaction is in progress, there may be a delay in |
179 | * suspending the port. Poll until the port is suspended. | 179 | * suspending the port. Poll until the port is suspended. |
180 | */ | 180 | */ |
181 | if (handshake(ehci, status_reg, PORT_SUSPEND, | 181 | if (handshake(ehci, status_reg, PORT_SUSPEND, |
182 | PORT_SUSPEND, 5000)) | 182 | PORT_SUSPEND, 5000)) |
183 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); | 183 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); |
184 | 184 | ||
185 | set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); | 185 | set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); |
186 | goto done; | 186 | goto done; |
187 | } | 187 | } |
188 | 188 | ||
189 | /* For USB1 port we need to issue Port Reset twice internally */ | 189 | /* For USB1 port we need to issue Port Reset twice internally */ |
190 | if (tegra->needs_double_reset && | 190 | if (tegra->needs_double_reset && |
191 | (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { | 191 | (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { |
192 | spin_unlock_irqrestore(&ehci->lock, flags); | 192 | spin_unlock_irqrestore(&ehci->lock, flags); |
193 | return tegra_ehci_internal_port_reset(ehci, status_reg); | 193 | return tegra_ehci_internal_port_reset(ehci, status_reg); |
194 | } | 194 | } |
195 | 195 | ||
196 | /* | 196 | /* |
197 | * Tegra host controller will time the resume operation to clear the bit | 197 | * Tegra host controller will time the resume operation to clear the bit |
198 | * when the port control state switches to HS or FS Idle. This behavior | 198 | * when the port control state switches to HS or FS Idle. This behavior |
199 | * is different from EHCI where the host controller driver is required | 199 | * is different from EHCI where the host controller driver is required |
200 | * to set this bit to a zero after the resume duration is timed in the | 200 | * to set this bit to a zero after the resume duration is timed in the |
201 | * driver. | 201 | * driver. |
202 | */ | 202 | */ |
203 | else if (typeReq == ClearPortFeature && | 203 | else if (typeReq == ClearPortFeature && |
204 | wValue == USB_PORT_FEAT_SUSPEND) { | 204 | wValue == USB_PORT_FEAT_SUSPEND) { |
205 | temp = ehci_readl(ehci, status_reg); | 205 | temp = ehci_readl(ehci, status_reg); |
206 | if ((temp & PORT_RESET) || !(temp & PORT_PE)) { | 206 | if ((temp & PORT_RESET) || !(temp & PORT_PE)) { |
207 | retval = -EPIPE; | 207 | retval = -EPIPE; |
208 | goto done; | 208 | goto done; |
209 | } | 209 | } |
210 | 210 | ||
211 | if (!(temp & PORT_SUSPEND)) | 211 | if (!(temp & PORT_SUSPEND)) |
212 | goto done; | 212 | goto done; |
213 | 213 | ||
214 | /* Disable disconnect detection during port resume */ | 214 | /* Disable disconnect detection during port resume */ |
215 | tegra_usb_phy_preresume(tegra->phy); | 215 | tegra_usb_phy_preresume(hcd->phy); |
216 | 216 | ||
217 | ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); | 217 | ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); |
218 | 218 | ||
219 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); | 219 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); |
220 | /* start resume signalling */ | 220 | /* start resume signalling */ |
221 | ehci_writel(ehci, temp | PORT_RESUME, status_reg); | 221 | ehci_writel(ehci, temp | PORT_RESUME, status_reg); |
222 | set_bit(wIndex-1, &ehci->resuming_ports); | 222 | set_bit(wIndex-1, &ehci->resuming_ports); |
223 | 223 | ||
224 | spin_unlock_irqrestore(&ehci->lock, flags); | 224 | spin_unlock_irqrestore(&ehci->lock, flags); |
225 | msleep(20); | 225 | msleep(20); |
226 | spin_lock_irqsave(&ehci->lock, flags); | 226 | spin_lock_irqsave(&ehci->lock, flags); |
227 | 227 | ||
228 | /* Poll until the controller clears RESUME and SUSPEND */ | 228 | /* Poll until the controller clears RESUME and SUSPEND */ |
229 | if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) | 229 | if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) |
230 | pr_err("%s: timeout waiting for RESUME\n", __func__); | 230 | pr_err("%s: timeout waiting for RESUME\n", __func__); |
231 | if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) | 231 | if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) |
232 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); | 232 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); |
233 | 233 | ||
234 | ehci->reset_done[wIndex-1] = 0; | 234 | ehci->reset_done[wIndex-1] = 0; |
235 | clear_bit(wIndex-1, &ehci->resuming_ports); | 235 | clear_bit(wIndex-1, &ehci->resuming_ports); |
236 | 236 | ||
237 | tegra->port_resuming = 1; | 237 | tegra->port_resuming = 1; |
238 | goto done; | 238 | goto done; |
239 | } | 239 | } |
240 | 240 | ||
241 | spin_unlock_irqrestore(&ehci->lock, flags); | 241 | spin_unlock_irqrestore(&ehci->lock, flags); |
242 | 242 | ||
243 | /* Handle the hub control events here */ | 243 | /* Handle the hub control events here */ |
244 | return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); | 244 | return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); |
245 | done: | 245 | done: |
246 | spin_unlock_irqrestore(&ehci->lock, flags); | 246 | spin_unlock_irqrestore(&ehci->lock, flags); |
247 | return retval; | 247 | return retval; |
248 | } | 248 | } |
249 | 249 | ||
250 | static void tegra_ehci_restart(struct usb_hcd *hcd) | 250 | static void tegra_ehci_restart(struct usb_hcd *hcd) |
251 | { | 251 | { |
252 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 252 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
253 | 253 | ||
254 | ehci_reset(ehci); | 254 | ehci_reset(ehci); |
255 | 255 | ||
256 | /* setup the frame list and Async q heads */ | 256 | /* setup the frame list and Async q heads */ |
257 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); | 257 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); |
258 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); | 258 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); |
259 | /* setup the command register and set the controller in RUN mode */ | 259 | /* setup the command register and set the controller in RUN mode */ |
260 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | 260 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); |
261 | ehci->command |= CMD_RUN; | 261 | ehci->command |= CMD_RUN; |
262 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | 262 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
263 | 263 | ||
264 | down_write(&ehci_cf_port_reset_rwsem); | 264 | down_write(&ehci_cf_port_reset_rwsem); |
265 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | 265 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
266 | /* flush posted writes */ | 266 | /* flush posted writes */ |
267 | ehci_readl(ehci, &ehci->regs->command); | 267 | ehci_readl(ehci, &ehci->regs->command); |
268 | up_write(&ehci_cf_port_reset_rwsem); | 268 | up_write(&ehci_cf_port_reset_rwsem); |
269 | } | 269 | } |
270 | 270 | ||
271 | static void tegra_ehci_shutdown(struct usb_hcd *hcd) | 271 | static void tegra_ehci_shutdown(struct usb_hcd *hcd) |
272 | { | 272 | { |
273 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 273 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
274 | 274 | ||
275 | /* ehci_shutdown touches the USB controller registers, make sure | 275 | /* ehci_shutdown touches the USB controller registers, make sure |
276 | * controller has clocks to it */ | 276 | * controller has clocks to it */ |
277 | if (!tegra->host_resumed) | 277 | if (!tegra->host_resumed) |
278 | tegra_ehci_power_up(hcd); | 278 | tegra_ehci_power_up(hcd); |
279 | 279 | ||
280 | ehci_shutdown(hcd); | 280 | ehci_shutdown(hcd); |
281 | } | 281 | } |
282 | 282 | ||
283 | static int tegra_ehci_setup(struct usb_hcd *hcd) | 283 | static int tegra_ehci_setup(struct usb_hcd *hcd) |
284 | { | 284 | { |
285 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 285 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
286 | 286 | ||
287 | /* EHCI registers start at offset 0x100 */ | 287 | /* EHCI registers start at offset 0x100 */ |
288 | ehci->caps = hcd->regs + 0x100; | 288 | ehci->caps = hcd->regs + 0x100; |
289 | 289 | ||
290 | /* switch to host mode */ | 290 | /* switch to host mode */ |
291 | hcd->has_tt = 1; | 291 | hcd->has_tt = 1; |
292 | 292 | ||
293 | return ehci_setup(hcd); | 293 | return ehci_setup(hcd); |
294 | } | 294 | } |
295 | 295 | ||
296 | struct dma_aligned_buffer { | 296 | struct dma_aligned_buffer { |
297 | void *kmalloc_ptr; | 297 | void *kmalloc_ptr; |
298 | void *old_xfer_buffer; | 298 | void *old_xfer_buffer; |
299 | u8 data[0]; | 299 | u8 data[0]; |
300 | }; | 300 | }; |
301 | 301 | ||
302 | static void free_dma_aligned_buffer(struct urb *urb) | 302 | static void free_dma_aligned_buffer(struct urb *urb) |
303 | { | 303 | { |
304 | struct dma_aligned_buffer *temp; | 304 | struct dma_aligned_buffer *temp; |
305 | 305 | ||
306 | if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) | 306 | if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) |
307 | return; | 307 | return; |
308 | 308 | ||
309 | temp = container_of(urb->transfer_buffer, | 309 | temp = container_of(urb->transfer_buffer, |
310 | struct dma_aligned_buffer, data); | 310 | struct dma_aligned_buffer, data); |
311 | 311 | ||
312 | if (usb_urb_dir_in(urb)) | 312 | if (usb_urb_dir_in(urb)) |
313 | memcpy(temp->old_xfer_buffer, temp->data, | 313 | memcpy(temp->old_xfer_buffer, temp->data, |
314 | urb->transfer_buffer_length); | 314 | urb->transfer_buffer_length); |
315 | urb->transfer_buffer = temp->old_xfer_buffer; | 315 | urb->transfer_buffer = temp->old_xfer_buffer; |
316 | kfree(temp->kmalloc_ptr); | 316 | kfree(temp->kmalloc_ptr); |
317 | 317 | ||
318 | urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; | 318 | urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; |
319 | } | 319 | } |
320 | 320 | ||
321 | static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) | 321 | static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) |
322 | { | 322 | { |
323 | struct dma_aligned_buffer *temp, *kmalloc_ptr; | 323 | struct dma_aligned_buffer *temp, *kmalloc_ptr; |
324 | size_t kmalloc_size; | 324 | size_t kmalloc_size; |
325 | 325 | ||
326 | if (urb->num_sgs || urb->sg || | 326 | if (urb->num_sgs || urb->sg || |
327 | urb->transfer_buffer_length == 0 || | 327 | urb->transfer_buffer_length == 0 || |
328 | !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) | 328 | !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) |
329 | return 0; | 329 | return 0; |
330 | 330 | ||
331 | /* Allocate a buffer with enough padding for alignment */ | 331 | /* Allocate a buffer with enough padding for alignment */ |
332 | kmalloc_size = urb->transfer_buffer_length + | 332 | kmalloc_size = urb->transfer_buffer_length + |
333 | sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; | 333 | sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; |
334 | 334 | ||
335 | kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); | 335 | kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); |
336 | if (!kmalloc_ptr) | 336 | if (!kmalloc_ptr) |
337 | return -ENOMEM; | 337 | return -ENOMEM; |
338 | 338 | ||
339 | /* Position our struct dma_aligned_buffer such that data is aligned */ | 339 | /* Position our struct dma_aligned_buffer such that data is aligned */ |
340 | temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; | 340 | temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; |
341 | temp->kmalloc_ptr = kmalloc_ptr; | 341 | temp->kmalloc_ptr = kmalloc_ptr; |
342 | temp->old_xfer_buffer = urb->transfer_buffer; | 342 | temp->old_xfer_buffer = urb->transfer_buffer; |
343 | if (usb_urb_dir_out(urb)) | 343 | if (usb_urb_dir_out(urb)) |
344 | memcpy(temp->data, urb->transfer_buffer, | 344 | memcpy(temp->data, urb->transfer_buffer, |
345 | urb->transfer_buffer_length); | 345 | urb->transfer_buffer_length); |
346 | urb->transfer_buffer = temp->data; | 346 | urb->transfer_buffer = temp->data; |
347 | 347 | ||
348 | urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; | 348 | urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; |
349 | 349 | ||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
353 | static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | 353 | static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, |
354 | gfp_t mem_flags) | 354 | gfp_t mem_flags) |
355 | { | 355 | { |
356 | int ret; | 356 | int ret; |
357 | 357 | ||
358 | ret = alloc_dma_aligned_buffer(urb, mem_flags); | 358 | ret = alloc_dma_aligned_buffer(urb, mem_flags); |
359 | if (ret) | 359 | if (ret) |
360 | return ret; | 360 | return ret; |
361 | 361 | ||
362 | ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); | 362 | ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); |
363 | if (ret) | 363 | if (ret) |
364 | free_dma_aligned_buffer(urb); | 364 | free_dma_aligned_buffer(urb); |
365 | 365 | ||
366 | return ret; | 366 | return ret; |
367 | } | 367 | } |
368 | 368 | ||
369 | static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | 369 | static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) |
370 | { | 370 | { |
371 | usb_hcd_unmap_urb_for_dma(hcd, urb); | 371 | usb_hcd_unmap_urb_for_dma(hcd, urb); |
372 | free_dma_aligned_buffer(urb); | 372 | free_dma_aligned_buffer(urb); |
373 | } | 373 | } |
374 | 374 | ||
375 | static const struct hc_driver tegra_ehci_hc_driver = { | 375 | static const struct hc_driver tegra_ehci_hc_driver = { |
376 | .description = hcd_name, | 376 | .description = hcd_name, |
377 | .product_desc = "Tegra EHCI Host Controller", | 377 | .product_desc = "Tegra EHCI Host Controller", |
378 | .hcd_priv_size = sizeof(struct ehci_hcd), | 378 | .hcd_priv_size = sizeof(struct ehci_hcd), |
379 | .flags = HCD_USB2 | HCD_MEMORY, | 379 | .flags = HCD_USB2 | HCD_MEMORY, |
380 | 380 | ||
381 | /* standard ehci functions */ | 381 | /* standard ehci functions */ |
382 | .irq = ehci_irq, | 382 | .irq = ehci_irq, |
383 | .start = ehci_run, | 383 | .start = ehci_run, |
384 | .stop = ehci_stop, | 384 | .stop = ehci_stop, |
385 | .urb_enqueue = ehci_urb_enqueue, | 385 | .urb_enqueue = ehci_urb_enqueue, |
386 | .urb_dequeue = ehci_urb_dequeue, | 386 | .urb_dequeue = ehci_urb_dequeue, |
387 | .endpoint_disable = ehci_endpoint_disable, | 387 | .endpoint_disable = ehci_endpoint_disable, |
388 | .endpoint_reset = ehci_endpoint_reset, | 388 | .endpoint_reset = ehci_endpoint_reset, |
389 | .get_frame_number = ehci_get_frame, | 389 | .get_frame_number = ehci_get_frame, |
390 | .hub_status_data = ehci_hub_status_data, | 390 | .hub_status_data = ehci_hub_status_data, |
391 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | 391 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, |
392 | .relinquish_port = ehci_relinquish_port, | 392 | .relinquish_port = ehci_relinquish_port, |
393 | .port_handed_over = ehci_port_handed_over, | 393 | .port_handed_over = ehci_port_handed_over, |
394 | 394 | ||
395 | /* modified ehci functions for tegra */ | 395 | /* modified ehci functions for tegra */ |
396 | .reset = tegra_ehci_setup, | 396 | .reset = tegra_ehci_setup, |
397 | .shutdown = tegra_ehci_shutdown, | 397 | .shutdown = tegra_ehci_shutdown, |
398 | .map_urb_for_dma = tegra_ehci_map_urb_for_dma, | 398 | .map_urb_for_dma = tegra_ehci_map_urb_for_dma, |
399 | .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, | 399 | .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, |
400 | .hub_control = tegra_ehci_hub_control, | 400 | .hub_control = tegra_ehci_hub_control, |
401 | #ifdef CONFIG_PM | 401 | #ifdef CONFIG_PM |
402 | .bus_suspend = ehci_bus_suspend, | 402 | .bus_suspend = ehci_bus_suspend, |
403 | .bus_resume = ehci_bus_resume, | 403 | .bus_resume = ehci_bus_resume, |
404 | #endif | 404 | #endif |
405 | }; | 405 | }; |
406 | 406 | ||
407 | static int setup_vbus_gpio(struct platform_device *pdev, | 407 | static int setup_vbus_gpio(struct platform_device *pdev, |
408 | struct tegra_ehci_platform_data *pdata) | 408 | struct tegra_ehci_platform_data *pdata) |
409 | { | 409 | { |
410 | int err = 0; | 410 | int err = 0; |
411 | int gpio; | 411 | int gpio; |
412 | 412 | ||
413 | gpio = pdata->vbus_gpio; | 413 | gpio = pdata->vbus_gpio; |
414 | if (!gpio_is_valid(gpio)) | 414 | if (!gpio_is_valid(gpio)) |
415 | gpio = of_get_named_gpio(pdev->dev.of_node, | 415 | gpio = of_get_named_gpio(pdev->dev.of_node, |
416 | "nvidia,vbus-gpio", 0); | 416 | "nvidia,vbus-gpio", 0); |
417 | if (!gpio_is_valid(gpio)) | 417 | if (!gpio_is_valid(gpio)) |
418 | return 0; | 418 | return 0; |
419 | 419 | ||
420 | err = gpio_request(gpio, "vbus_gpio"); | 420 | err = gpio_request(gpio, "vbus_gpio"); |
421 | if (err) { | 421 | if (err) { |
422 | dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); | 422 | dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); |
423 | return err; | 423 | return err; |
424 | } | 424 | } |
425 | err = gpio_direction_output(gpio, 1); | 425 | err = gpio_direction_output(gpio, 1); |
426 | if (err) { | 426 | if (err) { |
427 | dev_err(&pdev->dev, "can't enable vbus\n"); | 427 | dev_err(&pdev->dev, "can't enable vbus\n"); |
428 | return err; | 428 | return err; |
429 | } | 429 | } |
430 | 430 | ||
431 | return err; | 431 | return err; |
432 | } | 432 | } |
433 | 433 | ||
434 | #ifdef CONFIG_PM | 434 | #ifdef CONFIG_PM |
435 | 435 | ||
436 | static int controller_suspend(struct device *dev) | 436 | static int controller_suspend(struct device *dev) |
437 | { | 437 | { |
438 | struct tegra_ehci_hcd *tegra = | 438 | struct tegra_ehci_hcd *tegra = |
439 | platform_get_drvdata(to_platform_device(dev)); | 439 | platform_get_drvdata(to_platform_device(dev)); |
440 | struct ehci_hcd *ehci = tegra->ehci; | 440 | struct ehci_hcd *ehci = tegra->ehci; |
441 | struct usb_hcd *hcd = ehci_to_hcd(ehci); | 441 | struct usb_hcd *hcd = ehci_to_hcd(ehci); |
442 | struct ehci_regs __iomem *hw = ehci->regs; | 442 | struct ehci_regs __iomem *hw = ehci->regs; |
443 | unsigned long flags; | 443 | unsigned long flags; |
444 | 444 | ||
445 | if (time_before(jiffies, ehci->next_statechange)) | 445 | if (time_before(jiffies, ehci->next_statechange)) |
446 | msleep(10); | 446 | msleep(10); |
447 | 447 | ||
448 | ehci_halt(ehci); | 448 | ehci_halt(ehci); |
449 | 449 | ||
450 | spin_lock_irqsave(&ehci->lock, flags); | 450 | spin_lock_irqsave(&ehci->lock, flags); |
451 | tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; | 451 | tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; |
452 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 452 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
453 | spin_unlock_irqrestore(&ehci->lock, flags); | 453 | spin_unlock_irqrestore(&ehci->lock, flags); |
454 | 454 | ||
455 | tegra_ehci_power_down(hcd); | 455 | tegra_ehci_power_down(hcd); |
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | static int controller_resume(struct device *dev) | 459 | static int controller_resume(struct device *dev) |
460 | { | 460 | { |
461 | struct tegra_ehci_hcd *tegra = | 461 | struct tegra_ehci_hcd *tegra = |
462 | platform_get_drvdata(to_platform_device(dev)); | 462 | platform_get_drvdata(to_platform_device(dev)); |
463 | struct ehci_hcd *ehci = tegra->ehci; | 463 | struct ehci_hcd *ehci = tegra->ehci; |
464 | struct usb_hcd *hcd = ehci_to_hcd(ehci); | 464 | struct usb_hcd *hcd = ehci_to_hcd(ehci); |
465 | struct ehci_regs __iomem *hw = ehci->regs; | 465 | struct ehci_regs __iomem *hw = ehci->regs; |
466 | unsigned long val; | 466 | unsigned long val; |
467 | 467 | ||
468 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 468 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
469 | tegra_ehci_power_up(hcd); | 469 | tegra_ehci_power_up(hcd); |
470 | 470 | ||
471 | if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { | 471 | if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { |
472 | /* Wait for the phy to detect new devices | 472 | /* Wait for the phy to detect new devices |
473 | * before we restart the controller */ | 473 | * before we restart the controller */ |
474 | msleep(10); | 474 | msleep(10); |
475 | goto restart; | 475 | goto restart; |
476 | } | 476 | } |
477 | 477 | ||
478 | /* Force the phy to keep data lines in suspend state */ | 478 | /* Force the phy to keep data lines in suspend state */ |
479 | tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); | 479 | tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed); |
480 | 480 | ||
481 | /* Enable host mode */ | 481 | /* Enable host mode */ |
482 | tdi_reset(ehci); | 482 | tdi_reset(ehci); |
483 | 483 | ||
484 | /* Enable Port Power */ | 484 | /* Enable Port Power */ |
485 | val = readl(&hw->port_status[0]); | 485 | val = readl(&hw->port_status[0]); |
486 | val |= PORT_POWER; | 486 | val |= PORT_POWER; |
487 | writel(val, &hw->port_status[0]); | 487 | writel(val, &hw->port_status[0]); |
488 | udelay(10); | 488 | udelay(10); |
489 | 489 | ||
490 | /* Check if the phy resume from LP0. When the phy resume from LP0 | 490 | /* Check if the phy resume from LP0. When the phy resume from LP0 |
491 | * USB register will be reset. */ | 491 | * USB register will be reset. */ |
492 | if (!readl(&hw->async_next)) { | 492 | if (!readl(&hw->async_next)) { |
493 | /* Program the field PTC based on the saved speed mode */ | 493 | /* Program the field PTC based on the saved speed mode */ |
494 | val = readl(&hw->port_status[0]); | 494 | val = readl(&hw->port_status[0]); |
495 | val &= ~PORT_TEST(~0); | 495 | val &= ~PORT_TEST(~0); |
496 | if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) | 496 | if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) |
497 | val |= PORT_TEST_FORCE; | 497 | val |= PORT_TEST_FORCE; |
498 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) | 498 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) |
499 | val |= PORT_TEST(6); | 499 | val |= PORT_TEST(6); |
500 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) | 500 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) |
501 | val |= PORT_TEST(7); | 501 | val |= PORT_TEST(7); |
502 | writel(val, &hw->port_status[0]); | 502 | writel(val, &hw->port_status[0]); |
503 | udelay(10); | 503 | udelay(10); |
504 | 504 | ||
505 | /* Disable test mode by setting PTC field to NORMAL_OP */ | 505 | /* Disable test mode by setting PTC field to NORMAL_OP */ |
506 | val = readl(&hw->port_status[0]); | 506 | val = readl(&hw->port_status[0]); |
507 | val &= ~PORT_TEST(~0); | 507 | val &= ~PORT_TEST(~0); |
508 | writel(val, &hw->port_status[0]); | 508 | writel(val, &hw->port_status[0]); |
509 | udelay(10); | 509 | udelay(10); |
510 | } | 510 | } |
511 | 511 | ||
512 | /* Poll until CCS is enabled */ | 512 | /* Poll until CCS is enabled */ |
513 | if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, | 513 | if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, |
514 | PORT_CONNECT, 2000)) { | 514 | PORT_CONNECT, 2000)) { |
515 | pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); | 515 | pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); |
516 | goto restart; | 516 | goto restart; |
517 | } | 517 | } |
518 | 518 | ||
519 | /* Poll until PE is enabled */ | 519 | /* Poll until PE is enabled */ |
520 | if (handshake(ehci, &hw->port_status[0], PORT_PE, | 520 | if (handshake(ehci, &hw->port_status[0], PORT_PE, |
521 | PORT_PE, 2000)) { | 521 | PORT_PE, 2000)) { |
522 | pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); | 522 | pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); |
523 | goto restart; | 523 | goto restart; |
524 | } | 524 | } |
525 | 525 | ||
526 | /* Clear the PCI status, to avoid an interrupt taken upon resume */ | 526 | /* Clear the PCI status, to avoid an interrupt taken upon resume */ |
527 | val = readl(&hw->status); | 527 | val = readl(&hw->status); |
528 | val |= STS_PCD; | 528 | val |= STS_PCD; |
529 | writel(val, &hw->status); | 529 | writel(val, &hw->status); |
530 | 530 | ||
531 | /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ | 531 | /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ |
532 | val = readl(&hw->port_status[0]); | 532 | val = readl(&hw->port_status[0]); |
533 | if ((val & PORT_POWER) && (val & PORT_PE)) { | 533 | if ((val & PORT_POWER) && (val & PORT_PE)) { |
534 | val |= PORT_SUSPEND; | 534 | val |= PORT_SUSPEND; |
535 | writel(val, &hw->port_status[0]); | 535 | writel(val, &hw->port_status[0]); |
536 | 536 | ||
537 | /* Wait until port suspend completes */ | 537 | /* Wait until port suspend completes */ |
538 | if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, | 538 | if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, |
539 | PORT_SUSPEND, 1000)) { | 539 | PORT_SUSPEND, 1000)) { |
540 | pr_err("%s: timeout waiting for PORT_SUSPEND\n", | 540 | pr_err("%s: timeout waiting for PORT_SUSPEND\n", |
541 | __func__); | 541 | __func__); |
542 | goto restart; | 542 | goto restart; |
543 | } | 543 | } |
544 | } | 544 | } |
545 | 545 | ||
546 | tegra_ehci_phy_restore_end(tegra->phy); | 546 | tegra_ehci_phy_restore_end(hcd->phy); |
547 | goto done; | 547 | goto done; |
548 | 548 | ||
549 | restart: | 549 | restart: |
550 | if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) | 550 | if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) |
551 | tegra_ehci_phy_restore_end(tegra->phy); | 551 | tegra_ehci_phy_restore_end(hcd->phy); |
552 | 552 | ||
553 | tegra_ehci_restart(hcd); | 553 | tegra_ehci_restart(hcd); |
554 | 554 | ||
555 | done: | 555 | done: |
556 | tegra_usb_phy_preresume(tegra->phy); | 556 | tegra_usb_phy_preresume(hcd->phy); |
557 | tegra->port_resuming = 1; | 557 | tegra->port_resuming = 1; |
558 | return 0; | 558 | return 0; |
559 | } | 559 | } |
560 | 560 | ||
561 | static int tegra_ehci_suspend(struct device *dev) | 561 | static int tegra_ehci_suspend(struct device *dev) |
562 | { | 562 | { |
563 | struct tegra_ehci_hcd *tegra = | 563 | struct tegra_ehci_hcd *tegra = |
564 | platform_get_drvdata(to_platform_device(dev)); | 564 | platform_get_drvdata(to_platform_device(dev)); |
565 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | 565 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); |
566 | int rc = 0; | 566 | int rc = 0; |
567 | 567 | ||
568 | /* | 568 | /* |
569 | * When system sleep is supported and USB controller wakeup is | 569 | * When system sleep is supported and USB controller wakeup is |
570 | * implemented: If the controller is runtime-suspended and the | 570 | * implemented: If the controller is runtime-suspended and the |
571 | * wakeup setting needs to be changed, call pm_runtime_resume(). | 571 | * wakeup setting needs to be changed, call pm_runtime_resume(). |
572 | */ | 572 | */ |
573 | if (HCD_HW_ACCESSIBLE(hcd)) | 573 | if (HCD_HW_ACCESSIBLE(hcd)) |
574 | rc = controller_suspend(dev); | 574 | rc = controller_suspend(dev); |
575 | return rc; | 575 | return rc; |
576 | } | 576 | } |
577 | 577 | ||
578 | static int tegra_ehci_resume(struct device *dev) | 578 | static int tegra_ehci_resume(struct device *dev) |
579 | { | 579 | { |
580 | int rc; | 580 | int rc; |
581 | 581 | ||
582 | rc = controller_resume(dev); | 582 | rc = controller_resume(dev); |
583 | if (rc == 0) { | 583 | if (rc == 0) { |
584 | pm_runtime_disable(dev); | 584 | pm_runtime_disable(dev); |
585 | pm_runtime_set_active(dev); | 585 | pm_runtime_set_active(dev); |
586 | pm_runtime_enable(dev); | 586 | pm_runtime_enable(dev); |
587 | } | 587 | } |
588 | return rc; | 588 | return rc; |
589 | } | 589 | } |
590 | 590 | ||
591 | static int tegra_ehci_runtime_suspend(struct device *dev) | 591 | static int tegra_ehci_runtime_suspend(struct device *dev) |
592 | { | 592 | { |
593 | return controller_suspend(dev); | 593 | return controller_suspend(dev); |
594 | } | 594 | } |
595 | 595 | ||
596 | static int tegra_ehci_runtime_resume(struct device *dev) | 596 | static int tegra_ehci_runtime_resume(struct device *dev) |
597 | { | 597 | { |
598 | return controller_resume(dev); | 598 | return controller_resume(dev); |
599 | } | 599 | } |
600 | 600 | ||
601 | static const struct dev_pm_ops tegra_ehci_pm_ops = { | 601 | static const struct dev_pm_ops tegra_ehci_pm_ops = { |
602 | .suspend = tegra_ehci_suspend, | 602 | .suspend = tegra_ehci_suspend, |
603 | .resume = tegra_ehci_resume, | 603 | .resume = tegra_ehci_resume, |
604 | .runtime_suspend = tegra_ehci_runtime_suspend, | 604 | .runtime_suspend = tegra_ehci_runtime_suspend, |
605 | .runtime_resume = tegra_ehci_runtime_resume, | 605 | .runtime_resume = tegra_ehci_runtime_resume, |
606 | }; | 606 | }; |
607 | 607 | ||
608 | #endif | 608 | #endif |
609 | 609 | ||
610 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ | 610 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ |
611 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | 611 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) |
612 | 612 | ||
613 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) | 613 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) |
614 | { | 614 | { |
615 | unsigned long val; | 615 | unsigned long val; |
616 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | 616 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); |
617 | void __iomem *base = hcd->regs; | 617 | void __iomem *base = hcd->regs; |
618 | 618 | ||
619 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | 619 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; |
620 | val &= ~TEGRA_USB_PORTSC1_PTS(3); | 620 | val &= ~TEGRA_USB_PORTSC1_PTS(3); |
621 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); | 621 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); |
622 | writel(val, base + TEGRA_USB_PORTSC1); | 622 | writel(val, base + TEGRA_USB_PORTSC1); |
623 | } | 623 | } |
624 | EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); | 624 | EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); |
625 | 625 | ||
626 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) | 626 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) |
627 | { | 627 | { |
628 | unsigned long val; | 628 | unsigned long val; |
629 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | 629 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); |
630 | void __iomem *base = hcd->regs; | 630 | void __iomem *base = hcd->regs; |
631 | 631 | ||
632 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | 632 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; |
633 | if (enable) | 633 | if (enable) |
634 | val |= TEGRA_USB_PORTSC1_PHCD; | 634 | val |= TEGRA_USB_PORTSC1_PHCD; |
635 | else | 635 | else |
636 | val &= ~TEGRA_USB_PORTSC1_PHCD; | 636 | val &= ~TEGRA_USB_PORTSC1_PHCD; |
637 | writel(val, base + TEGRA_USB_PORTSC1); | 637 | writel(val, base + TEGRA_USB_PORTSC1); |
638 | } | 638 | } |
639 | EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); | 639 | EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); |
640 | 640 | ||
641 | static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); | 641 | static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); |
642 | 642 | ||
643 | static int tegra_ehci_probe(struct platform_device *pdev) | 643 | static int tegra_ehci_probe(struct platform_device *pdev) |
644 | { | 644 | { |
645 | struct resource *res; | 645 | struct resource *res; |
646 | struct usb_hcd *hcd; | 646 | struct usb_hcd *hcd; |
647 | struct tegra_ehci_hcd *tegra; | 647 | struct tegra_ehci_hcd *tegra; |
648 | struct tegra_ehci_platform_data *pdata; | 648 | struct tegra_ehci_platform_data *pdata; |
649 | int err = 0; | 649 | int err = 0; |
650 | int irq; | 650 | int irq; |
651 | int instance = pdev->id; | 651 | int instance = pdev->id; |
652 | struct usb_phy *u_phy; | 652 | struct usb_phy *u_phy; |
653 | 653 | ||
654 | pdata = pdev->dev.platform_data; | 654 | pdata = pdev->dev.platform_data; |
655 | if (!pdata) { | 655 | if (!pdata) { |
656 | dev_err(&pdev->dev, "Platform data missing\n"); | 656 | dev_err(&pdev->dev, "Platform data missing\n"); |
657 | return -EINVAL; | 657 | return -EINVAL; |
658 | } | 658 | } |
659 | 659 | ||
660 | /* Right now device-tree probed devices don't get dma_mask set. | 660 | /* Right now device-tree probed devices don't get dma_mask set. |
661 | * Since shared usb code relies on it, set it here for now. | 661 | * Since shared usb code relies on it, set it here for now. |
662 | * Once we have dma capability bindings this can go away. | 662 | * Once we have dma capability bindings this can go away. |
663 | */ | 663 | */ |
664 | if (!pdev->dev.dma_mask) | 664 | if (!pdev->dev.dma_mask) |
665 | pdev->dev.dma_mask = &tegra_ehci_dma_mask; | 665 | pdev->dev.dma_mask = &tegra_ehci_dma_mask; |
666 | 666 | ||
667 | setup_vbus_gpio(pdev, pdata); | 667 | setup_vbus_gpio(pdev, pdata); |
668 | 668 | ||
669 | tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), | 669 | tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), |
670 | GFP_KERNEL); | 670 | GFP_KERNEL); |
671 | if (!tegra) | 671 | if (!tegra) |
672 | return -ENOMEM; | 672 | return -ENOMEM; |
673 | 673 | ||
674 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, | 674 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, |
675 | dev_name(&pdev->dev)); | 675 | dev_name(&pdev->dev)); |
676 | if (!hcd) { | 676 | if (!hcd) { |
677 | dev_err(&pdev->dev, "Unable to create HCD\n"); | 677 | dev_err(&pdev->dev, "Unable to create HCD\n"); |
678 | return -ENOMEM; | 678 | return -ENOMEM; |
679 | } | 679 | } |
680 | 680 | ||
681 | platform_set_drvdata(pdev, tegra); | 681 | platform_set_drvdata(pdev, tegra); |
682 | 682 | ||
683 | tegra->clk = devm_clk_get(&pdev->dev, NULL); | 683 | tegra->clk = devm_clk_get(&pdev->dev, NULL); |
684 | if (IS_ERR(tegra->clk)) { | 684 | if (IS_ERR(tegra->clk)) { |
685 | dev_err(&pdev->dev, "Can't get ehci clock\n"); | 685 | dev_err(&pdev->dev, "Can't get ehci clock\n"); |
686 | err = PTR_ERR(tegra->clk); | 686 | err = PTR_ERR(tegra->clk); |
687 | goto fail_clk; | 687 | goto fail_clk; |
688 | } | 688 | } |
689 | 689 | ||
690 | err = clk_prepare_enable(tegra->clk); | 690 | err = clk_prepare_enable(tegra->clk); |
691 | if (err) | 691 | if (err) |
692 | goto fail_clk; | 692 | goto fail_clk; |
693 | 693 | ||
694 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, | 694 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, |
695 | "nvidia,needs-double-reset"); | 695 | "nvidia,needs-double-reset"); |
696 | 696 | ||
697 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 697 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
698 | if (!res) { | 698 | if (!res) { |
699 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | 699 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); |
700 | err = -ENXIO; | 700 | err = -ENXIO; |
701 | goto fail_io; | 701 | goto fail_io; |
702 | } | 702 | } |
703 | hcd->rsrc_start = res->start; | 703 | hcd->rsrc_start = res->start; |
704 | hcd->rsrc_len = resource_size(res); | 704 | hcd->rsrc_len = resource_size(res); |
705 | hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | 705 | hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
706 | if (!hcd->regs) { | 706 | if (!hcd->regs) { |
707 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | 707 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); |
708 | err = -ENOMEM; | 708 | err = -ENOMEM; |
709 | goto fail_io; | 709 | goto fail_io; |
710 | } | 710 | } |
711 | 711 | ||
712 | /* This is pretty ugly and needs to be fixed when we do only | 712 | /* This is pretty ugly and needs to be fixed when we do only |
713 | * device-tree probing. Old code relies on the platform_device | 713 | * device-tree probing. Old code relies on the platform_device |
714 | * numbering that we lack for device-tree-instantiated devices. | 714 | * numbering that we lack for device-tree-instantiated devices. |
715 | */ | 715 | */ |
716 | if (instance < 0) { | 716 | if (instance < 0) { |
717 | switch (res->start) { | 717 | switch (res->start) { |
718 | case TEGRA_USB_BASE: | 718 | case TEGRA_USB_BASE: |
719 | instance = 0; | 719 | instance = 0; |
720 | break; | 720 | break; |
721 | case TEGRA_USB2_BASE: | 721 | case TEGRA_USB2_BASE: |
722 | instance = 1; | 722 | instance = 1; |
723 | break; | 723 | break; |
724 | case TEGRA_USB3_BASE: | 724 | case TEGRA_USB3_BASE: |
725 | instance = 2; | 725 | instance = 2; |
726 | break; | 726 | break; |
727 | default: | 727 | default: |
728 | err = -ENODEV; | 728 | err = -ENODEV; |
729 | dev_err(&pdev->dev, "unknown usb instance\n"); | 729 | dev_err(&pdev->dev, "unknown usb instance\n"); |
730 | goto fail_io; | 730 | goto fail_io; |
731 | } | 731 | } |
732 | } | 732 | } |
733 | 733 | ||
734 | tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, | 734 | tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, |
735 | pdata->phy_config, | 735 | pdata->phy_config, |
736 | TEGRA_USB_PHY_MODE_HOST); | 736 | TEGRA_USB_PHY_MODE_HOST); |
737 | if (IS_ERR(tegra->phy)) { | 737 | if (IS_ERR(tegra->phy)) { |
738 | dev_err(&pdev->dev, "Failed to open USB phy\n"); | 738 | dev_err(&pdev->dev, "Failed to open USB phy\n"); |
739 | err = -ENXIO; | 739 | err = -ENXIO; |
740 | goto fail_io; | 740 | goto fail_io; |
741 | } | 741 | } |
742 | 742 | ||
743 | usb_phy_init(&tegra->phy->u_phy); | ||
744 | |||
745 | hcd->phy = u_phy = &tegra->phy->u_phy; | 743 | hcd->phy = u_phy = &tegra->phy->u_phy; |
744 | usb_phy_init(hcd->phy); | ||
745 | |||
746 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), | 746 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), |
747 | GFP_KERNEL); | 747 | GFP_KERNEL); |
748 | if (!u_phy->otg) { | 748 | if (!u_phy->otg) { |
749 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); | 749 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); |
750 | err = -ENOMEM; | 750 | err = -ENOMEM; |
751 | goto fail_io; | 751 | goto fail_io; |
752 | } | 752 | } |
753 | u_phy->otg->host = hcd_to_bus(hcd); | 753 | u_phy->otg->host = hcd_to_bus(hcd); |
754 | 754 | ||
755 | err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); | 755 | err = usb_phy_set_suspend(hcd->phy, 0); |
756 | if (err) { | 756 | if (err) { |
757 | dev_err(&pdev->dev, "Failed to power on the phy\n"); | 757 | dev_err(&pdev->dev, "Failed to power on the phy\n"); |
758 | goto fail; | 758 | goto fail; |
759 | } | 759 | } |
760 | 760 | ||
761 | tegra->host_resumed = 1; | 761 | tegra->host_resumed = 1; |
762 | tegra->ehci = hcd_to_ehci(hcd); | 762 | tegra->ehci = hcd_to_ehci(hcd); |
763 | 763 | ||
764 | irq = platform_get_irq(pdev, 0); | 764 | irq = platform_get_irq(pdev, 0); |
765 | if (!irq) { | 765 | if (!irq) { |
766 | dev_err(&pdev->dev, "Failed to get IRQ\n"); | 766 | dev_err(&pdev->dev, "Failed to get IRQ\n"); |
767 | err = -ENODEV; | 767 | err = -ENODEV; |
768 | goto fail; | 768 | goto fail; |
769 | } | 769 | } |
770 | 770 | ||
771 | #ifdef CONFIG_USB_OTG_UTILS | 771 | #ifdef CONFIG_USB_OTG_UTILS |
772 | if (pdata->operating_mode == TEGRA_USB_OTG) { | 772 | if (pdata->operating_mode == TEGRA_USB_OTG) { |
773 | tegra->transceiver = | 773 | tegra->transceiver = |
774 | devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); | 774 | devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); |
775 | if (!IS_ERR_OR_NULL(tegra->transceiver)) | 775 | if (!IS_ERR_OR_NULL(tegra->transceiver)) |
776 | otg_set_host(tegra->transceiver->otg, &hcd->self); | 776 | otg_set_host(tegra->transceiver->otg, &hcd->self); |
777 | } | 777 | } |
778 | #endif | 778 | #endif |
779 | 779 | ||
780 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); | 780 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
781 | if (err) { | 781 | if (err) { |
782 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); | 782 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
783 | goto fail; | 783 | goto fail; |
784 | } | 784 | } |
785 | 785 | ||
786 | pm_runtime_set_active(&pdev->dev); | 786 | pm_runtime_set_active(&pdev->dev); |
787 | pm_runtime_get_noresume(&pdev->dev); | 787 | pm_runtime_get_noresume(&pdev->dev); |
788 | 788 | ||
789 | /* Don't skip the pm_runtime_forbid call if wakeup isn't working */ | 789 | /* Don't skip the pm_runtime_forbid call if wakeup isn't working */ |
790 | /* if (!pdata->power_down_on_bus_suspend) */ | 790 | /* if (!pdata->power_down_on_bus_suspend) */ |
791 | pm_runtime_forbid(&pdev->dev); | 791 | pm_runtime_forbid(&pdev->dev); |
792 | pm_runtime_enable(&pdev->dev); | 792 | pm_runtime_enable(&pdev->dev); |
793 | pm_runtime_put_sync(&pdev->dev); | 793 | pm_runtime_put_sync(&pdev->dev); |
794 | return err; | 794 | return err; |
795 | 795 | ||
796 | fail: | 796 | fail: |
797 | #ifdef CONFIG_USB_OTG_UTILS | 797 | #ifdef CONFIG_USB_OTG_UTILS |
798 | if (!IS_ERR_OR_NULL(tegra->transceiver)) | 798 | if (!IS_ERR_OR_NULL(tegra->transceiver)) |
799 | otg_set_host(tegra->transceiver->otg, NULL); | 799 | otg_set_host(tegra->transceiver->otg, NULL); |
800 | #endif | 800 | #endif |
801 | usb_phy_shutdown(&tegra->phy->u_phy); | 801 | usb_phy_shutdown(hcd->phy); |
802 | fail_io: | 802 | fail_io: |
803 | clk_disable_unprepare(tegra->clk); | 803 | clk_disable_unprepare(tegra->clk); |
804 | fail_clk: | 804 | fail_clk: |
805 | usb_put_hcd(hcd); | 805 | usb_put_hcd(hcd); |
806 | return err; | 806 | return err; |
807 | } | 807 | } |
808 | 808 | ||
809 | static int tegra_ehci_remove(struct platform_device *pdev) | 809 | static int tegra_ehci_remove(struct platform_device *pdev) |
810 | { | 810 | { |
811 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); | 811 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); |
812 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | 812 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); |
813 | 813 | ||
814 | pm_runtime_get_sync(&pdev->dev); | 814 | pm_runtime_get_sync(&pdev->dev); |
815 | pm_runtime_disable(&pdev->dev); | 815 | pm_runtime_disable(&pdev->dev); |
816 | pm_runtime_put_noidle(&pdev->dev); | 816 | pm_runtime_put_noidle(&pdev->dev); |
817 | 817 | ||
818 | #ifdef CONFIG_USB_OTG_UTILS | 818 | #ifdef CONFIG_USB_OTG_UTILS |
819 | if (!IS_ERR_OR_NULL(tegra->transceiver)) | 819 | if (!IS_ERR_OR_NULL(tegra->transceiver)) |
820 | otg_set_host(tegra->transceiver->otg, NULL); | 820 | otg_set_host(tegra->transceiver->otg, NULL); |
821 | #endif | 821 | #endif |
822 | 822 | ||
823 | usb_phy_shutdown(hcd->phy); | ||
823 | usb_remove_hcd(hcd); | 824 | usb_remove_hcd(hcd); |
824 | usb_put_hcd(hcd); | 825 | usb_put_hcd(hcd); |
825 | |||
826 | usb_phy_shutdown(&tegra->phy->u_phy); | ||
827 | 826 | ||
828 | clk_disable_unprepare(tegra->clk); | 827 | clk_disable_unprepare(tegra->clk); |
829 | 828 | ||
830 | return 0; | 829 | return 0; |
831 | } | 830 | } |
832 | 831 | ||
833 | static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) | 832 | static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) |
834 | { | 833 | { |
835 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); | 834 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); |
836 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | 835 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); |
837 | 836 | ||
838 | if (hcd->driver->shutdown) | 837 | if (hcd->driver->shutdown) |
839 | hcd->driver->shutdown(hcd); | 838 | hcd->driver->shutdown(hcd); |
840 | } | 839 | } |
841 | 840 | ||
842 | static struct of_device_id tegra_ehci_of_match[] = { | 841 | static struct of_device_id tegra_ehci_of_match[] = { |
843 | { .compatible = "nvidia,tegra20-ehci", }, | 842 | { .compatible = "nvidia,tegra20-ehci", }, |
844 | { }, | 843 | { }, |
845 | }; | 844 | }; |
846 | 845 | ||
847 | static struct platform_driver tegra_ehci_driver = { | 846 | static struct platform_driver tegra_ehci_driver = { |
848 | .probe = tegra_ehci_probe, | 847 | .probe = tegra_ehci_probe, |
849 | .remove = tegra_ehci_remove, | 848 | .remove = tegra_ehci_remove, |
850 | .shutdown = tegra_ehci_hcd_shutdown, | 849 | .shutdown = tegra_ehci_hcd_shutdown, |
851 | .driver = { | 850 | .driver = { |
852 | .name = "tegra-ehci", | 851 | .name = "tegra-ehci", |
853 | .of_match_table = tegra_ehci_of_match, | 852 | .of_match_table = tegra_ehci_of_match, |
854 | #ifdef CONFIG_PM | 853 | #ifdef CONFIG_PM |
855 | .pm = &tegra_ehci_pm_ops, | 854 | .pm = &tegra_ehci_pm_ops, |
856 | #endif | 855 | #endif |
drivers/usb/phy/tegra_usb_phy.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Google, Inc. | 2 | * Copyright (C) 2010 Google, Inc. |
3 | * | 3 | * |
4 | * Author: | 4 | * Author: |
5 | * Erik Gilling <konkers@google.com> | 5 | * Erik Gilling <konkers@google.com> |
6 | * Benoit Goby <benoit@android.com> | 6 | * Benoit Goby <benoit@android.com> |
7 | * | 7 | * |
8 | * This software is licensed under the terms of the GNU General Public | 8 | * This software is licensed under the terms of the GNU General Public |
9 | * License version 2, as published by the Free Software Foundation, and | 9 | * License version 2, as published by the Free Software Foundation, and |
10 | * may be copied, distributed, and modified under those terms. | 10 | * may be copied, distributed, and modified under those terms. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/resource.h> | 19 | #include <linux/resource.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
29 | #include <linux/usb/otg.h> | 29 | #include <linux/usb/otg.h> |
30 | #include <linux/usb/ulpi.h> | 30 | #include <linux/usb/ulpi.h> |
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
32 | #include <linux/usb/tegra_usb_phy.h> | 32 | #include <linux/usb/tegra_usb_phy.h> |
33 | 33 | ||
34 | #define TEGRA_USB_BASE 0xC5000000 | 34 | #define TEGRA_USB_BASE 0xC5000000 |
35 | #define TEGRA_USB_SIZE SZ_16K | 35 | #define TEGRA_USB_SIZE SZ_16K |
36 | 36 | ||
37 | #define ULPI_VIEWPORT 0x170 | 37 | #define ULPI_VIEWPORT 0x170 |
38 | 38 | ||
39 | #define USB_SUSP_CTRL 0x400 | 39 | #define USB_SUSP_CTRL 0x400 |
40 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) | 40 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) |
41 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) | 41 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) |
42 | #define USB_SUSP_CLR (1 << 5) | 42 | #define USB_SUSP_CLR (1 << 5) |
43 | #define USB_PHY_CLK_VALID (1 << 7) | 43 | #define USB_PHY_CLK_VALID (1 << 7) |
44 | #define UTMIP_RESET (1 << 11) | 44 | #define UTMIP_RESET (1 << 11) |
45 | #define UHSIC_RESET (1 << 11) | 45 | #define UHSIC_RESET (1 << 11) |
46 | #define UTMIP_PHY_ENABLE (1 << 12) | 46 | #define UTMIP_PHY_ENABLE (1 << 12) |
47 | #define ULPI_PHY_ENABLE (1 << 13) | 47 | #define ULPI_PHY_ENABLE (1 << 13) |
48 | #define USB_SUSP_SET (1 << 14) | 48 | #define USB_SUSP_SET (1 << 14) |
49 | #define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) | 49 | #define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) |
50 | 50 | ||
51 | #define USB1_LEGACY_CTRL 0x410 | 51 | #define USB1_LEGACY_CTRL 0x410 |
52 | #define USB1_NO_LEGACY_MODE (1 << 0) | 52 | #define USB1_NO_LEGACY_MODE (1 << 0) |
53 | #define USB1_VBUS_SENSE_CTL_MASK (3 << 1) | 53 | #define USB1_VBUS_SENSE_CTL_MASK (3 << 1) |
54 | #define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1) | 54 | #define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1) |
55 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \ | 55 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \ |
56 | (1 << 1) | 56 | (1 << 1) |
57 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1) | 57 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1) |
58 | #define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1) | 58 | #define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1) |
59 | 59 | ||
60 | #define ULPI_TIMING_CTRL_0 0x424 | 60 | #define ULPI_TIMING_CTRL_0 0x424 |
61 | #define ULPI_OUTPUT_PINMUX_BYP (1 << 10) | 61 | #define ULPI_OUTPUT_PINMUX_BYP (1 << 10) |
62 | #define ULPI_CLKOUT_PINMUX_BYP (1 << 11) | 62 | #define ULPI_CLKOUT_PINMUX_BYP (1 << 11) |
63 | 63 | ||
64 | #define ULPI_TIMING_CTRL_1 0x428 | 64 | #define ULPI_TIMING_CTRL_1 0x428 |
65 | #define ULPI_DATA_TRIMMER_LOAD (1 << 0) | 65 | #define ULPI_DATA_TRIMMER_LOAD (1 << 0) |
66 | #define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) | 66 | #define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) |
67 | #define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) | 67 | #define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) |
68 | #define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) | 68 | #define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) |
69 | #define ULPI_DIR_TRIMMER_LOAD (1 << 24) | 69 | #define ULPI_DIR_TRIMMER_LOAD (1 << 24) |
70 | #define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) | 70 | #define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) |
71 | 71 | ||
72 | #define UTMIP_PLL_CFG1 0x804 | 72 | #define UTMIP_PLL_CFG1 0x804 |
73 | #define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) | 73 | #define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) |
74 | #define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) | 74 | #define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) |
75 | 75 | ||
76 | #define UTMIP_XCVR_CFG0 0x808 | 76 | #define UTMIP_XCVR_CFG0 0x808 |
77 | #define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0) | 77 | #define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0) |
78 | #define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8) | 78 | #define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8) |
79 | #define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10) | 79 | #define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10) |
80 | #define UTMIP_FORCE_PD_POWERDOWN (1 << 14) | 80 | #define UTMIP_FORCE_PD_POWERDOWN (1 << 14) |
81 | #define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) | 81 | #define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) |
82 | #define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) | 82 | #define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) |
83 | #define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) | 83 | #define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) |
84 | 84 | ||
85 | #define UTMIP_BIAS_CFG0 0x80c | 85 | #define UTMIP_BIAS_CFG0 0x80c |
86 | #define UTMIP_OTGPD (1 << 11) | 86 | #define UTMIP_OTGPD (1 << 11) |
87 | #define UTMIP_BIASPD (1 << 10) | 87 | #define UTMIP_BIASPD (1 << 10) |
88 | 88 | ||
89 | #define UTMIP_HSRX_CFG0 0x810 | 89 | #define UTMIP_HSRX_CFG0 0x810 |
90 | #define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) | 90 | #define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) |
91 | #define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15) | 91 | #define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15) |
92 | 92 | ||
93 | #define UTMIP_HSRX_CFG1 0x814 | 93 | #define UTMIP_HSRX_CFG1 0x814 |
94 | #define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1) | 94 | #define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1) |
95 | 95 | ||
96 | #define UTMIP_TX_CFG0 0x820 | 96 | #define UTMIP_TX_CFG0 0x820 |
97 | #define UTMIP_FS_PREABMLE_J (1 << 19) | 97 | #define UTMIP_FS_PREABMLE_J (1 << 19) |
98 | #define UTMIP_HS_DISCON_DISABLE (1 << 8) | 98 | #define UTMIP_HS_DISCON_DISABLE (1 << 8) |
99 | 99 | ||
100 | #define UTMIP_MISC_CFG0 0x824 | 100 | #define UTMIP_MISC_CFG0 0x824 |
101 | #define UTMIP_DPDM_OBSERVE (1 << 26) | 101 | #define UTMIP_DPDM_OBSERVE (1 << 26) |
102 | #define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) | 102 | #define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) |
103 | #define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) | 103 | #define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) |
104 | #define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) | 104 | #define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) |
105 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) | 105 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) |
106 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) | 106 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) |
107 | #define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) | 107 | #define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) |
108 | 108 | ||
109 | #define UTMIP_MISC_CFG1 0x828 | 109 | #define UTMIP_MISC_CFG1 0x828 |
110 | #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) | 110 | #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) |
111 | #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) | 111 | #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) |
112 | 112 | ||
113 | #define UTMIP_DEBOUNCE_CFG0 0x82c | 113 | #define UTMIP_DEBOUNCE_CFG0 0x82c |
114 | #define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0) | 114 | #define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0) |
115 | 115 | ||
116 | #define UTMIP_BAT_CHRG_CFG0 0x830 | 116 | #define UTMIP_BAT_CHRG_CFG0 0x830 |
117 | #define UTMIP_PD_CHRG (1 << 0) | 117 | #define UTMIP_PD_CHRG (1 << 0) |
118 | 118 | ||
119 | #define UTMIP_SPARE_CFG0 0x834 | 119 | #define UTMIP_SPARE_CFG0 0x834 |
120 | #define FUSE_SETUP_SEL (1 << 3) | 120 | #define FUSE_SETUP_SEL (1 << 3) |
121 | 121 | ||
122 | #define UTMIP_XCVR_CFG1 0x838 | 122 | #define UTMIP_XCVR_CFG1 0x838 |
123 | #define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) | 123 | #define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) |
124 | #define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) | 124 | #define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) |
125 | #define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) | 125 | #define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) |
126 | #define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18) | 126 | #define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18) |
127 | 127 | ||
128 | #define UTMIP_BIAS_CFG1 0x83c | 128 | #define UTMIP_BIAS_CFG1 0x83c |
129 | #define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3) | 129 | #define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3) |
130 | 130 | ||
131 | static DEFINE_SPINLOCK(utmip_pad_lock); | 131 | static DEFINE_SPINLOCK(utmip_pad_lock); |
132 | static int utmip_pad_count; | 132 | static int utmip_pad_count; |
133 | 133 | ||
134 | struct tegra_xtal_freq { | 134 | struct tegra_xtal_freq { |
135 | int freq; | 135 | int freq; |
136 | u8 enable_delay; | 136 | u8 enable_delay; |
137 | u8 stable_count; | 137 | u8 stable_count; |
138 | u8 active_delay; | 138 | u8 active_delay; |
139 | u8 xtal_freq_count; | 139 | u8 xtal_freq_count; |
140 | u16 debounce; | 140 | u16 debounce; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | static const struct tegra_xtal_freq tegra_freq_table[] = { | 143 | static const struct tegra_xtal_freq tegra_freq_table[] = { |
144 | { | 144 | { |
145 | .freq = 12000000, | 145 | .freq = 12000000, |
146 | .enable_delay = 0x02, | 146 | .enable_delay = 0x02, |
147 | .stable_count = 0x2F, | 147 | .stable_count = 0x2F, |
148 | .active_delay = 0x04, | 148 | .active_delay = 0x04, |
149 | .xtal_freq_count = 0x76, | 149 | .xtal_freq_count = 0x76, |
150 | .debounce = 0x7530, | 150 | .debounce = 0x7530, |
151 | }, | 151 | }, |
152 | { | 152 | { |
153 | .freq = 13000000, | 153 | .freq = 13000000, |
154 | .enable_delay = 0x02, | 154 | .enable_delay = 0x02, |
155 | .stable_count = 0x33, | 155 | .stable_count = 0x33, |
156 | .active_delay = 0x05, | 156 | .active_delay = 0x05, |
157 | .xtal_freq_count = 0x7F, | 157 | .xtal_freq_count = 0x7F, |
158 | .debounce = 0x7EF4, | 158 | .debounce = 0x7EF4, |
159 | }, | 159 | }, |
160 | { | 160 | { |
161 | .freq = 19200000, | 161 | .freq = 19200000, |
162 | .enable_delay = 0x03, | 162 | .enable_delay = 0x03, |
163 | .stable_count = 0x4B, | 163 | .stable_count = 0x4B, |
164 | .active_delay = 0x06, | 164 | .active_delay = 0x06, |
165 | .xtal_freq_count = 0xBB, | 165 | .xtal_freq_count = 0xBB, |
166 | .debounce = 0xBB80, | 166 | .debounce = 0xBB80, |
167 | }, | 167 | }, |
168 | { | 168 | { |
169 | .freq = 26000000, | 169 | .freq = 26000000, |
170 | .enable_delay = 0x04, | 170 | .enable_delay = 0x04, |
171 | .stable_count = 0x66, | 171 | .stable_count = 0x66, |
172 | .active_delay = 0x09, | 172 | .active_delay = 0x09, |
173 | .xtal_freq_count = 0xFE, | 173 | .xtal_freq_count = 0xFE, |
174 | .debounce = 0xFDE8, | 174 | .debounce = 0xFDE8, |
175 | }, | 175 | }, |
176 | }; | 176 | }; |
177 | 177 | ||
178 | static struct tegra_utmip_config utmip_default[] = { | 178 | static struct tegra_utmip_config utmip_default[] = { |
179 | [0] = { | 179 | [0] = { |
180 | .hssync_start_delay = 9, | 180 | .hssync_start_delay = 9, |
181 | .idle_wait_delay = 17, | 181 | .idle_wait_delay = 17, |
182 | .elastic_limit = 16, | 182 | .elastic_limit = 16, |
183 | .term_range_adj = 6, | 183 | .term_range_adj = 6, |
184 | .xcvr_setup = 9, | 184 | .xcvr_setup = 9, |
185 | .xcvr_lsfslew = 1, | 185 | .xcvr_lsfslew = 1, |
186 | .xcvr_lsrslew = 1, | 186 | .xcvr_lsrslew = 1, |
187 | }, | 187 | }, |
188 | [2] = { | 188 | [2] = { |
189 | .hssync_start_delay = 9, | 189 | .hssync_start_delay = 9, |
190 | .idle_wait_delay = 17, | 190 | .idle_wait_delay = 17, |
191 | .elastic_limit = 16, | 191 | .elastic_limit = 16, |
192 | .term_range_adj = 6, | 192 | .term_range_adj = 6, |
193 | .xcvr_setup = 9, | 193 | .xcvr_setup = 9, |
194 | .xcvr_lsfslew = 2, | 194 | .xcvr_lsfslew = 2, |
195 | .xcvr_lsrslew = 2, | 195 | .xcvr_lsrslew = 2, |
196 | }, | 196 | }, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static int utmip_pad_open(struct tegra_usb_phy *phy) | 199 | static int utmip_pad_open(struct tegra_usb_phy *phy) |
200 | { | 200 | { |
201 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); | 201 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); |
202 | if (IS_ERR(phy->pad_clk)) { | 202 | if (IS_ERR(phy->pad_clk)) { |
203 | pr_err("%s: can't get utmip pad clock\n", __func__); | 203 | pr_err("%s: can't get utmip pad clock\n", __func__); |
204 | return PTR_ERR(phy->pad_clk); | 204 | return PTR_ERR(phy->pad_clk); |
205 | } | 205 | } |
206 | 206 | ||
207 | if (phy->is_legacy_phy) { | 207 | if (phy->is_legacy_phy) { |
208 | phy->pad_regs = phy->regs; | 208 | phy->pad_regs = phy->regs; |
209 | } else { | 209 | } else { |
210 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); | 210 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); |
211 | if (!phy->pad_regs) { | 211 | if (!phy->pad_regs) { |
212 | pr_err("%s: can't remap usb registers\n", __func__); | 212 | pr_err("%s: can't remap usb registers\n", __func__); |
213 | clk_put(phy->pad_clk); | 213 | clk_put(phy->pad_clk); |
214 | return -ENOMEM; | 214 | return -ENOMEM; |
215 | } | 215 | } |
216 | } | 216 | } |
217 | return 0; | 217 | return 0; |
218 | } | 218 | } |
219 | 219 | ||
220 | static void utmip_pad_close(struct tegra_usb_phy *phy) | 220 | static void utmip_pad_close(struct tegra_usb_phy *phy) |
221 | { | 221 | { |
222 | if (!phy->is_legacy_phy) | 222 | if (!phy->is_legacy_phy) |
223 | iounmap(phy->pad_regs); | 223 | iounmap(phy->pad_regs); |
224 | clk_put(phy->pad_clk); | 224 | clk_put(phy->pad_clk); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) | 227 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) |
228 | { | 228 | { |
229 | unsigned long val, flags; | 229 | unsigned long val, flags; |
230 | void __iomem *base = phy->pad_regs; | 230 | void __iomem *base = phy->pad_regs; |
231 | 231 | ||
232 | clk_prepare_enable(phy->pad_clk); | 232 | clk_prepare_enable(phy->pad_clk); |
233 | 233 | ||
234 | spin_lock_irqsave(&utmip_pad_lock, flags); | 234 | spin_lock_irqsave(&utmip_pad_lock, flags); |
235 | 235 | ||
236 | if (utmip_pad_count++ == 0) { | 236 | if (utmip_pad_count++ == 0) { |
237 | val = readl(base + UTMIP_BIAS_CFG0); | 237 | val = readl(base + UTMIP_BIAS_CFG0); |
238 | val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); | 238 | val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); |
239 | writel(val, base + UTMIP_BIAS_CFG0); | 239 | writel(val, base + UTMIP_BIAS_CFG0); |
240 | } | 240 | } |
241 | 241 | ||
242 | spin_unlock_irqrestore(&utmip_pad_lock, flags); | 242 | spin_unlock_irqrestore(&utmip_pad_lock, flags); |
243 | 243 | ||
244 | clk_disable_unprepare(phy->pad_clk); | 244 | clk_disable_unprepare(phy->pad_clk); |
245 | } | 245 | } |
246 | 246 | ||
247 | static int utmip_pad_power_off(struct tegra_usb_phy *phy) | 247 | static int utmip_pad_power_off(struct tegra_usb_phy *phy) |
248 | { | 248 | { |
249 | unsigned long val, flags; | 249 | unsigned long val, flags; |
250 | void __iomem *base = phy->pad_regs; | 250 | void __iomem *base = phy->pad_regs; |
251 | 251 | ||
252 | if (!utmip_pad_count) { | 252 | if (!utmip_pad_count) { |
253 | pr_err("%s: utmip pad already powered off\n", __func__); | 253 | pr_err("%s: utmip pad already powered off\n", __func__); |
254 | return -EINVAL; | 254 | return -EINVAL; |
255 | } | 255 | } |
256 | 256 | ||
257 | clk_prepare_enable(phy->pad_clk); | 257 | clk_prepare_enable(phy->pad_clk); |
258 | 258 | ||
259 | spin_lock_irqsave(&utmip_pad_lock, flags); | 259 | spin_lock_irqsave(&utmip_pad_lock, flags); |
260 | 260 | ||
261 | if (--utmip_pad_count == 0) { | 261 | if (--utmip_pad_count == 0) { |
262 | val = readl(base + UTMIP_BIAS_CFG0); | 262 | val = readl(base + UTMIP_BIAS_CFG0); |
263 | val |= UTMIP_OTGPD | UTMIP_BIASPD; | 263 | val |= UTMIP_OTGPD | UTMIP_BIASPD; |
264 | writel(val, base + UTMIP_BIAS_CFG0); | 264 | writel(val, base + UTMIP_BIAS_CFG0); |
265 | } | 265 | } |
266 | 266 | ||
267 | spin_unlock_irqrestore(&utmip_pad_lock, flags); | 267 | spin_unlock_irqrestore(&utmip_pad_lock, flags); |
268 | 268 | ||
269 | clk_disable_unprepare(phy->pad_clk); | 269 | clk_disable_unprepare(phy->pad_clk); |
270 | 270 | ||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) | 274 | static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) |
275 | { | 275 | { |
276 | unsigned long timeout = 2000; | 276 | unsigned long timeout = 2000; |
277 | do { | 277 | do { |
278 | if ((readl(reg) & mask) == result) | 278 | if ((readl(reg) & mask) == result) |
279 | return 0; | 279 | return 0; |
280 | udelay(1); | 280 | udelay(1); |
281 | timeout--; | 281 | timeout--; |
282 | } while (timeout); | 282 | } while (timeout); |
283 | return -1; | 283 | return -1; |
284 | } | 284 | } |
285 | 285 | ||
286 | static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | 286 | static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) |
287 | { | 287 | { |
288 | unsigned long val; | 288 | unsigned long val; |
289 | void __iomem *base = phy->regs; | 289 | void __iomem *base = phy->regs; |
290 | 290 | ||
291 | if (phy->is_legacy_phy) { | 291 | if (phy->is_legacy_phy) { |
292 | val = readl(base + USB_SUSP_CTRL); | 292 | val = readl(base + USB_SUSP_CTRL); |
293 | val |= USB_SUSP_SET; | 293 | val |= USB_SUSP_SET; |
294 | writel(val, base + USB_SUSP_CTRL); | 294 | writel(val, base + USB_SUSP_CTRL); |
295 | 295 | ||
296 | udelay(10); | 296 | udelay(10); |
297 | 297 | ||
298 | val = readl(base + USB_SUSP_CTRL); | 298 | val = readl(base + USB_SUSP_CTRL); |
299 | val &= ~USB_SUSP_SET; | 299 | val &= ~USB_SUSP_SET; |
300 | writel(val, base + USB_SUSP_CTRL); | 300 | writel(val, base + USB_SUSP_CTRL); |
301 | } else | 301 | } else |
302 | tegra_ehci_set_phcd(&phy->u_phy, true); | 302 | tegra_ehci_set_phcd(&phy->u_phy, true); |
303 | 303 | ||
304 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | 304 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) |
305 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 305 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); |
306 | } | 306 | } |
307 | 307 | ||
308 | static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | 308 | static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) |
309 | { | 309 | { |
310 | unsigned long val; | 310 | unsigned long val; |
311 | void __iomem *base = phy->regs; | 311 | void __iomem *base = phy->regs; |
312 | 312 | ||
313 | if (phy->is_legacy_phy) { | 313 | if (phy->is_legacy_phy) { |
314 | val = readl(base + USB_SUSP_CTRL); | 314 | val = readl(base + USB_SUSP_CTRL); |
315 | val |= USB_SUSP_CLR; | 315 | val |= USB_SUSP_CLR; |
316 | writel(val, base + USB_SUSP_CTRL); | 316 | writel(val, base + USB_SUSP_CTRL); |
317 | 317 | ||
318 | udelay(10); | 318 | udelay(10); |
319 | 319 | ||
320 | val = readl(base + USB_SUSP_CTRL); | 320 | val = readl(base + USB_SUSP_CTRL); |
321 | val &= ~USB_SUSP_CLR; | 321 | val &= ~USB_SUSP_CLR; |
322 | writel(val, base + USB_SUSP_CTRL); | 322 | writel(val, base + USB_SUSP_CTRL); |
323 | } else | 323 | } else |
324 | tegra_ehci_set_phcd(&phy->u_phy, false); | 324 | tegra_ehci_set_phcd(&phy->u_phy, false); |
325 | 325 | ||
326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | 326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, |
327 | USB_PHY_CLK_VALID)) | 327 | USB_PHY_CLK_VALID)) |
328 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 328 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); |
329 | } | 329 | } |
330 | 330 | ||
331 | static int utmi_phy_power_on(struct tegra_usb_phy *phy) | 331 | static int utmi_phy_power_on(struct tegra_usb_phy *phy) |
332 | { | 332 | { |
333 | unsigned long val; | 333 | unsigned long val; |
334 | void __iomem *base = phy->regs; | 334 | void __iomem *base = phy->regs; |
335 | struct tegra_utmip_config *config = phy->config; | 335 | struct tegra_utmip_config *config = phy->config; |
336 | 336 | ||
337 | val = readl(base + USB_SUSP_CTRL); | 337 | val = readl(base + USB_SUSP_CTRL); |
338 | val |= UTMIP_RESET; | 338 | val |= UTMIP_RESET; |
339 | writel(val, base + USB_SUSP_CTRL); | 339 | writel(val, base + USB_SUSP_CTRL); |
340 | 340 | ||
341 | if (phy->is_legacy_phy) { | 341 | if (phy->is_legacy_phy) { |
342 | val = readl(base + USB1_LEGACY_CTRL); | 342 | val = readl(base + USB1_LEGACY_CTRL); |
343 | val |= USB1_NO_LEGACY_MODE; | 343 | val |= USB1_NO_LEGACY_MODE; |
344 | writel(val, base + USB1_LEGACY_CTRL); | 344 | writel(val, base + USB1_LEGACY_CTRL); |
345 | } | 345 | } |
346 | 346 | ||
347 | val = readl(base + UTMIP_TX_CFG0); | 347 | val = readl(base + UTMIP_TX_CFG0); |
348 | val &= ~UTMIP_FS_PREABMLE_J; | 348 | val &= ~UTMIP_FS_PREABMLE_J; |
349 | writel(val, base + UTMIP_TX_CFG0); | 349 | writel(val, base + UTMIP_TX_CFG0); |
350 | 350 | ||
351 | val = readl(base + UTMIP_HSRX_CFG0); | 351 | val = readl(base + UTMIP_HSRX_CFG0); |
352 | val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0)); | 352 | val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0)); |
353 | val |= UTMIP_IDLE_WAIT(config->idle_wait_delay); | 353 | val |= UTMIP_IDLE_WAIT(config->idle_wait_delay); |
354 | val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit); | 354 | val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit); |
355 | writel(val, base + UTMIP_HSRX_CFG0); | 355 | writel(val, base + UTMIP_HSRX_CFG0); |
356 | 356 | ||
357 | val = readl(base + UTMIP_HSRX_CFG1); | 357 | val = readl(base + UTMIP_HSRX_CFG1); |
358 | val &= ~UTMIP_HS_SYNC_START_DLY(~0); | 358 | val &= ~UTMIP_HS_SYNC_START_DLY(~0); |
359 | val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay); | 359 | val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay); |
360 | writel(val, base + UTMIP_HSRX_CFG1); | 360 | writel(val, base + UTMIP_HSRX_CFG1); |
361 | 361 | ||
362 | val = readl(base + UTMIP_DEBOUNCE_CFG0); | 362 | val = readl(base + UTMIP_DEBOUNCE_CFG0); |
363 | val &= ~UTMIP_BIAS_DEBOUNCE_A(~0); | 363 | val &= ~UTMIP_BIAS_DEBOUNCE_A(~0); |
364 | val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce); | 364 | val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce); |
365 | writel(val, base + UTMIP_DEBOUNCE_CFG0); | 365 | writel(val, base + UTMIP_DEBOUNCE_CFG0); |
366 | 366 | ||
367 | val = readl(base + UTMIP_MISC_CFG0); | 367 | val = readl(base + UTMIP_MISC_CFG0); |
368 | val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE; | 368 | val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE; |
369 | writel(val, base + UTMIP_MISC_CFG0); | 369 | writel(val, base + UTMIP_MISC_CFG0); |
370 | 370 | ||
371 | val = readl(base + UTMIP_MISC_CFG1); | 371 | val = readl(base + UTMIP_MISC_CFG1); |
372 | val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0)); | 372 | val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0)); |
373 | val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) | | 373 | val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) | |
374 | UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count); | 374 | UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count); |
375 | writel(val, base + UTMIP_MISC_CFG1); | 375 | writel(val, base + UTMIP_MISC_CFG1); |
376 | 376 | ||
377 | val = readl(base + UTMIP_PLL_CFG1); | 377 | val = readl(base + UTMIP_PLL_CFG1); |
378 | val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0)); | 378 | val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0)); |
379 | val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) | | 379 | val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) | |
380 | UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); | 380 | UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); |
381 | writel(val, base + UTMIP_PLL_CFG1); | 381 | writel(val, base + UTMIP_PLL_CFG1); |
382 | 382 | ||
383 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { | 383 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { |
384 | val = readl(base + USB_SUSP_CTRL); | 384 | val = readl(base + USB_SUSP_CTRL); |
385 | val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); | 385 | val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); |
386 | writel(val, base + USB_SUSP_CTRL); | 386 | writel(val, base + USB_SUSP_CTRL); |
387 | } | 387 | } |
388 | 388 | ||
389 | utmip_pad_power_on(phy); | 389 | utmip_pad_power_on(phy); |
390 | 390 | ||
391 | val = readl(base + UTMIP_XCVR_CFG0); | 391 | val = readl(base + UTMIP_XCVR_CFG0); |
392 | val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | | 392 | val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | |
393 | UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) | | 393 | UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) | |
394 | UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | | 394 | UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | |
395 | UTMIP_XCVR_HSSLEW_MSB(~0)); | 395 | UTMIP_XCVR_HSSLEW_MSB(~0)); |
396 | val |= UTMIP_XCVR_SETUP(config->xcvr_setup); | 396 | val |= UTMIP_XCVR_SETUP(config->xcvr_setup); |
397 | val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); | 397 | val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); |
398 | val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); | 398 | val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); |
399 | writel(val, base + UTMIP_XCVR_CFG0); | 399 | writel(val, base + UTMIP_XCVR_CFG0); |
400 | 400 | ||
401 | val = readl(base + UTMIP_XCVR_CFG1); | 401 | val = readl(base + UTMIP_XCVR_CFG1); |
402 | val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | | 402 | val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | |
403 | UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0)); | 403 | UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0)); |
404 | val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj); | 404 | val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj); |
405 | writel(val, base + UTMIP_XCVR_CFG1); | 405 | writel(val, base + UTMIP_XCVR_CFG1); |
406 | 406 | ||
407 | val = readl(base + UTMIP_BAT_CHRG_CFG0); | 407 | val = readl(base + UTMIP_BAT_CHRG_CFG0); |
408 | val &= ~UTMIP_PD_CHRG; | 408 | val &= ~UTMIP_PD_CHRG; |
409 | writel(val, base + UTMIP_BAT_CHRG_CFG0); | 409 | writel(val, base + UTMIP_BAT_CHRG_CFG0); |
410 | 410 | ||
411 | val = readl(base + UTMIP_BIAS_CFG1); | 411 | val = readl(base + UTMIP_BIAS_CFG1); |
412 | val &= ~UTMIP_BIAS_PDTRK_COUNT(~0); | 412 | val &= ~UTMIP_BIAS_PDTRK_COUNT(~0); |
413 | val |= UTMIP_BIAS_PDTRK_COUNT(0x5); | 413 | val |= UTMIP_BIAS_PDTRK_COUNT(0x5); |
414 | writel(val, base + UTMIP_BIAS_CFG1); | 414 | writel(val, base + UTMIP_BIAS_CFG1); |
415 | 415 | ||
416 | if (phy->is_legacy_phy) { | 416 | if (phy->is_legacy_phy) { |
417 | val = readl(base + UTMIP_SPARE_CFG0); | 417 | val = readl(base + UTMIP_SPARE_CFG0); |
418 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) | 418 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) |
419 | val &= ~FUSE_SETUP_SEL; | 419 | val &= ~FUSE_SETUP_SEL; |
420 | else | 420 | else |
421 | val |= FUSE_SETUP_SEL; | 421 | val |= FUSE_SETUP_SEL; |
422 | writel(val, base + UTMIP_SPARE_CFG0); | 422 | writel(val, base + UTMIP_SPARE_CFG0); |
423 | } else { | 423 | } else { |
424 | val = readl(base + USB_SUSP_CTRL); | 424 | val = readl(base + USB_SUSP_CTRL); |
425 | val |= UTMIP_PHY_ENABLE; | 425 | val |= UTMIP_PHY_ENABLE; |
426 | writel(val, base + USB_SUSP_CTRL); | 426 | writel(val, base + USB_SUSP_CTRL); |
427 | } | 427 | } |
428 | 428 | ||
429 | val = readl(base + USB_SUSP_CTRL); | 429 | val = readl(base + USB_SUSP_CTRL); |
430 | val &= ~UTMIP_RESET; | 430 | val &= ~UTMIP_RESET; |
431 | writel(val, base + USB_SUSP_CTRL); | 431 | writel(val, base + USB_SUSP_CTRL); |
432 | 432 | ||
433 | if (phy->is_legacy_phy) { | 433 | if (phy->is_legacy_phy) { |
434 | val = readl(base + USB1_LEGACY_CTRL); | 434 | val = readl(base + USB1_LEGACY_CTRL); |
435 | val &= ~USB1_VBUS_SENSE_CTL_MASK; | 435 | val &= ~USB1_VBUS_SENSE_CTL_MASK; |
436 | val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; | 436 | val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; |
437 | writel(val, base + USB1_LEGACY_CTRL); | 437 | writel(val, base + USB1_LEGACY_CTRL); |
438 | 438 | ||
439 | val = readl(base + USB_SUSP_CTRL); | 439 | val = readl(base + USB_SUSP_CTRL); |
440 | val &= ~USB_SUSP_SET; | 440 | val &= ~USB_SUSP_SET; |
441 | writel(val, base + USB_SUSP_CTRL); | 441 | writel(val, base + USB_SUSP_CTRL); |
442 | } | 442 | } |
443 | 443 | ||
444 | utmi_phy_clk_enable(phy); | 444 | utmi_phy_clk_enable(phy); |
445 | 445 | ||
446 | if (!phy->is_legacy_phy) | 446 | if (!phy->is_legacy_phy) |
447 | tegra_ehci_set_pts(&phy->u_phy, 0); | 447 | tegra_ehci_set_pts(&phy->u_phy, 0); |
448 | 448 | ||
449 | return 0; | 449 | return 0; |
450 | } | 450 | } |
451 | 451 | ||
452 | static int utmi_phy_power_off(struct tegra_usb_phy *phy) | 452 | static int utmi_phy_power_off(struct tegra_usb_phy *phy) |
453 | { | 453 | { |
454 | unsigned long val; | 454 | unsigned long val; |
455 | void __iomem *base = phy->regs; | 455 | void __iomem *base = phy->regs; |
456 | 456 | ||
457 | utmi_phy_clk_disable(phy); | 457 | utmi_phy_clk_disable(phy); |
458 | 458 | ||
459 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { | 459 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { |
460 | val = readl(base + USB_SUSP_CTRL); | 460 | val = readl(base + USB_SUSP_CTRL); |
461 | val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); | 461 | val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); |
462 | val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); | 462 | val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); |
463 | writel(val, base + USB_SUSP_CTRL); | 463 | writel(val, base + USB_SUSP_CTRL); |
464 | } | 464 | } |
465 | 465 | ||
466 | val = readl(base + USB_SUSP_CTRL); | 466 | val = readl(base + USB_SUSP_CTRL); |
467 | val |= UTMIP_RESET; | 467 | val |= UTMIP_RESET; |
468 | writel(val, base + USB_SUSP_CTRL); | 468 | writel(val, base + USB_SUSP_CTRL); |
469 | 469 | ||
470 | val = readl(base + UTMIP_BAT_CHRG_CFG0); | 470 | val = readl(base + UTMIP_BAT_CHRG_CFG0); |
471 | val |= UTMIP_PD_CHRG; | 471 | val |= UTMIP_PD_CHRG; |
472 | writel(val, base + UTMIP_BAT_CHRG_CFG0); | 472 | writel(val, base + UTMIP_BAT_CHRG_CFG0); |
473 | 473 | ||
474 | val = readl(base + UTMIP_XCVR_CFG0); | 474 | val = readl(base + UTMIP_XCVR_CFG0); |
475 | val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | | 475 | val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | |
476 | UTMIP_FORCE_PDZI_POWERDOWN; | 476 | UTMIP_FORCE_PDZI_POWERDOWN; |
477 | writel(val, base + UTMIP_XCVR_CFG0); | 477 | writel(val, base + UTMIP_XCVR_CFG0); |
478 | 478 | ||
479 | val = readl(base + UTMIP_XCVR_CFG1); | 479 | val = readl(base + UTMIP_XCVR_CFG1); |
480 | val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | | 480 | val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | |
481 | UTMIP_FORCE_PDDR_POWERDOWN; | 481 | UTMIP_FORCE_PDDR_POWERDOWN; |
482 | writel(val, base + UTMIP_XCVR_CFG1); | 482 | writel(val, base + UTMIP_XCVR_CFG1); |
483 | 483 | ||
484 | return utmip_pad_power_off(phy); | 484 | return utmip_pad_power_off(phy); |
485 | } | 485 | } |
486 | 486 | ||
487 | static void utmi_phy_preresume(struct tegra_usb_phy *phy) | 487 | static void utmi_phy_preresume(struct tegra_usb_phy *phy) |
488 | { | 488 | { |
489 | unsigned long val; | 489 | unsigned long val; |
490 | void __iomem *base = phy->regs; | 490 | void __iomem *base = phy->regs; |
491 | 491 | ||
492 | val = readl(base + UTMIP_TX_CFG0); | 492 | val = readl(base + UTMIP_TX_CFG0); |
493 | val |= UTMIP_HS_DISCON_DISABLE; | 493 | val |= UTMIP_HS_DISCON_DISABLE; |
494 | writel(val, base + UTMIP_TX_CFG0); | 494 | writel(val, base + UTMIP_TX_CFG0); |
495 | } | 495 | } |
496 | 496 | ||
497 | static void utmi_phy_postresume(struct tegra_usb_phy *phy) | 497 | static void utmi_phy_postresume(struct tegra_usb_phy *phy) |
498 | { | 498 | { |
499 | unsigned long val; | 499 | unsigned long val; |
500 | void __iomem *base = phy->regs; | 500 | void __iomem *base = phy->regs; |
501 | 501 | ||
502 | val = readl(base + UTMIP_TX_CFG0); | 502 | val = readl(base + UTMIP_TX_CFG0); |
503 | val &= ~UTMIP_HS_DISCON_DISABLE; | 503 | val &= ~UTMIP_HS_DISCON_DISABLE; |
504 | writel(val, base + UTMIP_TX_CFG0); | 504 | writel(val, base + UTMIP_TX_CFG0); |
505 | } | 505 | } |
506 | 506 | ||
507 | static void utmi_phy_restore_start(struct tegra_usb_phy *phy, | 507 | static void utmi_phy_restore_start(struct tegra_usb_phy *phy, |
508 | enum tegra_usb_phy_port_speed port_speed) | 508 | enum tegra_usb_phy_port_speed port_speed) |
509 | { | 509 | { |
510 | unsigned long val; | 510 | unsigned long val; |
511 | void __iomem *base = phy->regs; | 511 | void __iomem *base = phy->regs; |
512 | 512 | ||
513 | val = readl(base + UTMIP_MISC_CFG0); | 513 | val = readl(base + UTMIP_MISC_CFG0); |
514 | val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); | 514 | val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); |
515 | if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) | 515 | if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) |
516 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; | 516 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; |
517 | else | 517 | else |
518 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; | 518 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; |
519 | writel(val, base + UTMIP_MISC_CFG0); | 519 | writel(val, base + UTMIP_MISC_CFG0); |
520 | udelay(1); | 520 | udelay(1); |
521 | 521 | ||
522 | val = readl(base + UTMIP_MISC_CFG0); | 522 | val = readl(base + UTMIP_MISC_CFG0); |
523 | val |= UTMIP_DPDM_OBSERVE; | 523 | val |= UTMIP_DPDM_OBSERVE; |
524 | writel(val, base + UTMIP_MISC_CFG0); | 524 | writel(val, base + UTMIP_MISC_CFG0); |
525 | udelay(10); | 525 | udelay(10); |
526 | } | 526 | } |
527 | 527 | ||
528 | static void utmi_phy_restore_end(struct tegra_usb_phy *phy) | 528 | static void utmi_phy_restore_end(struct tegra_usb_phy *phy) |
529 | { | 529 | { |
530 | unsigned long val; | 530 | unsigned long val; |
531 | void __iomem *base = phy->regs; | 531 | void __iomem *base = phy->regs; |
532 | 532 | ||
533 | val = readl(base + UTMIP_MISC_CFG0); | 533 | val = readl(base + UTMIP_MISC_CFG0); |
534 | val &= ~UTMIP_DPDM_OBSERVE; | 534 | val &= ~UTMIP_DPDM_OBSERVE; |
535 | writel(val, base + UTMIP_MISC_CFG0); | 535 | writel(val, base + UTMIP_MISC_CFG0); |
536 | udelay(10); | 536 | udelay(10); |
537 | } | 537 | } |
538 | 538 | ||
539 | static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | 539 | static int ulpi_phy_power_on(struct tegra_usb_phy *phy) |
540 | { | 540 | { |
541 | int ret; | 541 | int ret; |
542 | unsigned long val; | 542 | unsigned long val; |
543 | void __iomem *base = phy->regs; | 543 | void __iomem *base = phy->regs; |
544 | struct tegra_ulpi_config *config = phy->config; | 544 | struct tegra_ulpi_config *config = phy->config; |
545 | 545 | ||
546 | gpio_direction_output(config->reset_gpio, 0); | 546 | gpio_direction_output(config->reset_gpio, 0); |
547 | msleep(5); | 547 | msleep(5); |
548 | gpio_direction_output(config->reset_gpio, 1); | 548 | gpio_direction_output(config->reset_gpio, 1); |
549 | 549 | ||
550 | clk_prepare_enable(phy->clk); | 550 | clk_prepare_enable(phy->clk); |
551 | msleep(1); | 551 | msleep(1); |
552 | 552 | ||
553 | val = readl(base + USB_SUSP_CTRL); | 553 | val = readl(base + USB_SUSP_CTRL); |
554 | val |= UHSIC_RESET; | 554 | val |= UHSIC_RESET; |
555 | writel(val, base + USB_SUSP_CTRL); | 555 | writel(val, base + USB_SUSP_CTRL); |
556 | 556 | ||
557 | val = readl(base + ULPI_TIMING_CTRL_0); | 557 | val = readl(base + ULPI_TIMING_CTRL_0); |
558 | val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; | 558 | val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; |
559 | writel(val, base + ULPI_TIMING_CTRL_0); | 559 | writel(val, base + ULPI_TIMING_CTRL_0); |
560 | 560 | ||
561 | val = readl(base + USB_SUSP_CTRL); | 561 | val = readl(base + USB_SUSP_CTRL); |
562 | val |= ULPI_PHY_ENABLE; | 562 | val |= ULPI_PHY_ENABLE; |
563 | writel(val, base + USB_SUSP_CTRL); | 563 | writel(val, base + USB_SUSP_CTRL); |
564 | 564 | ||
565 | val = 0; | 565 | val = 0; |
566 | writel(val, base + ULPI_TIMING_CTRL_1); | 566 | writel(val, base + ULPI_TIMING_CTRL_1); |
567 | 567 | ||
568 | val |= ULPI_DATA_TRIMMER_SEL(4); | 568 | val |= ULPI_DATA_TRIMMER_SEL(4); |
569 | val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); | 569 | val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); |
570 | val |= ULPI_DIR_TRIMMER_SEL(4); | 570 | val |= ULPI_DIR_TRIMMER_SEL(4); |
571 | writel(val, base + ULPI_TIMING_CTRL_1); | 571 | writel(val, base + ULPI_TIMING_CTRL_1); |
572 | udelay(10); | 572 | udelay(10); |
573 | 573 | ||
574 | val |= ULPI_DATA_TRIMMER_LOAD; | 574 | val |= ULPI_DATA_TRIMMER_LOAD; |
575 | val |= ULPI_STPDIRNXT_TRIMMER_LOAD; | 575 | val |= ULPI_STPDIRNXT_TRIMMER_LOAD; |
576 | val |= ULPI_DIR_TRIMMER_LOAD; | 576 | val |= ULPI_DIR_TRIMMER_LOAD; |
577 | writel(val, base + ULPI_TIMING_CTRL_1); | 577 | writel(val, base + ULPI_TIMING_CTRL_1); |
578 | 578 | ||
579 | /* Fix VbusInvalid due to floating VBUS */ | 579 | /* Fix VbusInvalid due to floating VBUS */ |
580 | ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); | 580 | ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); |
581 | if (ret) { | 581 | if (ret) { |
582 | pr_err("%s: ulpi write failed\n", __func__); | 582 | pr_err("%s: ulpi write failed\n", __func__); |
583 | return ret; | 583 | return ret; |
584 | } | 584 | } |
585 | 585 | ||
586 | ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); | 586 | ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); |
587 | if (ret) { | 587 | if (ret) { |
588 | pr_err("%s: ulpi write failed\n", __func__); | 588 | pr_err("%s: ulpi write failed\n", __func__); |
589 | return ret; | 589 | return ret; |
590 | } | 590 | } |
591 | 591 | ||
592 | val = readl(base + USB_SUSP_CTRL); | 592 | val = readl(base + USB_SUSP_CTRL); |
593 | val |= USB_SUSP_CLR; | 593 | val |= USB_SUSP_CLR; |
594 | writel(val, base + USB_SUSP_CTRL); | 594 | writel(val, base + USB_SUSP_CTRL); |
595 | udelay(100); | 595 | udelay(100); |
596 | 596 | ||
597 | val = readl(base + USB_SUSP_CTRL); | 597 | val = readl(base + USB_SUSP_CTRL); |
598 | val &= ~USB_SUSP_CLR; | 598 | val &= ~USB_SUSP_CLR; |
599 | writel(val, base + USB_SUSP_CTRL); | 599 | writel(val, base + USB_SUSP_CTRL); |
600 | 600 | ||
601 | return 0; | 601 | return 0; |
602 | } | 602 | } |
603 | 603 | ||
604 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) | 604 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) |
605 | { | 605 | { |
606 | struct tegra_ulpi_config *config = phy->config; | 606 | struct tegra_ulpi_config *config = phy->config; |
607 | 607 | ||
608 | clk_disable(phy->clk); | 608 | clk_disable(phy->clk); |
609 | return gpio_direction_output(config->reset_gpio, 0); | 609 | return gpio_direction_output(config->reset_gpio, 0); |
610 | } | 610 | } |
611 | 611 | ||
612 | static int tegra_phy_init(struct usb_phy *x) | 612 | static int tegra_phy_init(struct usb_phy *x) |
613 | { | 613 | { |
614 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 614 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
615 | struct tegra_ulpi_config *ulpi_config; | 615 | struct tegra_ulpi_config *ulpi_config; |
616 | int err; | 616 | int err; |
617 | 617 | ||
618 | if (phy->is_ulpi_phy) { | 618 | if (phy->is_ulpi_phy) { |
619 | ulpi_config = phy->config; | 619 | ulpi_config = phy->config; |
620 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); | 620 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); |
621 | if (IS_ERR(phy->clk)) { | 621 | if (IS_ERR(phy->clk)) { |
622 | pr_err("%s: can't get ulpi clock\n", __func__); | 622 | pr_err("%s: can't get ulpi clock\n", __func__); |
623 | err = -ENXIO; | 623 | err = -ENXIO; |
624 | goto err1; | 624 | goto err1; |
625 | } | 625 | } |
626 | if (!gpio_is_valid(ulpi_config->reset_gpio)) | 626 | if (!gpio_is_valid(ulpi_config->reset_gpio)) |
627 | ulpi_config->reset_gpio = | 627 | ulpi_config->reset_gpio = |
628 | of_get_named_gpio(phy->dev->of_node, | 628 | of_get_named_gpio(phy->dev->of_node, |
629 | "nvidia,phy-reset-gpio", 0); | 629 | "nvidia,phy-reset-gpio", 0); |
630 | if (!gpio_is_valid(ulpi_config->reset_gpio)) { | 630 | if (!gpio_is_valid(ulpi_config->reset_gpio)) { |
631 | pr_err("%s: invalid reset gpio: %d\n", __func__, | 631 | pr_err("%s: invalid reset gpio: %d\n", __func__, |
632 | ulpi_config->reset_gpio); | 632 | ulpi_config->reset_gpio); |
633 | err = -EINVAL; | 633 | err = -EINVAL; |
634 | goto err1; | 634 | goto err1; |
635 | } | 635 | } |
636 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); | 636 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); |
637 | gpio_direction_output(ulpi_config->reset_gpio, 0); | 637 | gpio_direction_output(ulpi_config->reset_gpio, 0); |
638 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | 638 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); |
639 | phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; | 639 | phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; |
640 | } else { | 640 | } else { |
641 | err = utmip_pad_open(phy); | 641 | err = utmip_pad_open(phy); |
642 | if (err < 0) | 642 | if (err < 0) |
643 | goto err1; | 643 | goto err1; |
644 | } | 644 | } |
645 | return 0; | 645 | return 0; |
646 | err1: | 646 | err1: |
647 | clk_disable_unprepare(phy->pll_u); | 647 | clk_disable_unprepare(phy->pll_u); |
648 | clk_put(phy->pll_u); | 648 | clk_put(phy->pll_u); |
649 | return err; | 649 | return err; |
650 | } | 650 | } |
651 | 651 | ||
652 | static void tegra_usb_phy_close(struct usb_phy *x) | 652 | static void tegra_usb_phy_close(struct usb_phy *x) |
653 | { | 653 | { |
654 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 654 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
655 | 655 | ||
656 | if (phy->is_ulpi_phy) | 656 | if (phy->is_ulpi_phy) |
657 | clk_put(phy->clk); | 657 | clk_put(phy->clk); |
658 | else | 658 | else |
659 | utmip_pad_close(phy); | 659 | utmip_pad_close(phy); |
660 | clk_disable_unprepare(phy->pll_u); | 660 | clk_disable_unprepare(phy->pll_u); |
661 | clk_put(phy->pll_u); | 661 | clk_put(phy->pll_u); |
662 | kfree(phy); | 662 | kfree(phy); |
663 | } | 663 | } |
664 | 664 | ||
665 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | 665 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) |
666 | { | 666 | { |
667 | if (phy->is_ulpi_phy) | 667 | if (phy->is_ulpi_phy) |
668 | return ulpi_phy_power_on(phy); | 668 | return ulpi_phy_power_on(phy); |
669 | else | 669 | else |
670 | return utmi_phy_power_on(phy); | 670 | return utmi_phy_power_on(phy); |
671 | } | 671 | } |
672 | 672 | ||
673 | static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) | 673 | static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) |
674 | { | 674 | { |
675 | if (phy->is_ulpi_phy) | 675 | if (phy->is_ulpi_phy) |
676 | return ulpi_phy_power_off(phy); | 676 | return ulpi_phy_power_off(phy); |
677 | else | 677 | else |
678 | return utmi_phy_power_off(phy); | 678 | return utmi_phy_power_off(phy); |
679 | } | 679 | } |
680 | 680 | ||
681 | static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend) | 681 | static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend) |
682 | { | 682 | { |
683 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 683 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
684 | if (suspend) | 684 | if (suspend) |
685 | return tegra_usb_phy_power_off(phy); | 685 | return tegra_usb_phy_power_off(phy); |
686 | else | 686 | else |
687 | return tegra_usb_phy_power_on(phy); | 687 | return tegra_usb_phy_power_on(phy); |
688 | } | 688 | } |
689 | 689 | ||
690 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | 690 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, |
691 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) | 691 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) |
692 | { | 692 | { |
693 | struct tegra_usb_phy *phy; | 693 | struct tegra_usb_phy *phy; |
694 | unsigned long parent_rate; | 694 | unsigned long parent_rate; |
695 | int i; | 695 | int i; |
696 | int err; | 696 | int err; |
697 | struct device_node *np = dev->of_node; | 697 | struct device_node *np = dev->of_node; |
698 | 698 | ||
699 | phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); | 699 | phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); |
700 | if (!phy) | 700 | if (!phy) |
701 | return ERR_PTR(-ENOMEM); | 701 | return ERR_PTR(-ENOMEM); |
702 | 702 | ||
703 | phy->instance = instance; | 703 | phy->instance = instance; |
704 | phy->regs = regs; | 704 | phy->regs = regs; |
705 | phy->config = config; | 705 | phy->config = config; |
706 | phy->mode = phy_mode; | 706 | phy->mode = phy_mode; |
707 | phy->dev = dev; | 707 | phy->dev = dev; |
708 | phy->is_legacy_phy = | 708 | phy->is_legacy_phy = |
709 | of_property_read_bool(np, "nvidia,has-legacy-mode"); | 709 | of_property_read_bool(np, "nvidia,has-legacy-mode"); |
710 | err = of_property_match_string(np, "phy_type", "ulpi"); | 710 | err = of_property_match_string(np, "phy_type", "ulpi"); |
711 | if (err < 0) | 711 | if (err < 0) |
712 | phy->is_ulpi_phy = false; | 712 | phy->is_ulpi_phy = false; |
713 | else | 713 | else |
714 | phy->is_ulpi_phy = true; | 714 | phy->is_ulpi_phy = true; |
715 | 715 | ||
716 | if (!phy->config) { | 716 | if (!phy->config) { |
717 | if (phy->is_ulpi_phy) { | 717 | if (phy->is_ulpi_phy) { |
718 | pr_err("%s: ulpi phy configuration missing", __func__); | 718 | pr_err("%s: ulpi phy configuration missing", __func__); |
719 | err = -EINVAL; | 719 | err = -EINVAL; |
720 | goto err0; | 720 | goto err0; |
721 | } else { | 721 | } else { |
722 | phy->config = &utmip_default[instance]; | 722 | phy->config = &utmip_default[instance]; |
723 | } | 723 | } |
724 | } | 724 | } |
725 | 725 | ||
726 | phy->pll_u = clk_get_sys(NULL, "pll_u"); | 726 | phy->pll_u = clk_get_sys(NULL, "pll_u"); |
727 | if (IS_ERR(phy->pll_u)) { | 727 | if (IS_ERR(phy->pll_u)) { |
728 | pr_err("Can't get pll_u clock\n"); | 728 | pr_err("Can't get pll_u clock\n"); |
729 | err = PTR_ERR(phy->pll_u); | 729 | err = PTR_ERR(phy->pll_u); |
730 | goto err0; | 730 | goto err0; |
731 | } | 731 | } |
732 | clk_prepare_enable(phy->pll_u); | 732 | clk_prepare_enable(phy->pll_u); |
733 | 733 | ||
734 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); | 734 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); |
735 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { | 735 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { |
736 | if (tegra_freq_table[i].freq == parent_rate) { | 736 | if (tegra_freq_table[i].freq == parent_rate) { |
737 | phy->freq = &tegra_freq_table[i]; | 737 | phy->freq = &tegra_freq_table[i]; |
738 | break; | 738 | break; |
739 | } | 739 | } |
740 | } | 740 | } |
741 | if (!phy->freq) { | 741 | if (!phy->freq) { |
742 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); | 742 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); |
743 | err = -EINVAL; | 743 | err = -EINVAL; |
744 | goto err1; | 744 | goto err1; |
745 | } | 745 | } |
746 | 746 | ||
747 | phy->u_phy.init = tegra_phy_init; | 747 | phy->u_phy.init = tegra_phy_init; |
748 | phy->u_phy.shutdown = tegra_usb_phy_close; | 748 | phy->u_phy.shutdown = tegra_usb_phy_close; |
749 | phy->u_phy.set_suspend = tegra_usb_phy_suspend; | 749 | phy->u_phy.set_suspend = tegra_usb_phy_suspend; |
750 | 750 | ||
751 | return phy; | 751 | return phy; |
752 | 752 | ||
753 | err1: | 753 | err1: |
754 | clk_disable_unprepare(phy->pll_u); | 754 | clk_disable_unprepare(phy->pll_u); |
755 | clk_put(phy->pll_u); | 755 | clk_put(phy->pll_u); |
756 | err0: | 756 | err0: |
757 | kfree(phy); | 757 | kfree(phy); |
758 | return ERR_PTR(err); | 758 | return ERR_PTR(err); |
759 | } | 759 | } |
760 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); | 760 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); |
761 | 761 | ||
762 | void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) | 762 | void tegra_usb_phy_preresume(struct usb_phy *x) |
763 | { | 763 | { |
764 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | ||
765 | |||
764 | if (!phy->is_ulpi_phy) | 766 | if (!phy->is_ulpi_phy) |
765 | utmi_phy_preresume(phy); | 767 | utmi_phy_preresume(phy); |
766 | } | 768 | } |
767 | EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); | 769 | EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); |
768 | 770 | ||
769 | void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) | 771 | void tegra_usb_phy_postresume(struct usb_phy *x) |
770 | { | 772 | { |
773 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | ||
774 | |||
771 | if (!phy->is_ulpi_phy) | 775 | if (!phy->is_ulpi_phy) |
772 | utmi_phy_postresume(phy); | 776 | utmi_phy_postresume(phy); |
773 | } | 777 | } |
774 | EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); | 778 | EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); |
775 | 779 | ||
776 | void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, | 780 | void tegra_ehci_phy_restore_start(struct usb_phy *x, |
777 | enum tegra_usb_phy_port_speed port_speed) | 781 | enum tegra_usb_phy_port_speed port_speed) |
778 | { | 782 | { |
783 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | ||
784 | |||
779 | if (!phy->is_ulpi_phy) | 785 | if (!phy->is_ulpi_phy) |
780 | utmi_phy_restore_start(phy, port_speed); | 786 | utmi_phy_restore_start(phy, port_speed); |
781 | } | 787 | } |
782 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); | 788 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); |
783 | 789 | ||
784 | void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) | 790 | void tegra_ehci_phy_restore_end(struct usb_phy *x) |
785 | { | 791 | { |
792 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | ||
793 | |||
786 | if (!phy->is_ulpi_phy) | 794 | if (!phy->is_ulpi_phy) |
787 | utmi_phy_restore_end(phy); | 795 | utmi_phy_restore_end(phy); |
788 | } | 796 | } |
789 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); | 797 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); |
790 | 798 | ||
791 | 799 |
include/linux/usb/tegra_usb_phy.h
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Google, Inc. | 2 | * Copyright (C) 2010 Google, Inc. |
3 | * | 3 | * |
4 | * This software is licensed under the terms of the GNU General Public | 4 | * This software is licensed under the terms of the GNU General Public |
5 | * License version 2, as published by the Free Software Foundation, and | 5 | * License version 2, as published by the Free Software Foundation, and |
6 | * may be copied, distributed, and modified under those terms. | 6 | * may be copied, distributed, and modified under those terms. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, | 8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. | 11 | * GNU General Public License for more details. |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #ifndef __TEGRA_USB_PHY_H | 15 | #ifndef __TEGRA_USB_PHY_H |
16 | #define __TEGRA_USB_PHY_H | 16 | #define __TEGRA_USB_PHY_H |
17 | 17 | ||
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/usb/otg.h> | 19 | #include <linux/usb/otg.h> |
20 | 20 | ||
21 | struct tegra_utmip_config { | 21 | struct tegra_utmip_config { |
22 | u8 hssync_start_delay; | 22 | u8 hssync_start_delay; |
23 | u8 elastic_limit; | 23 | u8 elastic_limit; |
24 | u8 idle_wait_delay; | 24 | u8 idle_wait_delay; |
25 | u8 term_range_adj; | 25 | u8 term_range_adj; |
26 | u8 xcvr_setup; | 26 | u8 xcvr_setup; |
27 | u8 xcvr_lsfslew; | 27 | u8 xcvr_lsfslew; |
28 | u8 xcvr_lsrslew; | 28 | u8 xcvr_lsrslew; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | struct tegra_ulpi_config { | 31 | struct tegra_ulpi_config { |
32 | int reset_gpio; | 32 | int reset_gpio; |
33 | const char *clk; | 33 | const char *clk; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | enum tegra_usb_phy_port_speed { | 36 | enum tegra_usb_phy_port_speed { |
37 | TEGRA_USB_PHY_PORT_SPEED_FULL = 0, | 37 | TEGRA_USB_PHY_PORT_SPEED_FULL = 0, |
38 | TEGRA_USB_PHY_PORT_SPEED_LOW, | 38 | TEGRA_USB_PHY_PORT_SPEED_LOW, |
39 | TEGRA_USB_PHY_PORT_SPEED_HIGH, | 39 | TEGRA_USB_PHY_PORT_SPEED_HIGH, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | enum tegra_usb_phy_mode { | 42 | enum tegra_usb_phy_mode { |
43 | TEGRA_USB_PHY_MODE_DEVICE, | 43 | TEGRA_USB_PHY_MODE_DEVICE, |
44 | TEGRA_USB_PHY_MODE_HOST, | 44 | TEGRA_USB_PHY_MODE_HOST, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | struct tegra_xtal_freq; | 47 | struct tegra_xtal_freq; |
48 | 48 | ||
49 | struct tegra_usb_phy { | 49 | struct tegra_usb_phy { |
50 | int instance; | 50 | int instance; |
51 | const struct tegra_xtal_freq *freq; | 51 | const struct tegra_xtal_freq *freq; |
52 | void __iomem *regs; | 52 | void __iomem *regs; |
53 | void __iomem *pad_regs; | 53 | void __iomem *pad_regs; |
54 | struct clk *clk; | 54 | struct clk *clk; |
55 | struct clk *pll_u; | 55 | struct clk *pll_u; |
56 | struct clk *pad_clk; | 56 | struct clk *pad_clk; |
57 | enum tegra_usb_phy_mode mode; | 57 | enum tegra_usb_phy_mode mode; |
58 | void *config; | 58 | void *config; |
59 | struct usb_phy *ulpi; | 59 | struct usb_phy *ulpi; |
60 | struct usb_phy u_phy; | 60 | struct usb_phy u_phy; |
61 | struct device *dev; | 61 | struct device *dev; |
62 | bool is_legacy_phy; | 62 | bool is_legacy_phy; |
63 | bool is_ulpi_phy; | 63 | bool is_ulpi_phy; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | 66 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, |
67 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); | 67 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); |
68 | 68 | ||
69 | void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); | 69 | void tegra_usb_phy_preresume(struct usb_phy *phy); |
70 | 70 | ||
71 | void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); | 71 | void tegra_usb_phy_postresume(struct usb_phy *phy); |
72 | 72 | ||
73 | void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, | 73 | void tegra_ehci_phy_restore_start(struct usb_phy *phy, |
74 | enum tegra_usb_phy_port_speed port_speed); | 74 | enum tegra_usb_phy_port_speed port_speed); |
75 | 75 | ||
76 | void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); | 76 | void tegra_ehci_phy_restore_end(struct usb_phy *phy); |
77 | 77 | ||
78 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val); | 78 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val); |
79 | 79 | ||
80 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable); | 80 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable); |
81 | 81 | ||
82 | #endif /* __TEGRA_USB_PHY_H */ | 82 | #endif /* __TEGRA_USB_PHY_H */ |
83 | 83 |