aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2014-09-26 20:04:08 -0400
committerMike Turquette <mturquette@linaro.org>2014-09-26 20:04:08 -0400
commit8791db53a9d2556b8908af300d8327eecb110d8a (patch)
tree760ae9de15ea3f642e55824dd7be1b4bef9bd6a1
parentc873d14d30b838a516a94967242322d4b73e79e7 (diff)
parentceac26c64200015a5e6e358e903b1ca9a6f41dd8 (diff)
Merge tag 'clk-mvebu-3.18' of git://git.infradead.org/linux-mvebu into clk-next
clock changes for mvebu for v3.18 - correct timer drift caused by SSCG deviation - fix typo in comment
-rw-r--r--drivers/clk/mvebu/armada-370.c8
-rw-r--r--drivers/clk/mvebu/armada-375.c4
-rw-r--r--drivers/clk/mvebu/common.c82
-rw-r--r--drivers/clk/mvebu/common.h7
4 files changed, 99 insertions, 2 deletions
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index bef198a83863..756f0f39d6a3 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#define SARL 0 /* Low part [0:31] */ 25#define SARL 0 /* Low part [0:31] */
26#define SARL_A370_SSCG_ENABLE BIT(10)
26#define SARL_A370_PCLK_FREQ_OPT 11 27#define SARL_A370_PCLK_FREQ_OPT 11
27#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF 28#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
28#define SARL_A370_FAB_FREQ_OPT 15 29#define SARL_A370_FAB_FREQ_OPT 15
@@ -133,10 +134,17 @@ static void __init a370_get_clk_ratio(
133 } 134 }
134} 135}
135 136
137static bool a370_is_sscg_enabled(void __iomem *sar)
138{
139 return !(readl(sar) & SARL_A370_SSCG_ENABLE);
140}
141
136static const struct coreclk_soc_desc a370_coreclks = { 142static const struct coreclk_soc_desc a370_coreclks = {
137 .get_tclk_freq = a370_get_tclk_freq, 143 .get_tclk_freq = a370_get_tclk_freq,
138 .get_cpu_freq = a370_get_cpu_freq, 144 .get_cpu_freq = a370_get_cpu_freq,
139 .get_clk_ratio = a370_get_clk_ratio, 145 .get_clk_ratio = a370_get_clk_ratio,
146 .is_sscg_enabled = a370_is_sscg_enabled,
147 .fix_sscg_deviation = kirkwood_fix_sscg_deviation,
140 .ratios = a370_coreclk_ratios, 148 .ratios = a370_coreclk_ratios,
141 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), 149 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
142}; 150};
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c
index c991a4d95e10..c7af2242b796 100644
--- a/drivers/clk/mvebu/armada-375.c
+++ b/drivers/clk/mvebu/armada-375.c
@@ -27,14 +27,14 @@
27 * all modified at the same time, and not separately as for the Armada 27 * all modified at the same time, and not separately as for the Armada
28 * 370 or the Armada XP SoCs. 28 * 370 or the Armada XP SoCs.
29 * 29 *
30 * SAR0[21:17] : CPU frequency DDR frequency L2 frequency 30 * SAR1[21:17] : CPU frequency DDR frequency L2 frequency
31 * 6 = 400 MHz 400 MHz 200 MHz 31 * 6 = 400 MHz 400 MHz 200 MHz
32 * 15 = 600 MHz 600 MHz 300 MHz 32 * 15 = 600 MHz 600 MHz 300 MHz
33 * 21 = 800 MHz 534 MHz 400 MHz 33 * 21 = 800 MHz 534 MHz 400 MHz
34 * 25 = 1000 MHz 500 MHz 500 MHz 34 * 25 = 1000 MHz 500 MHz 500 MHz
35 * others reserved. 35 * others reserved.
36 * 36 *
37 * SAR0[22] : TCLK frequency 37 * SAR1[22] : TCLK frequency
38 * 0 = 166 MHz 38 * 0 = 166 MHz
39 * 1 = 200 MHz 39 * 1 = 200 MHz
40 */ 40 */
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 8145c4efc381..7f8a33ab265b 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -26,8 +26,85 @@
26 * Core Clocks 26 * Core Clocks
27 */ 27 */
28 28
29#define SSCG_CONF_MODE(reg) (((reg) >> 16) & 0x3)
30#define SSCG_SPREAD_DOWN 0x0
31#define SSCG_SPREAD_UP 0x1
32#define SSCG_SPREAD_CENTRAL 0x2
33#define SSCG_CONF_LOW(reg) (((reg) >> 8) & 0xFF)
34#define SSCG_CONF_HIGH(reg) ((reg) & 0xFF)
35
29static struct clk_onecell_data clk_data; 36static struct clk_onecell_data clk_data;
30 37
38/*
39 * This function can be used by the Kirkwood, the Armada 370, the
40 * Armada XP and the Armada 375 SoC. The name of the function was
41 * chosen following the dt convention: using the first known SoC
42 * compatible with it.
43 */
44u32 kirkwood_fix_sscg_deviation(struct device_node *np, u32 system_clk)
45{
46 struct device_node *sscg_np = NULL;
47 void __iomem *sscg_map;
48 u32 sscg_reg;
49 s32 low_bound, high_bound;
50 u64 freq_swing_half;
51
52 sscg_np = of_find_node_by_name(np, "sscg");
53 if (sscg_np == NULL) {
54 pr_err("cannot get SSCG register node\n");
55 return system_clk;
56 }
57
58 sscg_map = of_iomap(sscg_np, 0);
59 if (sscg_map == NULL) {
60 pr_err("cannot map SSCG register\n");
61 goto out;
62 }
63
64 sscg_reg = readl(sscg_map);
65 high_bound = SSCG_CONF_HIGH(sscg_reg);
66 low_bound = SSCG_CONF_LOW(sscg_reg);
67
68 if ((high_bound - low_bound) <= 0)
69 goto out;
70 /*
71 * From Marvell engineer we got the following formula (when
72 * this code was written, the datasheet was erroneous)
73 * Spread percentage = 1/96 * (H - L) / H
74 * H = SSCG_High_Boundary
75 * L = SSCG_Low_Boundary
76 *
77 * As the deviation is half of spread then it lead to the
78 * following formula in the code.
79 *
80 * To avoid an overflow and not lose any significant digit in
81 * the same time we have to use a 64 bit integer.
82 */
83
84 freq_swing_half = (((u64)high_bound - (u64)low_bound)
85 * (u64)system_clk);
86 do_div(freq_swing_half, (2 * 96 * high_bound));
87
88 switch (SSCG_CONF_MODE(sscg_reg)) {
89 case SSCG_SPREAD_DOWN:
90 system_clk -= freq_swing_half;
91 break;
92 case SSCG_SPREAD_UP:
93 system_clk += freq_swing_half;
94 break;
95 case SSCG_SPREAD_CENTRAL:
96 default:
97 break;
98 }
99
100 iounmap(sscg_map);
101
102out:
103 of_node_put(sscg_np);
104
105 return system_clk;
106}
107
31void __init mvebu_coreclk_setup(struct device_node *np, 108void __init mvebu_coreclk_setup(struct device_node *np,
32 const struct coreclk_soc_desc *desc) 109 const struct coreclk_soc_desc *desc)
33{ 110{
@@ -62,6 +139,11 @@ void __init mvebu_coreclk_setup(struct device_node *np,
62 of_property_read_string_index(np, "clock-output-names", 1, 139 of_property_read_string_index(np, "clock-output-names", 1,
63 &cpuclk_name); 140 &cpuclk_name);
64 rate = desc->get_cpu_freq(base); 141 rate = desc->get_cpu_freq(base);
142
143 if (desc->is_sscg_enabled && desc->fix_sscg_deviation
144 && desc->is_sscg_enabled(base))
145 rate = desc->fix_sscg_deviation(np, rate);
146
65 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL, 147 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
66 CLK_IS_ROOT, rate); 148 CLK_IS_ROOT, rate);
67 WARN_ON(IS_ERR(clk_data.clks[1])); 149 WARN_ON(IS_ERR(clk_data.clks[1]));
diff --git a/drivers/clk/mvebu/common.h b/drivers/clk/mvebu/common.h
index 8cd28e47471c..8f8db7eac3f6 100644
--- a/drivers/clk/mvebu/common.h
+++ b/drivers/clk/mvebu/common.h
@@ -30,6 +30,8 @@ struct coreclk_soc_desc {
30 u32 (*get_tclk_freq)(void __iomem *sar); 30 u32 (*get_tclk_freq)(void __iomem *sar);
31 u32 (*get_cpu_freq)(void __iomem *sar); 31 u32 (*get_cpu_freq)(void __iomem *sar);
32 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div); 32 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
33 bool (*is_sscg_enabled)(void __iomem *sar);
34 u32 (*fix_sscg_deviation)(struct device_node *np, u32 system_clk);
33 const struct coreclk_ratio *ratios; 35 const struct coreclk_ratio *ratios;
34 int num_ratios; 36 int num_ratios;
35}; 37};
@@ -47,4 +49,9 @@ void __init mvebu_coreclk_setup(struct device_node *np,
47void __init mvebu_clk_gating_setup(struct device_node *np, 49void __init mvebu_clk_gating_setup(struct device_node *np,
48 const struct clk_gating_soc_desc *desc); 50 const struct clk_gating_soc_desc *desc);
49 51
52/*
53 * This function is shared among the Kirkwood, Armada 370, Armada XP
54 * and Armada 375 SoC
55 */
56u32 kirkwood_fix_sscg_deviation(struct device_node *np, u32 system_clk);
50#endif 57#endif