uboot-sunxi: bump u-boot version - update u-boot to 2014.01-rc1 - smp support on a20
[openwrt/openwrt.git] / target / linux / sunxi / patches-3.12 / 110-clk-sunxi-fix-pll5-6.patch
1 From 11e7ff129807394d87c937b880bb58972dc91fc0 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
3 Date: Thu, 28 Nov 2013 09:00:47 -0300
4 Subject: [PATCH] fixup! clk: sunxi: add PLL5 and PLL6 support
5
6 ---
7 drivers/clk/sunxi/clk-sunxi.c | 83 +++++++++++++++++++++++++++++++++++--------
8 1 file changed, 69 insertions(+), 14 deletions(-)
9
10 diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
11 index d2b8d3c..3ce33b8 100644
12 --- a/drivers/clk/sunxi/clk-sunxi.c
13 +++ b/drivers/clk/sunxi/clk-sunxi.c
14 @@ -807,10 +807,11 @@ struct divs_data {
15 struct clk_div_table *table; /* is it a table based divisor? */
16 u8 shift; /* otherwise it's a normal divisor with this shift */
17 u8 pow; /* is it power-of-two based? */
18 + u8 gate; /* is it independently gateable? */
19 } div[SUNXI_DIVS_MAX_QTY];
20 };
21
22 -static struct clk_div_table pll6_sata_table[] = {
23 +static struct clk_div_table pll6_sata_tbl[] = {
24 { .val = 0, .div = 6, },
25 { .val = 1, .div = 12, },
26 { .val = 2, .div = 18, },
27 @@ -829,7 +830,7 @@ struct divs_data {
28 static const struct divs_data pll6_divs_data __initconst = {
29 .factors = &sun4i_pll5_data,
30 .div = {
31 - { .shift = 0, .table = pll6_sata_table }, /* M, SATA */
32 + { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
33 { .fixed = 2 }, /* P, other */
34 }
35 };
36 @@ -852,6 +853,11 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
37 const char *parent = node->name;
38 const char *clk_name;
39 struct clk **clks, *pclk;
40 + struct clk_hw *gate_hw, *rate_hw;
41 + const struct clk_ops *rate_ops;
42 + struct clk_gate *gate = NULL;
43 + struct clk_fixed_factor *fix_factor;
44 + struct clk_divider *divider;
45 void *reg;
46 int i = 0;
47 int flags, clkflags;
48 @@ -866,10 +872,9 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
49 return;
50
51 clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
52 - if (!clks) {
53 - kfree(clk_data);
54 - return;
55 - }
56 + if (!clks)
57 + goto free_clkdata;
58 +
59 clk_data->clks = clks;
60
61 /* It's not a good idea to have automatic reparenting changing
62 @@ -881,19 +886,60 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
63 i, &clk_name) != 0)
64 break;
65
66 + gate_hw = NULL;
67 + rate_hw = NULL;
68 + rate_ops = NULL;
69 +
70 + /* If this leaf clock can be gated, create a gate */
71 + if (data->div[i].gate) {
72 + gate = kzalloc(sizeof(*gate), GFP_KERNEL);
73 + if (!gate)
74 + goto free_clks;
75 +
76 + gate->reg = reg;
77 + gate->bit_idx = data->div[i].gate;
78 + gate->lock = &clk_lock;
79 +
80 + gate_hw = &gate->hw;
81 + }
82 +
83 + /* Leaves can be fixed or configurable divisors */
84 if (data->div[i].fixed) {
85 - clks[i] = clk_register_fixed_factor(NULL, clk_name,
86 - parent, clkflags,
87 - 1, data->div[i].fixed);
88 + fix_factor = kzalloc(sizeof(*fix_factor), GFP_KERNEL);
89 + if (!fix_factor)
90 + goto free_gate;
91 +
92 + fix_factor->mult = 1;
93 + fix_factor->div = data->div[i].fixed;
94 +
95 + rate_hw = &fix_factor->hw;
96 + rate_ops = &clk_fixed_factor_ops;
97 } else {
98 + divider = kzalloc(sizeof(*divider), GFP_KERNEL);
99 + if (!divider)
100 + goto free_gate;
101 +
102 flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
103 - clks[i] = clk_register_divider_table(NULL, clk_name,
104 - parent, clkflags, reg,
105 - data->div[i].shift,
106 - SUNXI_DIVISOR_WIDTH, flags,
107 - data->div[i].table, &clk_lock);
108 +
109 + divider->reg = reg;
110 + divider->shift = data->div[i].shift;
111 + divider->width = SUNXI_DIVISOR_WIDTH;
112 + divider->flags = flags;
113 + divider->lock = &clk_lock;
114 + divider->table = data->div[i].table;
115 +
116 + rate_hw = &divider->hw;
117 + rate_ops = &clk_divider_ops;
118 }
119
120 + /* Wrap the (potential) gate and the divisor on a composite
121 + * clock to unify them */
122 + clks[i] = clk_register_composite(NULL, clk_name, &parent, 1,
123 + NULL, NULL,
124 + rate_hw, rate_ops,
125 + gate_hw, &clk_gate_ops,
126 + clkflags);
127 +
128 WARN_ON(IS_ERR(clk_data->clks[i]));
129 clk_register_clkdev(clks[i], clk_name, NULL);
130 }
131 @@ -905,6 +951,15 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
132 clk_data->clk_num = i;
133
134 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
135 +
136 + return;
137 +
138 +free_gate:
139 + kfree(gate);
140 +free_clks:
141 + kfree(clks);
142 +free_clkdata:
143 + kfree(clk_data);
144 }
145
146
147 --
148 1.8.5.1
149