diff options
-rw-r--r-- | drivers/clk/clk-vt8500.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index a885600f5270..fe25570874d6 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c | |||
@@ -120,8 +120,17 @@ static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw, | |||
120 | static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate, | 120 | static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate, |
121 | unsigned long *prate) | 121 | unsigned long *prate) |
122 | { | 122 | { |
123 | struct clk_device *cdev = to_clk_device(hw); | ||
123 | u32 divisor = *prate / rate; | 124 | u32 divisor = *prate / rate; |
124 | 125 | ||
126 | /* | ||
127 | * If this is a request for SDMMC we have to adjust the divisor | ||
128 | * when >31 to use the fixed predivisor | ||
129 | */ | ||
130 | if ((cdev->div_mask == 0x3F) && (divisor > 31)) { | ||
131 | divisor = 64 * ((divisor / 64) + 1); | ||
132 | } | ||
133 | |||
125 | return *prate / divisor; | 134 | return *prate / divisor; |
126 | } | 135 | } |
127 | 136 | ||
@@ -135,6 +144,15 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate, | |||
135 | if (divisor == cdev->div_mask + 1) | 144 | if (divisor == cdev->div_mask + 1) |
136 | divisor = 0; | 145 | divisor = 0; |
137 | 146 | ||
147 | /* SDMMC mask may need to be corrected before testing if its valid */ | ||
148 | if ((cdev->div_mask == 0x3F) && (divisor > 31)) { | ||
149 | /* | ||
150 | * Bit 5 is a fixed /64 predivisor. If the requested divisor | ||
151 | * is >31 then correct for the fixed divisor being required. | ||
152 | */ | ||
153 | divisor = 0x20 + (divisor / 64); | ||
154 | } | ||
155 | |||
138 | if (divisor > cdev->div_mask) { | 156 | if (divisor > cdev->div_mask) { |
139 | pr_err("%s: invalid divisor for clock\n", __func__); | 157 | pr_err("%s: invalid divisor for clock\n", __func__); |
140 | return -EINVAL; | 158 | return -EINVAL; |