diff options
| author | Peter Chen <peter.chen@freescale.com> | 2013-08-14 05:44:08 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-14 15:37:19 -0400 |
| commit | 577b232fc9caba1b6f7a3bb9901c00b10e0ca1ba (patch) | |
| tree | 7c3fd6ed7f8405c3f5f59dc9d1b83b17739da689 | |
| parent | 3f124d233e97db96d9471d1fb346335d43d8650d (diff) | |
usb: chipidea: add flag CI_HDRC_DUAL_ROLE_NOT_OTG
Since we need otgsc to know vbus's status at some chipidea
controllers even it is peripheral-only mode. Besides, some
SoCs (eg, AR9331 SoC) don't have otgsc register even
the DCCPARAMS_DC and DCCPARAMS_HC are both 1 at CAP_DCCPARAMS.
We inroduce flag CI_HDRC_DUAL_ROLE_NOT_OTG to indicate if the
controller is dual role, but not supports OTG. If this flag is
not set, we follow the rule that if DCCPARAMS_DC and DCCPARAMS_HC
are both 1 at CAP_DCCPARAMS, then this controller is otg capable.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/usb/chipidea/core.c | 37 | ||||
| -rw-r--r-- | include/linux/usb/chipidea.h | 5 |
2 files changed, 35 insertions, 7 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 75afc524b659..ab01e18bc2f8 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
| @@ -426,6 +426,18 @@ static inline void ci_role_destroy(struct ci_hdrc *ci) | |||
| 426 | ci_hdrc_host_destroy(ci); | 426 | ci_hdrc_host_destroy(ci); |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | static void ci_get_otg_capable(struct ci_hdrc *ci) | ||
| 430 | { | ||
| 431 | if (ci->platdata->flags & CI_HDRC_DUAL_ROLE_NOT_OTG) | ||
| 432 | ci->is_otg = false; | ||
| 433 | else | ||
| 434 | ci->is_otg = (hw_read(ci, CAP_DCCPARAMS, | ||
| 435 | DCCPARAMS_DC | DCCPARAMS_HC) | ||
| 436 | == (DCCPARAMS_DC | DCCPARAMS_HC)); | ||
| 437 | if (ci->is_otg) | ||
| 438 | dev_dbg(ci->dev, "It is OTG capable controller\n"); | ||
| 439 | } | ||
| 440 | |||
| 429 | static int ci_hdrc_probe(struct platform_device *pdev) | 441 | static int ci_hdrc_probe(struct platform_device *pdev) |
| 430 | { | 442 | { |
| 431 | struct device *dev = &pdev->dev; | 443 | struct device *dev = &pdev->dev; |
| @@ -480,6 +492,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
| 480 | return -ENODEV; | 492 | return -ENODEV; |
| 481 | } | 493 | } |
| 482 | 494 | ||
| 495 | ci_get_otg_capable(ci); | ||
| 496 | |||
| 483 | if (!ci->platdata->phy_mode) | 497 | if (!ci->platdata->phy_mode) |
| 484 | ci->platdata->phy_mode = of_usb_get_phy_mode(of_node); | 498 | ci->platdata->phy_mode = of_usb_get_phy_mode(of_node); |
| 485 | 499 | ||
| @@ -512,10 +526,22 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
| 512 | } | 526 | } |
| 513 | 527 | ||
| 514 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { | 528 | if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { |
| 515 | ci->is_otg = true; | 529 | if (ci->is_otg) { |
| 516 | /* ID pin needs 1ms debouce time, we delay 2ms for safe */ | 530 | /* |
| 517 | mdelay(2); | 531 | * ID pin needs 1ms debouce time, |
| 518 | ci->role = ci_otg_role(ci); | 532 | * we delay 2ms for safe. |
| 533 | */ | ||
| 534 | mdelay(2); | ||
| 535 | ci->role = ci_otg_role(ci); | ||
| 536 | ci_hdrc_otg_init(ci); | ||
| 537 | } else { | ||
| 538 | /* | ||
| 539 | * If the controller is not OTG capable, but support | ||
| 540 | * role switch, the defalt role is gadget, and the | ||
| 541 | * user can switch it through debugfs. | ||
| 542 | */ | ||
| 543 | ci->role = CI_ROLE_GADGET; | ||
| 544 | } | ||
| 519 | } else { | 545 | } else { |
| 520 | ci->role = ci->roles[CI_ROLE_HOST] | 546 | ci->role = ci->roles[CI_ROLE_HOST] |
| 521 | ? CI_ROLE_HOST | 547 | ? CI_ROLE_HOST |
| @@ -534,9 +560,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
| 534 | if (ret) | 560 | if (ret) |
| 535 | goto stop; | 561 | goto stop; |
| 536 | 562 | ||
| 537 | if (ci->is_otg) | ||
| 538 | ci_hdrc_otg_init(ci); | ||
| 539 | |||
| 540 | ret = dbg_create_files(ci); | 563 | ret = dbg_create_files(ci); |
| 541 | if (!ret) | 564 | if (!ret) |
| 542 | return 0; | 565 | return 0; |
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index ce4e1aa071b3..10a607ce9090 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h | |||
| @@ -20,6 +20,11 @@ struct ci_hdrc_platform_data { | |||
| 20 | #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1) | 20 | #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1) |
| 21 | #define CI_HDRC_PULLUP_ON_VBUS BIT(2) | 21 | #define CI_HDRC_PULLUP_ON_VBUS BIT(2) |
| 22 | #define CI_HDRC_DISABLE_STREAMING BIT(3) | 22 | #define CI_HDRC_DISABLE_STREAMING BIT(3) |
| 23 | /* | ||
| 24 | * Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1, | ||
| 25 | * but otg is not supported (no register otgsc). | ||
| 26 | */ | ||
| 27 | #define CI_HDRC_DUAL_ROLE_NOT_OTG BIT(4) | ||
| 23 | enum usb_dr_mode dr_mode; | 28 | enum usb_dr_mode dr_mode; |
| 24 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 | 29 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 |
| 25 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 | 30 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 |
