aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ingenic/cgu.c
diff options
context:
space:
mode:
authorHarvey Hunt <harvey.hunt@imgtec.com>2016-05-09 17:29:52 +0100
committerStephen Boyd <sboyd@codeaurora.org>2016-05-12 14:48:25 -0700
commit4afe2d1a6ed5cba794aeeaa816e7c97a45167b01 (patch)
treee88fd50b5e791760c7abb20f01e087c53583fe34 /drivers/clk/ingenic/cgu.c
parentMerge tag 'v4.7-rockchip-clk4' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into clk-next (diff)
downloadlinux-dev-4afe2d1a6ed5cba794aeeaa816e7c97a45167b01.tar.xz
linux-dev-4afe2d1a6ed5cba794aeeaa816e7c97a45167b01.zip
clk: ingenic: Allow divider value to be divided
The JZ4780's MSC clock divider registers multiply the clock divider by 2. This means that MMC devices run at half their expected speed. Add the ability to divide the clock divider in order to solve this. Signed-off-by: Harvey Hunt <harvey.hunt@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-clk@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers/clk/ingenic/cgu.c')
-rw-r--r--drivers/clk/ingenic/cgu.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 7cfb7b2a2ed6..e8248f9185f7 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -325,6 +325,7 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
div = (div_reg >> clk_info->div.shift) &
GENMASK(clk_info->div.bits - 1, 0);
div += 1;
+ div *= clk_info->div.div;
rate /= div;
}
@@ -345,6 +346,14 @@ ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
div = min_t(unsigned, div, 1 << clk_info->div.bits);
div = max_t(unsigned, div, 1);
+ /*
+ * If the divider value itself must be divided before being written to
+ * the divider register, we must ensure we don't have any bits set that
+ * would be lost as a result of doing so.
+ */
+ div /= clk_info->div.div;
+ div *= clk_info->div.div;
+
return div;
}
@@ -395,7 +404,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
/* update the divide */
mask = GENMASK(clk_info->div.bits - 1, 0);
reg &= ~(mask << clk_info->div.shift);
- reg |= (div - 1) << clk_info->div.shift;
+ reg |= ((div / clk_info->div.div) - 1) << clk_info->div.shift;
/* clear the stop bit */
if (clk_info->div.stop_bit != -1)