uboot-sunxi: bump u-boot version
[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