diff options
| -rw-r--r-- | arch/arm/mach-imx/clk-pllv2.c | 78 |
1 files changed, 54 insertions, 24 deletions
diff --git a/arch/arm/mach-imx/clk-pllv2.c b/arch/arm/mach-imx/clk-pllv2.c index 1b0307195a6e..0440379e3628 100644 --- a/arch/arm/mach-imx/clk-pllv2.c +++ b/arch/arm/mach-imx/clk-pllv2.c | |||
| @@ -74,24 +74,15 @@ struct clk_pllv2 { | |||
| 74 | void __iomem *base; | 74 | void __iomem *base; |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, | 77 | static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate, |
| 78 | unsigned long parent_rate) | 78 | u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn) |
| 79 | { | 79 | { |
| 80 | long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; | 80 | long mfi, mfn, mfd, pdf, ref_clk, mfn_abs; |
| 81 | unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, dbl; | 81 | unsigned long dbl; |
| 82 | void __iomem *pllbase; | ||
| 83 | s64 temp; | 82 | s64 temp; |
| 84 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
| 85 | |||
| 86 | pllbase = pll->base; | ||
| 87 | 83 | ||
| 88 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); | ||
| 89 | dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; | 84 | dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN; |
| 90 | 85 | ||
| 91 | dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); | ||
| 92 | dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); | ||
| 93 | dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); | ||
| 94 | |||
| 95 | pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; | 86 | pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; |
| 96 | mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; | 87 | mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET; |
| 97 | mfi = (mfi <= 5) ? 5 : mfi; | 88 | mfi = (mfi <= 5) ? 5 : mfi; |
| @@ -117,18 +108,30 @@ static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, | |||
| 117 | return temp; | 108 | return temp; |
| 118 | } | 109 | } |
| 119 | 110 | ||
| 120 | static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, | 111 | static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, |
| 121 | unsigned long parent_rate) | 112 | unsigned long parent_rate) |
| 122 | { | 113 | { |
| 114 | u32 dp_op, dp_mfd, dp_mfn, dp_ctl; | ||
| 115 | void __iomem *pllbase; | ||
| 123 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | 116 | struct clk_pllv2 *pll = to_clk_pllv2(hw); |
| 117 | |||
| 118 | pllbase = pll->base; | ||
| 119 | |||
| 120 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); | ||
| 121 | dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); | ||
| 122 | dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); | ||
| 123 | dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); | ||
| 124 | |||
| 125 | return __clk_pllv2_recalc_rate(parent_rate, dp_ctl, dp_op, dp_mfd, dp_mfn); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate, | ||
| 129 | u32 *dp_op, u32 *dp_mfd, u32 *dp_mfn) | ||
| 130 | { | ||
| 124 | u32 reg; | 131 | u32 reg; |
| 125 | void __iomem *pllbase; | ||
| 126 | long mfi, pdf, mfn, mfd = 999999; | 132 | long mfi, pdf, mfn, mfd = 999999; |
| 127 | s64 temp64; | 133 | s64 temp64; |
| 128 | unsigned long quad_parent_rate; | 134 | unsigned long quad_parent_rate; |
| 129 | unsigned long dp_ctl; | ||
| 130 | |||
| 131 | pllbase = pll->base; | ||
| 132 | 135 | ||
| 133 | quad_parent_rate = 4 * parent_rate; | 136 | quad_parent_rate = 4 * parent_rate; |
| 134 | pdf = mfi = -1; | 137 | pdf = mfi = -1; |
| @@ -138,18 +141,41 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 138 | return -EINVAL; | 141 | return -EINVAL; |
| 139 | pdf--; | 142 | pdf--; |
| 140 | 143 | ||
| 141 | temp64 = rate * (pdf+1) - quad_parent_rate * mfi; | 144 | temp64 = rate * (pdf + 1) - quad_parent_rate * mfi; |
| 142 | do_div(temp64, quad_parent_rate/1000000); | 145 | do_div(temp64, quad_parent_rate / 1000000); |
| 143 | mfn = (long)temp64; | 146 | mfn = (long)temp64; |
| 144 | 147 | ||
| 148 | reg = mfi << 4 | pdf; | ||
| 149 | |||
| 150 | *dp_op = reg; | ||
| 151 | *dp_mfd = mfd; | ||
| 152 | *dp_mfn = mfn; | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 158 | unsigned long parent_rate) | ||
| 159 | { | ||
| 160 | struct clk_pllv2 *pll = to_clk_pllv2(hw); | ||
| 161 | void __iomem *pllbase; | ||
| 162 | u32 dp_ctl, dp_op, dp_mfd, dp_mfn; | ||
| 163 | int ret; | ||
| 164 | |||
| 165 | pllbase = pll->base; | ||
| 166 | |||
| 167 | |||
| 168 | ret = __clk_pllv2_set_rate(rate, parent_rate, &dp_op, &dp_mfd, &dp_mfn); | ||
| 169 | if (ret) | ||
| 170 | return ret; | ||
| 171 | |||
| 145 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); | 172 | dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL); |
| 146 | /* use dpdck0_2 */ | 173 | /* use dpdck0_2 */ |
| 147 | __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); | 174 | __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL); |
| 148 | 175 | ||
| 149 | reg = mfi << 4 | pdf; | 176 | __raw_writel(dp_op, pllbase + MXC_PLL_DP_OP); |
| 150 | __raw_writel(reg, pllbase + MXC_PLL_DP_OP); | 177 | __raw_writel(dp_mfd, pllbase + MXC_PLL_DP_MFD); |
| 151 | __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD); | 178 | __raw_writel(dp_mfn, pllbase + MXC_PLL_DP_MFN); |
| 152 | __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN); | ||
| 153 | 179 | ||
| 154 | return 0; | 180 | return 0; |
| 155 | } | 181 | } |
| @@ -157,7 +183,11 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 157 | static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, | 183 | static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, |
| 158 | unsigned long *prate) | 184 | unsigned long *prate) |
| 159 | { | 185 | { |
| 160 | return rate; | 186 | u32 dp_op, dp_mfd, dp_mfn; |
| 187 | |||
| 188 | __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn); | ||
| 189 | return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN, | ||
| 190 | dp_op, dp_mfd, dp_mfn); | ||
| 161 | } | 191 | } |
| 162 | 192 | ||
| 163 | static int clk_pllv2_prepare(struct clk_hw *hw) | 193 | static int clk_pllv2_prepare(struct clk_hw *hw) |
