aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk-mod0.c82
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c1
3 files changed, 83 insertions, 1 deletions
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6850cba35871..833f086d4a52 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,7 @@
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o 6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o 7obj-y += clk-a20-gmac.o
8obj-y += clk-mod0.o
8 9
9obj-$(CONFIG_MFD_SUN6I_PRCM) += \ 10obj-$(CONFIG_MFD_SUN6I_PRCM) += \
10 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ 11 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
new file mode 100644
index 000000000000..bce09a84ab4f
--- /dev/null
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -0,0 +1,82 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19
20#include "clk-factors.h"
21
22/**
23 * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
24 * MOD0 rate is calculated as follows
25 * rate = (parent_rate >> p) / (m + 1);
26 */
27
28static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
29 u8 *n, u8 *k, u8 *m, u8 *p)
30{
31 u8 div, calcm, calcp;
32
33 /* These clocks can only divide, so we will never be able to achieve
34 * frequencies higher than the parent frequency */
35 if (*freq > parent_rate)
36 *freq = parent_rate;
37
38 div = DIV_ROUND_UP(parent_rate, *freq);
39
40 if (div < 16)
41 calcp = 0;
42 else if (div / 2 < 16)
43 calcp = 1;
44 else if (div / 4 < 16)
45 calcp = 2;
46 else
47 calcp = 3;
48
49 calcm = DIV_ROUND_UP(div, 1 << calcp);
50
51 *freq = (parent_rate >> calcp) / calcm;
52
53 /* we were called to round the frequency, we can now return */
54 if (n == NULL)
55 return;
56
57 *m = calcm - 1;
58 *p = calcp;
59}
60
61/* user manual says "n" but it's really "p" */
62static struct clk_factors_config sun4i_a10_mod0_config = {
63 .mshift = 0,
64 .mwidth = 4,
65 .pshift = 16,
66 .pwidth = 2,
67};
68
69static const struct factors_data sun4i_a10_mod0_data __initconst = {
70 .enable = 31,
71 .mux = 24,
72 .table = &sun4i_a10_mod0_config,
73 .getter = sun4i_a10_get_mod0_factors,
74};
75
76static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
77
78static void __init sun4i_a10_mod0_setup(struct device_node *node)
79{
80 sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
81}
82CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 17e1e3bec954..fc5549447772 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1120,7 +1120,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
1120 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, 1120 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
1121 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, 1121 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1122 {.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,}, 1122 {.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
1123 {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
1124 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1123 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
1125 {} 1124 {}
1126}; 1125};