summaryrefslogtreecommitdiff
path: root/drivers/clk/sunxi/clk-sun8i-mbus.c
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2014-09-27 23:52:33 +0400
committerMike Turquette <mturquette@linaro.org>2014-09-27 23:52:33 +0400
commit4dc7ed32f398fa76b9e1d243a852420b1dad0150 (patch)
treea040f8c006ea7a7a3c962f135c8efd8b72cbc4b4 /drivers/clk/sunxi/clk-sun8i-mbus.c
parent5ad67d3e5e0a5059945a7726a407763a23f80d9e (diff)
parent9c8176bfb67f98ed9a521b624dcb6ab7fa254aa7 (diff)
downloadlinux-4dc7ed32f398fa76b9e1d243a852420b1dad0150.tar.xz
Merge tag 'sunxi-clocks-for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into clk-next
Allwinner Clocks Additions for 3.18 The most important part of this serie is the addition of the phase API to handle the MMC clocks in the Allwinner SoCs. Apart from that, the A23 gained a new mbus driver, and there's a fix for a incorrect divider table on the APB0 clock.
Diffstat (limited to 'drivers/clk/sunxi/clk-sun8i-mbus.c')
-rw-r--r--drivers/clk/sunxi/clk-sun8i-mbus.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c
new file mode 100644
index 000000000000..8e49b44cee41
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+
+#include "clk-factors.h"
+
+/**
+ * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks
+ * MBUS rate is calculated as follows
+ * rate = parent_rate / (m + 1);
+ */
+
+static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /*
+ * These clocks can only divide, so we will never be able to
+ * achieve frequencies higher than the parent frequency
+ */
+ if (*freq > parent_rate)
+ *freq = parent_rate;
+
+ div = DIV_ROUND_UP(parent_rate, *freq);
+
+ if (div > 8)
+ div = 8;
+
+ *freq = parent_rate / div;
+
+ /* we were called to round the frequency, we can now return */
+ if (m == NULL)
+ return;
+
+ *m = div - 1;
+}
+
+static struct clk_factors_config sun8i_a23_mbus_config = {
+ .mshift = 0,
+ .mwidth = 3,
+};
+
+static const struct factors_data sun8i_a23_mbus_data __initconst = {
+ .enable = 31,
+ .mux = 24,
+ .table = &sun8i_a23_mbus_config,
+ .getter = sun8i_a23_get_mbus_factors,
+};
+
+static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
+
+static void __init sun8i_a23_mbus_setup(struct device_node *node)
+{
+ struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
+ &sun8i_a23_mbus_lock);
+
+ /* The MBUS clocks needs to be always enabled */
+ __clk_get(mbus);
+ clk_prepare_enable(mbus);
+}
+CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);