USB: OTG: msm: vote for dayatona fabric clock
authorAnji jonnala <anjir@codeaurora.org>
Wed, 4 May 2011 04:49:46 +0000 (10:19 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sat, 7 May 2011 01:27:48 +0000 (18:27 -0700)
HSUSB core clock is derived from daytona fabric clock and for
HSUSB operational require minimum core clock at 55MHz. Since, HSUSB
cannot tolerate daytona fabric clock change in the middle of HSUSB
operational, vote for maximum Daytona fabric clock
while usb is operational

Signed-off-by: Anji jonnala <anjir@codeaurora.org>
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/otg/msm_otg.c
include/linux/usb/msm_hsusb.h

index f58b7dab75aa836ef7d41dd3914134265573432f..7792fef0be5e764f868f80cb0fdeb277f9cb6ac6 100644 (file)
@@ -324,6 +324,9 @@ static int msm_otg_suspend(struct msm_otg *motg)
        if (motg->core_clk)
                clk_disable(motg->core_clk);
 
+       if (!IS_ERR(motg->pclk_src))
+               clk_disable(motg->pclk_src);
+
        if (device_may_wakeup(otg->dev))
                enable_irq_wake(motg->irq);
        if (bus)
@@ -347,6 +350,9 @@ static int msm_otg_resume(struct msm_otg *motg)
        if (!atomic_read(&motg->in_lpm))
                return 0;
 
+       if (!IS_ERR(motg->pclk_src))
+               clk_enable(motg->pclk_src);
+
        clk_enable(motg->pclk);
        clk_enable(motg->clk);
        if (motg->core_clk)
@@ -862,12 +868,31 @@ static int __init msm_otg_probe(struct platform_device *pdev)
                ret = PTR_ERR(motg->clk);
                goto put_phy_reset_clk;
        }
+       clk_set_rate(motg->clk, 60000000);
+
+       /*
+        * If USB Core is running its protocol engine based on CORE CLK,
+        * CORE CLK  must be running at >55Mhz for correct HSUSB
+        * operation and USB core cannot tolerate frequency changes on
+        * CORE CLK. For such USB cores, vote for maximum clk frequency
+        * on pclk source
+        */
+        if (motg->pdata->pclk_src_name) {
+               motg->pclk_src = clk_get(&pdev->dev,
+                       motg->pdata->pclk_src_name);
+               if (IS_ERR(motg->pclk_src))
+                       goto put_clk;
+               clk_set_rate(motg->pclk_src, INT_MAX);
+               clk_enable(motg->pclk_src);
+       } else
+               motg->pclk_src = ERR_PTR(-ENOENT);
+
 
        motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
        if (IS_ERR(motg->pclk)) {
                dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
                ret = PTR_ERR(motg->pclk);
-               goto put_clk;
+               goto put_pclk_src;
        }
 
        /*
@@ -955,6 +980,11 @@ put_core_clk:
        if (motg->core_clk)
                clk_put(motg->core_clk);
        clk_put(motg->pclk);
+put_pclk_src:
+       if (!IS_ERR(motg->pclk_src)) {
+               clk_disable(motg->pclk_src);
+               clk_put(motg->pclk_src);
+       }
 put_clk:
        clk_put(motg->clk);
 put_phy_reset_clk:
@@ -1004,6 +1034,10 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
        clk_disable(motg->clk);
        if (motg->core_clk)
                clk_disable(motg->core_clk);
+       if (!IS_ERR(motg->pclk_src)) {
+               clk_disable(motg->pclk_src);
+               clk_put(motg->pclk_src);
+       }
 
        iounmap(motg->regs);
        pm_runtime_set_suspended(&pdev->dev);
index 3657403eac188ffeb759139809250c9f7c8b43ae..31ef1853f93cb61af3edeaecd43a3f6168c8ab45 100644 (file)
@@ -64,7 +64,8 @@ enum otg_control_type {
  * @otg_control: OTG switch controlled by user/Id pin
  * @default_mode: Default operational mode. Applicable only if
  *              OTG switch is controller by user.
- *
+ * @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
+ *              dfab_usb_hs_clk in case of 8660 and 8960.
  */
 struct msm_otg_platform_data {
        int *phy_init_seq;
@@ -74,6 +75,7 @@ struct msm_otg_platform_data {
        enum otg_control_type otg_control;
        enum usb_mode_type default_mode;
        void (*setup_gpio)(enum usb_otg_state state);
+       char *pclk_src_name;
 };
 
 /**
@@ -83,6 +85,7 @@ struct msm_otg_platform_data {
  * @irq: IRQ number assigned for HSUSB controller.
  * @clk: clock struct of usb_hs_clk.
  * @pclk: clock struct of usb_hs_pclk.
+ * @pclk_src: pclk source for voting.
  * @phy_reset_clk: clock struct of usb_phy_clk.
  * @core_clk: clock struct of usb_hs_core_clk.
  * @regs: ioremapped register base address.
@@ -90,7 +93,6 @@ struct msm_otg_platform_data {
  * @sm_work: OTG state machine work.
  * @in_lpm: indicates low power mode (LPM) state.
  * @async_int: Async interrupt arrived.
- *
  */
 struct msm_otg {
        struct otg_transceiver otg;
@@ -98,6 +100,7 @@ struct msm_otg {
        int irq;
        struct clk *clk;
        struct clk *pclk;
+       struct clk *pclk_src;
        struct clk *phy_reset_clk;
        struct clk *core_clk;
        void __iomem *regs;