diff options
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 36 | ||||
-rw-r--r-- | include/linux/usb/msm_hsusb.h | 7 |
2 files changed, 40 insertions, 3 deletions
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index f58b7dab75a..7792fef0be5 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c | |||
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg) | |||
324 | if (motg->core_clk) | 324 | if (motg->core_clk) |
325 | clk_disable(motg->core_clk); | 325 | clk_disable(motg->core_clk); |
326 | 326 | ||
327 | if (!IS_ERR(motg->pclk_src)) | ||
328 | clk_disable(motg->pclk_src); | ||
329 | |||
327 | if (device_may_wakeup(otg->dev)) | 330 | if (device_may_wakeup(otg->dev)) |
328 | enable_irq_wake(motg->irq); | 331 | enable_irq_wake(motg->irq); |
329 | if (bus) | 332 | if (bus) |
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg) | |||
347 | if (!atomic_read(&motg->in_lpm)) | 350 | if (!atomic_read(&motg->in_lpm)) |
348 | return 0; | 351 | return 0; |
349 | 352 | ||
353 | if (!IS_ERR(motg->pclk_src)) | ||
354 | clk_enable(motg->pclk_src); | ||
355 | |||
350 | clk_enable(motg->pclk); | 356 | clk_enable(motg->pclk); |
351 | clk_enable(motg->clk); | 357 | clk_enable(motg->clk); |
352 | if (motg->core_clk) | 358 | if (motg->core_clk) |
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev) | |||
862 | ret = PTR_ERR(motg->clk); | 868 | ret = PTR_ERR(motg->clk); |
863 | goto put_phy_reset_clk; | 869 | goto put_phy_reset_clk; |
864 | } | 870 | } |
871 | clk_set_rate(motg->clk, 60000000); | ||
872 | |||
873 | /* | ||
874 | * If USB Core is running its protocol engine based on CORE CLK, | ||
875 | * CORE CLK must be running at >55Mhz for correct HSUSB | ||
876 | * operation and USB core cannot tolerate frequency changes on | ||
877 | * CORE CLK. For such USB cores, vote for maximum clk frequency | ||
878 | * on pclk source | ||
879 | */ | ||
880 | if (motg->pdata->pclk_src_name) { | ||
881 | motg->pclk_src = clk_get(&pdev->dev, | ||
882 | motg->pdata->pclk_src_name); | ||
883 | if (IS_ERR(motg->pclk_src)) | ||
884 | goto put_clk; | ||
885 | clk_set_rate(motg->pclk_src, INT_MAX); | ||
886 | clk_enable(motg->pclk_src); | ||
887 | } else | ||
888 | motg->pclk_src = ERR_PTR(-ENOENT); | ||
889 | |||
865 | 890 | ||
866 | motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); | 891 | motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); |
867 | if (IS_ERR(motg->pclk)) { | 892 | if (IS_ERR(motg->pclk)) { |
868 | dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); | 893 | dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); |
869 | ret = PTR_ERR(motg->pclk); | 894 | ret = PTR_ERR(motg->pclk); |
870 | goto put_clk; | 895 | goto put_pclk_src; |
871 | } | 896 | } |
872 | 897 | ||
873 | /* | 898 | /* |
@@ -955,6 +980,11 @@ put_core_clk: | |||
955 | if (motg->core_clk) | 980 | if (motg->core_clk) |
956 | clk_put(motg->core_clk); | 981 | clk_put(motg->core_clk); |
957 | clk_put(motg->pclk); | 982 | clk_put(motg->pclk); |
983 | put_pclk_src: | ||
984 | if (!IS_ERR(motg->pclk_src)) { | ||
985 | clk_disable(motg->pclk_src); | ||
986 | clk_put(motg->pclk_src); | ||
987 | } | ||
958 | put_clk: | 988 | put_clk: |
959 | clk_put(motg->clk); | 989 | clk_put(motg->clk); |
960 | put_phy_reset_clk: | 990 | put_phy_reset_clk: |
@@ -1004,6 +1034,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) | |||
1004 | clk_disable(motg->clk); | 1034 | clk_disable(motg->clk); |
1005 | if (motg->core_clk) | 1035 | if (motg->core_clk) |
1006 | clk_disable(motg->core_clk); | 1036 | clk_disable(motg->core_clk); |
1037 | if (!IS_ERR(motg->pclk_src)) { | ||
1038 | clk_disable(motg->pclk_src); | ||
1039 | clk_put(motg->pclk_src); | ||
1040 | } | ||
1007 | 1041 | ||
1008 | iounmap(motg->regs); | 1042 | iounmap(motg->regs); |
1009 | pm_runtime_set_suspended(&pdev->dev); | 1043 | pm_runtime_set_suspended(&pdev->dev); |
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 3657403eac1..31ef1853f93 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h | |||
@@ -64,7 +64,8 @@ enum otg_control_type { | |||
64 | * @otg_control: OTG switch controlled by user/Id pin | 64 | * @otg_control: OTG switch controlled by user/Id pin |
65 | * @default_mode: Default operational mode. Applicable only if | 65 | * @default_mode: Default operational mode. Applicable only if |
66 | * OTG switch is controller by user. | 66 | * OTG switch is controller by user. |
67 | * | 67 | * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k |
68 | * dfab_usb_hs_clk in case of 8660 and 8960. | ||
68 | */ | 69 | */ |
69 | struct msm_otg_platform_data { | 70 | struct msm_otg_platform_data { |
70 | int *phy_init_seq; | 71 | int *phy_init_seq; |
@@ -74,6 +75,7 @@ struct msm_otg_platform_data { | |||
74 | enum otg_control_type otg_control; | 75 | enum otg_control_type otg_control; |
75 | enum usb_mode_type default_mode; | 76 | enum usb_mode_type default_mode; |
76 | void (*setup_gpio)(enum usb_otg_state state); | 77 | void (*setup_gpio)(enum usb_otg_state state); |
78 | char *pclk_src_name; | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | /** | 81 | /** |
@@ -83,6 +85,7 @@ struct msm_otg_platform_data { | |||
83 | * @irq: IRQ number assigned for HSUSB controller. | 85 | * @irq: IRQ number assigned for HSUSB controller. |
84 | * @clk: clock struct of usb_hs_clk. | 86 | * @clk: clock struct of usb_hs_clk. |
85 | * @pclk: clock struct of usb_hs_pclk. | 87 | * @pclk: clock struct of usb_hs_pclk. |
88 | * @pclk_src: pclk source for voting. | ||
86 | * @phy_reset_clk: clock struct of usb_phy_clk. | 89 | * @phy_reset_clk: clock struct of usb_phy_clk. |
87 | * @core_clk: clock struct of usb_hs_core_clk. | 90 | * @core_clk: clock struct of usb_hs_core_clk. |
88 | * @regs: ioremapped register base address. | 91 | * @regs: ioremapped register base address. |
@@ -90,7 +93,6 @@ struct msm_otg_platform_data { | |||
90 | * @sm_work: OTG state machine work. | 93 | * @sm_work: OTG state machine work. |
91 | * @in_lpm: indicates low power mode (LPM) state. | 94 | * @in_lpm: indicates low power mode (LPM) state. |
92 | * @async_int: Async interrupt arrived. | 95 | * @async_int: Async interrupt arrived. |
93 | * | ||
94 | */ | 96 | */ |
95 | struct msm_otg { | 97 | struct msm_otg { |
96 | struct otg_transceiver otg; | 98 | struct otg_transceiver otg; |
@@ -98,6 +100,7 @@ struct msm_otg { | |||
98 | int irq; | 100 | int irq; |
99 | struct clk *clk; | 101 | struct clk *clk; |
100 | struct clk *pclk; | 102 | struct clk *pclk; |
103 | struct clk *pclk_src; | ||
101 | struct clk *phy_reset_clk; | 104 | struct clk *phy_reset_clk; |
102 | struct clk *core_clk; | 105 | struct clk *core_clk; |
103 | void __iomem *regs; | 106 | void __iomem *regs; |