forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/usb/chipidea/host.c
....@@ -13,6 +13,7 @@
1313 #include <linux/usb/hcd.h>
1414 #include <linux/usb/chipidea.h>
1515 #include <linux/regulator/consumer.h>
16
+#include <linux/pinctrl/consumer.h>
1617
1718 #include "../host/ehci.h"
1819
....@@ -155,6 +156,10 @@
155156 }
156157 }
157158
159
+ if (ci->platdata->pins_host)
160
+ pinctrl_select_state(ci->platdata->pctl,
161
+ ci->platdata->pins_host);
162
+
158163 ret = usb_add_hcd(hcd, 0, 0);
159164 if (ret) {
160165 goto disable_reg;
....@@ -167,6 +172,11 @@
167172 otg->host = &hcd->self;
168173 hcd->self.otg_port = 1;
169174 }
175
+
176
+ if (ci->platdata->notify_event &&
177
+ (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC))
178
+ ci->platdata->notify_event
179
+ (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT);
170180 }
171181
172182 return ret;
....@@ -199,6 +209,10 @@
199209 }
200210 ci->hcd = NULL;
201211 ci->otg.host = NULL;
212
+
213
+ if (ci->platdata->pins_host && ci->platdata->pins_default)
214
+ pinctrl_select_state(ci->platdata->pctl,
215
+ ci->platdata->pins_default);
202216 }
203217
204218
....@@ -208,9 +222,93 @@
208222 host_stop(ci);
209223 }
210224
225
+/* The below code is based on tegra ehci driver */
226
+static int ci_ehci_hub_control(
227
+ struct usb_hcd *hcd,
228
+ u16 typeReq,
229
+ u16 wValue,
230
+ u16 wIndex,
231
+ char *buf,
232
+ u16 wLength
233
+)
234
+{
235
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
236
+ unsigned int ports = HCS_N_PORTS(ehci->hcs_params);
237
+ u32 __iomem *status_reg;
238
+ u32 temp, port_index;
239
+ unsigned long flags;
240
+ int retval = 0;
241
+ struct device *dev = hcd->self.controller;
242
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
243
+
244
+ port_index = wIndex & 0xff;
245
+ port_index -= (port_index > 0);
246
+ status_reg = &ehci->regs->port_status[port_index];
247
+
248
+ spin_lock_irqsave(&ehci->lock, flags);
249
+
250
+ if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
251
+ if (!wIndex || wIndex > ports) {
252
+ retval = -EPIPE;
253
+ goto done;
254
+ }
255
+
256
+ temp = ehci_readl(ehci, status_reg);
257
+ if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
258
+ retval = -EPIPE;
259
+ goto done;
260
+ }
261
+
262
+ temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
263
+ temp |= PORT_WKDISC_E | PORT_WKOC_E;
264
+ ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
265
+
266
+ /*
267
+ * If a transaction is in progress, there may be a delay in
268
+ * suspending the port. Poll until the port is suspended.
269
+ */
270
+ if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
271
+ PORT_SUSPEND, 5000))
272
+ ehci_err(ehci, "timeout waiting for SUSPEND\n");
273
+
274
+ if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
275
+ if (ci->platdata->notify_event)
276
+ ci->platdata->notify_event(ci,
277
+ CI_HDRC_IMX_HSIC_SUSPEND_EVENT);
278
+
279
+ temp = ehci_readl(ehci, status_reg);
280
+ temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
281
+ ehci_writel(ehci, temp, status_reg);
282
+ }
283
+
284
+ set_bit(port_index, &ehci->suspended_ports);
285
+ goto done;
286
+ }
287
+
288
+ /*
289
+ * After resume has finished, it needs do some post resume
290
+ * operation for some SoCs.
291
+ */
292
+ else if (typeReq == ClearPortFeature &&
293
+ wValue == USB_PORT_FEAT_C_SUSPEND) {
294
+ /* Make sure the resume has finished, it should be finished */
295
+ if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
296
+ ehci_err(ehci, "timeout waiting for resume\n");
297
+ }
298
+
299
+ spin_unlock_irqrestore(&ehci->lock, flags);
300
+
301
+ /* Handle the hub control events here */
302
+ return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
303
+done:
304
+ spin_unlock_irqrestore(&ehci->lock, flags);
305
+ return retval;
306
+}
211307 static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
212308 {
213309 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
310
+ struct device *dev = hcd->self.controller;
311
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
214312 int port;
215313 u32 tmp;
216314
....@@ -242,6 +340,16 @@
242340 * It needs a short delay between set RS bit and PHCD.
243341 */
244342 usleep_range(150, 200);
343
+ /*
344
+ * Need to clear WKCN and WKOC for imx HSIC,
345
+ * otherwise, there will be wakeup event.
346
+ */
347
+ if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
348
+ tmp = ehci_readl(ehci, reg);
349
+ tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
350
+ ehci_writel(ehci, tmp, reg);
351
+ }
352
+
245353 break;
246354 }
247355 }
....@@ -274,4 +382,5 @@
274382 ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
275383 orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
276384 ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
385
+ ci_ehci_hc_driver.hub_control = ci_ehci_hub_control;
277386 }