aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@nxp.com>2018-10-15 21:17:02 -0400
committerPeter Chen <peter.chen@nxp.com>2018-12-10 20:12:30 -0500
commit7c8e8909417eb6342ac487dc5ab3076d46718f71 (patch)
tree2368c0024f335e03ce1e29b0e9b12815c98273b2 /drivers/usb/chipidea
parent014abe34a9095daaa6cbb2693ee90bbb54674693 (diff)
usb: chipidea: imx: add HSIC support
To support imx HSIC, there are some special requirement: - The HSIC pad is 1.2v, it may need to supply from external - The data/strobe pin needs to be pulled down first, and after host mode is initialized, the strobe pin needs to be pulled up - During the USB suspend/resume, special setting is needed Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de> Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de> Signed-off-by: Peter Chen <peter.chen@nxp.com>
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c140
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h9
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c140
3 files changed, 270 insertions, 19 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 09b37c0d075d..56781c329db0 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -14,6 +14,7 @@
14#include <linux/usb/chipidea.h> 14#include <linux/usb/chipidea.h>
15#include <linux/usb/of.h> 15#include <linux/usb/of.h>
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/pinctrl/consumer.h>
17 18
18#include "ci.h" 19#include "ci.h"
19#include "ci_hdrc_imx.h" 20#include "ci_hdrc_imx.h"
@@ -85,6 +86,9 @@ struct ci_hdrc_imx_data {
85 bool supports_runtime_pm; 86 bool supports_runtime_pm;
86 bool override_phy_control; 87 bool override_phy_control;
87 bool in_lpm; 88 bool in_lpm;
89 struct pinctrl *pinctrl;
90 struct pinctrl_state *pinctrl_hsic_active;
91 struct regulator *hsic_pad_regulator;
88 /* SoC before i.mx6 (except imx23/imx28) needs three clks */ 92 /* SoC before i.mx6 (except imx23/imx28) needs three clks */
89 bool need_three_clks; 93 bool need_three_clks;
90 struct clk *clk_ipg; 94 struct clk *clk_ipg;
@@ -245,19 +249,49 @@ static void imx_disable_unprepare_clks(struct device *dev)
245 } 249 }
246} 250}
247 251
252static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event)
253{
254 struct device *dev = ci->dev->parent;
255 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
256 int ret = 0;
257
258 switch (event) {
259 case CI_HDRC_IMX_HSIC_ACTIVE_EVENT:
260 ret = pinctrl_select_state(data->pinctrl,
261 data->pinctrl_hsic_active);
262 if (ret)
263 dev_err(dev, "hsic_active select failed, err=%d\n",
264 ret);
265 break;
266 case CI_HDRC_IMX_HSIC_SUSPEND_EVENT:
267 ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data);
268 if (ret)
269 dev_err(dev,
270 "hsic_set_connect failed, err=%d\n", ret);
271 break;
272 default:
273 break;
274 }
275
276 return ret;
277}
278
248static int ci_hdrc_imx_probe(struct platform_device *pdev) 279static int ci_hdrc_imx_probe(struct platform_device *pdev)
249{ 280{
250 struct ci_hdrc_imx_data *data; 281 struct ci_hdrc_imx_data *data;
251 struct ci_hdrc_platform_data pdata = { 282 struct ci_hdrc_platform_data pdata = {
252 .name = dev_name(&pdev->dev), 283 .name = dev_name(&pdev->dev),
253 .capoffset = DEF_CAPOFFSET, 284 .capoffset = DEF_CAPOFFSET,
285 .notify_event = ci_hdrc_imx_notify_event,
254 }; 286 };
255 int ret; 287 int ret;
256 const struct of_device_id *of_id; 288 const struct of_device_id *of_id;
257 const struct ci_hdrc_imx_platform_flag *imx_platform_flag; 289 const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
258 struct device_node *np = pdev->dev.of_node; 290 struct device_node *np = pdev->dev.of_node;
291 struct device *dev = &pdev->dev;
292 struct pinctrl_state *pinctrl_hsic_idle;
259 293
260 of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); 294 of_id = of_match_device(ci_hdrc_imx_dt_ids, dev);
261 if (!of_id) 295 if (!of_id)
262 return -ENODEV; 296 return -ENODEV;
263 297
@@ -268,19 +302,73 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
268 return -ENOMEM; 302 return -ENOMEM;
269 303
270 platform_set_drvdata(pdev, data); 304 platform_set_drvdata(pdev, data);
271 data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); 305 data->usbmisc_data = usbmisc_get_init_data(dev);
272 if (IS_ERR(data->usbmisc_data)) 306 if (IS_ERR(data->usbmisc_data))
273 return PTR_ERR(data->usbmisc_data); 307 return PTR_ERR(data->usbmisc_data);
274 308
275 ret = imx_get_clks(&pdev->dev); 309 if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
310 pdata.flags |= CI_HDRC_IMX_IS_HSIC;
311 data->usbmisc_data->hsic = 1;
312 data->pinctrl = devm_pinctrl_get(dev);
313 if (IS_ERR(data->pinctrl)) {
314 dev_err(dev, "pinctrl get failed, err=%ld\n",
315 PTR_ERR(data->pinctrl));
316 return PTR_ERR(data->pinctrl);
317 }
318
319 pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle");
320 if (IS_ERR(pinctrl_hsic_idle)) {
321 dev_err(dev,
322 "pinctrl_hsic_idle lookup failed, err=%ld\n",
323 PTR_ERR(pinctrl_hsic_idle));
324 return PTR_ERR(pinctrl_hsic_idle);
325 }
326
327 ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle);
328 if (ret) {
329 dev_err(dev, "hsic_idle select failed, err=%d\n", ret);
330 return ret;
331 }
332
333 data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl,
334 "active");
335 if (IS_ERR(data->pinctrl_hsic_active)) {
336 dev_err(dev,
337 "pinctrl_hsic_active lookup failed, err=%ld\n",
338 PTR_ERR(data->pinctrl_hsic_active));
339 return PTR_ERR(data->pinctrl_hsic_active);
340 }
341
342 data->hsic_pad_regulator = devm_regulator_get(dev, "hsic");
343 if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) {
344 return -EPROBE_DEFER;
345 } else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) {
346 /* no pad regualator is needed */
347 data->hsic_pad_regulator = NULL;
348 } else if (IS_ERR(data->hsic_pad_regulator)) {
349 dev_err(dev, "Get HSIC pad regulator error: %ld\n",
350 PTR_ERR(data->hsic_pad_regulator));
351 return PTR_ERR(data->hsic_pad_regulator);
352 }
353
354 if (data->hsic_pad_regulator) {
355 ret = regulator_enable(data->hsic_pad_regulator);
356 if (ret) {
357 dev_err(dev,
358 "Failed to enable HSIC pad regulator\n");
359 return ret;
360 }
361 }
362 }
363 ret = imx_get_clks(dev);
276 if (ret) 364 if (ret)
277 return ret; 365 goto disable_hsic_regulator;
278 366
279 ret = imx_prepare_enable_clks(&pdev->dev); 367 ret = imx_prepare_enable_clks(dev);
280 if (ret) 368 if (ret)
281 return ret; 369 goto disable_hsic_regulator;
282 370
283 data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); 371 data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0);
284 if (IS_ERR(data->phy)) { 372 if (IS_ERR(data->phy)) {
285 ret = PTR_ERR(data->phy); 373 ret = PTR_ERR(data->phy);
286 /* Return -EINVAL if no usbphy is available */ 374 /* Return -EINVAL if no usbphy is available */
@@ -305,40 +393,43 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
305 393
306 ret = imx_usbmisc_init(data->usbmisc_data); 394 ret = imx_usbmisc_init(data->usbmisc_data);
307 if (ret) { 395 if (ret) {
308 dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); 396 dev_err(dev, "usbmisc init failed, ret=%d\n", ret);
309 goto err_clk; 397 goto err_clk;
310 } 398 }
311 399
312 data->ci_pdev = ci_hdrc_add_device(&pdev->dev, 400 data->ci_pdev = ci_hdrc_add_device(dev,
313 pdev->resource, pdev->num_resources, 401 pdev->resource, pdev->num_resources,
314 &pdata); 402 &pdata);
315 if (IS_ERR(data->ci_pdev)) { 403 if (IS_ERR(data->ci_pdev)) {
316 ret = PTR_ERR(data->ci_pdev); 404 ret = PTR_ERR(data->ci_pdev);
317 if (ret != -EPROBE_DEFER) 405 if (ret != -EPROBE_DEFER)
318 dev_err(&pdev->dev, 406 dev_err(dev, "ci_hdrc_add_device failed, err=%d\n",
319 "ci_hdrc_add_device failed, err=%d\n", ret); 407 ret);
320 goto err_clk; 408 goto err_clk;
321 } 409 }
322 410
323 ret = imx_usbmisc_init_post(data->usbmisc_data); 411 ret = imx_usbmisc_init_post(data->usbmisc_data);
324 if (ret) { 412 if (ret) {
325 dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); 413 dev_err(dev, "usbmisc post failed, ret=%d\n", ret);
326 goto disable_device; 414 goto disable_device;
327 } 415 }
328 416
329 if (data->supports_runtime_pm) { 417 if (data->supports_runtime_pm) {
330 pm_runtime_set_active(&pdev->dev); 418 pm_runtime_set_active(dev);
331 pm_runtime_enable(&pdev->dev); 419 pm_runtime_enable(dev);
332 } 420 }
333 421
334 device_set_wakeup_capable(&pdev->dev, true); 422 device_set_wakeup_capable(dev, true);
335 423
336 return 0; 424 return 0;
337 425
338disable_device: 426disable_device:
339 ci_hdrc_remove_device(data->ci_pdev); 427 ci_hdrc_remove_device(data->ci_pdev);
340err_clk: 428err_clk:
341 imx_disable_unprepare_clks(&pdev->dev); 429 imx_disable_unprepare_clks(dev);
430disable_hsic_regulator:
431 if (data->hsic_pad_regulator)
432 ret = regulator_disable(data->hsic_pad_regulator);
342 return ret; 433 return ret;
343} 434}
344 435
@@ -355,6 +446,8 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
355 if (data->override_phy_control) 446 if (data->override_phy_control)
356 usb_phy_shutdown(data->phy); 447 usb_phy_shutdown(data->phy);
357 imx_disable_unprepare_clks(&pdev->dev); 448 imx_disable_unprepare_clks(&pdev->dev);
449 if (data->hsic_pad_regulator)
450 regulator_disable(data->hsic_pad_regulator);
358 451
359 return 0; 452 return 0;
360} 453}
@@ -367,9 +460,16 @@ static void ci_hdrc_imx_shutdown(struct platform_device *pdev)
367static int __maybe_unused imx_controller_suspend(struct device *dev) 460static int __maybe_unused imx_controller_suspend(struct device *dev)
368{ 461{
369 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 462 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
463 int ret = 0;
370 464
371 dev_dbg(dev, "at %s\n", __func__); 465 dev_dbg(dev, "at %s\n", __func__);
372 466
467 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false);
468 if (ret) {
469 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
470 return ret;
471 }
472
373 imx_disable_unprepare_clks(dev); 473 imx_disable_unprepare_clks(dev);
374 data->in_lpm = true; 474 data->in_lpm = true;
375 475
@@ -400,8 +500,16 @@ static int __maybe_unused imx_controller_resume(struct device *dev)
400 goto clk_disable; 500 goto clk_disable;
401 } 501 }
402 502
503 ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true);
504 if (ret) {
505 dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret);
506 goto hsic_set_clk_fail;
507 }
508
403 return 0; 509 return 0;
404 510
511hsic_set_clk_fail:
512 imx_usbmisc_set_wakeup(data->usbmisc_data, true);
405clk_disable: 513clk_disable:
406 imx_disable_unprepare_clks(dev); 514 imx_disable_unprepare_clks(dev);
407 return ret; 515 return ret;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 204275f47573..fcecab478934 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -14,10 +14,13 @@ struct imx_usbmisc_data {
14 unsigned int oc_polarity:1; /* over current polarity if oc enabled */ 14 unsigned int oc_polarity:1; /* over current polarity if oc enabled */
15 unsigned int evdo:1; /* set external vbus divider option */ 15 unsigned int evdo:1; /* set external vbus divider option */
16 unsigned int ulpi:1; /* connected to an ULPI phy */ 16 unsigned int ulpi:1; /* connected to an ULPI phy */
17 unsigned int hsic:1; /* HSIC controlller */
17}; 18};
18 19
19int imx_usbmisc_init(struct imx_usbmisc_data *); 20int imx_usbmisc_init(struct imx_usbmisc_data *data);
20int imx_usbmisc_init_post(struct imx_usbmisc_data *); 21int imx_usbmisc_init_post(struct imx_usbmisc_data *data);
21int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool); 22int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled);
23int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data);
24int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on);
22 25
23#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ 26#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index def80ff547e4..43a15a6e86f5 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -64,10 +64,22 @@
64#define MX6_BM_OVER_CUR_DIS BIT(7) 64#define MX6_BM_OVER_CUR_DIS BIT(7)
65#define MX6_BM_OVER_CUR_POLARITY BIT(8) 65#define MX6_BM_OVER_CUR_POLARITY BIT(8)
66#define MX6_BM_WAKEUP_ENABLE BIT(10) 66#define MX6_BM_WAKEUP_ENABLE BIT(10)
67#define MX6_BM_UTMI_ON_CLOCK BIT(13)
67#define MX6_BM_ID_WAKEUP BIT(16) 68#define MX6_BM_ID_WAKEUP BIT(16)
68#define MX6_BM_VBUS_WAKEUP BIT(17) 69#define MX6_BM_VBUS_WAKEUP BIT(17)
69#define MX6SX_BM_DPDM_WAKEUP_EN BIT(29) 70#define MX6SX_BM_DPDM_WAKEUP_EN BIT(29)
70#define MX6_BM_WAKEUP_INTR BIT(31) 71#define MX6_BM_WAKEUP_INTR BIT(31)
72
73#define MX6_USB_HSIC_CTRL_OFFSET 0x10
74/* Send resume signal without 480Mhz PHY clock */
75#define MX6SX_BM_HSIC_AUTO_RESUME BIT(23)
76/* set before portsc.suspendM = 1 */
77#define MX6_BM_HSIC_DEV_CONN BIT(21)
78/* HSIC enable */
79#define MX6_BM_HSIC_EN BIT(12)
80/* Force HSIC module 480M clock on, even when in Host is in suspend mode */
81#define MX6_BM_HSIC_CLK_ON BIT(11)
82
71#define MX6_USB_OTG1_PHY_CTRL 0x18 83#define MX6_USB_OTG1_PHY_CTRL 0x18
72/* For imx6dql, it is host-only controller, for later imx6, it is otg's */ 84/* For imx6dql, it is host-only controller, for later imx6, it is otg's */
73#define MX6_USB_OTG2_PHY_CTRL 0x1c 85#define MX6_USB_OTG2_PHY_CTRL 0x1c
@@ -94,6 +106,10 @@ struct usbmisc_ops {
94 int (*post)(struct imx_usbmisc_data *data); 106 int (*post)(struct imx_usbmisc_data *data);
95 /* It's called when we need to enable/disable usb wakeup */ 107 /* It's called when we need to enable/disable usb wakeup */
96 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); 108 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
109 /* It's called before setting portsc.suspendM */
110 int (*hsic_set_connect)(struct imx_usbmisc_data *data);
111 /* It's called during suspend/resume */
112 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
97}; 113};
98 114
99struct imx_usbmisc { 115struct imx_usbmisc {
@@ -353,6 +369,18 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
353 writel(reg | MX6_BM_NON_BURST_SETTING, 369 writel(reg | MX6_BM_NON_BURST_SETTING,
354 usbmisc->base + data->index * 4); 370 usbmisc->base + data->index * 4);
355 371
372 /* For HSIC controller */
373 if (data->hsic) {
374 reg = readl(usbmisc->base + data->index * 4);
375 writel(reg | MX6_BM_UTMI_ON_CLOCK,
376 usbmisc->base + data->index * 4);
377 reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
378 + (data->index - 2) * 4);
379 reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
380 writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
381 + (data->index - 2) * 4);
382 }
383
356 spin_unlock_irqrestore(&usbmisc->lock, flags); 384 spin_unlock_irqrestore(&usbmisc->lock, flags);
357 385
358 usbmisc_imx6q_set_wakeup(data, false); 386 usbmisc_imx6q_set_wakeup(data, false);
@@ -360,6 +388,79 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
360 return 0; 388 return 0;
361} 389}
362 390
391static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
392{
393 int offset, ret = 0;
394
395 if (data->index == 2 || data->index == 3) {
396 offset = (data->index - 2) * 4;
397 } else if (data->index == 0) {
398 /*
399 * For SoCs like i.MX7D and later, each USB controller has
400 * its own non-core register region. For SoCs before i.MX7D,
401 * the first two USB controllers are non-HSIC controllers.
402 */
403 offset = 0;
404 } else {
405 dev_err(data->dev, "index is error for usbmisc\n");
406 ret = -EINVAL;
407 }
408
409 return ret ? ret : offset;
410}
411
412static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
413{
414 unsigned long flags;
415 u32 val;
416 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
417 int offset;
418
419 spin_lock_irqsave(&usbmisc->lock, flags);
420 offset = usbmisc_imx6_hsic_get_reg_offset(data);
421 if (offset < 0) {
422 spin_unlock_irqrestore(&usbmisc->lock, flags);
423 return offset;
424 }
425
426 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
427 if (!(val & MX6_BM_HSIC_DEV_CONN))
428 writel(val | MX6_BM_HSIC_DEV_CONN,
429 usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
430
431 spin_unlock_irqrestore(&usbmisc->lock, flags);
432
433 return 0;
434}
435
436static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
437{
438 unsigned long flags;
439 u32 val;
440 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
441 int offset;
442
443 spin_lock_irqsave(&usbmisc->lock, flags);
444 offset = usbmisc_imx6_hsic_get_reg_offset(data);
445 if (offset < 0) {
446 spin_unlock_irqrestore(&usbmisc->lock, flags);
447 return offset;
448 }
449
450 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
451 val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
452 if (on)
453 val |= MX6_BM_HSIC_CLK_ON;
454 else
455 val &= ~MX6_BM_HSIC_CLK_ON;
456
457 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
458 spin_unlock_irqrestore(&usbmisc->lock, flags);
459
460 return 0;
461}
462
463
363static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) 464static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
364{ 465{
365 void __iomem *reg = NULL; 466 void __iomem *reg = NULL;
@@ -385,6 +486,13 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
385 spin_unlock_irqrestore(&usbmisc->lock, flags); 486 spin_unlock_irqrestore(&usbmisc->lock, flags);
386 } 487 }
387 488
489 /* For HSIC controller */
490 if (data->hsic) {
491 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
492 val |= MX6SX_BM_HSIC_AUTO_RESUME;
493 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
494 }
495
388 return 0; 496 return 0;
389} 497}
390 498
@@ -454,6 +562,7 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
454 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 562 reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
455 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, 563 writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
456 usbmisc->base + MX7D_USBNC_USB_CTRL2); 564 usbmisc->base + MX7D_USBNC_USB_CTRL2);
565
457 spin_unlock_irqrestore(&usbmisc->lock, flags); 566 spin_unlock_irqrestore(&usbmisc->lock, flags);
458 567
459 usbmisc_imx7d_set_wakeup(data, false); 568 usbmisc_imx7d_set_wakeup(data, false);
@@ -481,6 +590,8 @@ static const struct usbmisc_ops imx53_usbmisc_ops = {
481static const struct usbmisc_ops imx6q_usbmisc_ops = { 590static const struct usbmisc_ops imx6q_usbmisc_ops = {
482 .set_wakeup = usbmisc_imx6q_set_wakeup, 591 .set_wakeup = usbmisc_imx6q_set_wakeup,
483 .init = usbmisc_imx6q_init, 592 .init = usbmisc_imx6q_init,
593 .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
594 .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
484}; 595};
485 596
486static const struct usbmisc_ops vf610_usbmisc_ops = { 597static const struct usbmisc_ops vf610_usbmisc_ops = {
@@ -490,6 +601,8 @@ static const struct usbmisc_ops vf610_usbmisc_ops = {
490static const struct usbmisc_ops imx6sx_usbmisc_ops = { 601static const struct usbmisc_ops imx6sx_usbmisc_ops = {
491 .set_wakeup = usbmisc_imx6q_set_wakeup, 602 .set_wakeup = usbmisc_imx6q_set_wakeup,
492 .init = usbmisc_imx6sx_init, 603 .init = usbmisc_imx6sx_init,
604 .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
605 .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
493}; 606};
494 607
495static const struct usbmisc_ops imx7d_usbmisc_ops = { 608static const struct usbmisc_ops imx7d_usbmisc_ops = {
@@ -546,6 +659,33 @@ int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
546} 659}
547EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); 660EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
548 661
662int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
663{
664 struct imx_usbmisc *usbmisc;
665
666 if (!data)
667 return 0;
668
669 usbmisc = dev_get_drvdata(data->dev);
670 if (!usbmisc->ops->hsic_set_connect || !data->hsic)
671 return 0;
672 return usbmisc->ops->hsic_set_connect(data);
673}
674EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
675
676int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
677{
678 struct imx_usbmisc *usbmisc;
679
680 if (!data)
681 return 0;
682
683 usbmisc = dev_get_drvdata(data->dev);
684 if (!usbmisc->ops->hsic_set_clk || !data->hsic)
685 return 0;
686 return usbmisc->ops->hsic_set_clk(data, on);
687}
688EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
549static const struct of_device_id usbmisc_imx_dt_ids[] = { 689static const struct of_device_id usbmisc_imx_dt_ids[] = {
550 { 690 {
551 .compatible = "fsl,imx25-usbmisc", 691 .compatible = "fsl,imx25-usbmisc",