1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Marvell PXA family clocks |
4 | * |
5 | * Copyright (C) 2014 Robert Jarzmik |
6 | * |
7 | * Common clock code for PXA clocks ("CKEN" type clocks + DT) |
8 | */ |
9 | #ifndef _CLK_PXA_ |
10 | #define _CLK_PXA_ |
11 | |
12 | #define CLKCFG_TURBO 0x1 |
13 | #define CLKCFG_FCS 0x2 |
14 | #define CLKCFG_HALFTURBO 0x4 |
15 | #define CLKCFG_FASTBUS 0x8 |
16 | |
17 | #define PARENTS(name) \ |
18 | static const char *const name ## _parents[] __initconst |
19 | #define MUX_RO_RATE_RO_OPS(name, clk_name) \ |
20 | static struct clk_hw name ## _mux_hw; \ |
21 | static struct clk_hw name ## _rate_hw; \ |
22 | static const struct clk_ops name ## _mux_ops = { \ |
23 | .get_parent = name ## _get_parent, \ |
24 | .set_parent = dummy_clk_set_parent, \ |
25 | }; \ |
26 | static const struct clk_ops name ## _rate_ops = { \ |
27 | .recalc_rate = name ## _get_rate, \ |
28 | }; \ |
29 | static struct clk * __init clk_register_ ## name(void) \ |
30 | { \ |
31 | return clk_register_composite(NULL, clk_name, \ |
32 | name ## _parents, \ |
33 | ARRAY_SIZE(name ## _parents), \ |
34 | &name ## _mux_hw, &name ## _mux_ops, \ |
35 | &name ## _rate_hw, &name ## _rate_ops, \ |
36 | NULL, NULL, CLK_GET_RATE_NOCACHE); \ |
37 | } |
38 | |
39 | #define RATE_RO_OPS(name, clk_name) \ |
40 | static struct clk_hw name ## _rate_hw; \ |
41 | static const struct clk_ops name ## _rate_ops = { \ |
42 | .recalc_rate = name ## _get_rate, \ |
43 | }; \ |
44 | static struct clk * __init clk_register_ ## name(void) \ |
45 | { \ |
46 | return clk_register_composite(NULL, clk_name, \ |
47 | name ## _parents, \ |
48 | ARRAY_SIZE(name ## _parents), \ |
49 | NULL, NULL, \ |
50 | &name ## _rate_hw, &name ## _rate_ops, \ |
51 | NULL, NULL, CLK_GET_RATE_NOCACHE); \ |
52 | } |
53 | |
54 | #define RATE_OPS(name, clk_name) \ |
55 | static struct clk_hw name ## _rate_hw; \ |
56 | static const struct clk_ops name ## _rate_ops = { \ |
57 | .recalc_rate = name ## _get_rate, \ |
58 | .set_rate = name ## _set_rate, \ |
59 | .determine_rate = name ## _determine_rate, \ |
60 | }; \ |
61 | static struct clk * __init clk_register_ ## name(void) \ |
62 | { \ |
63 | return clk_register_composite(NULL, clk_name, \ |
64 | name ## _parents, \ |
65 | ARRAY_SIZE(name ## _parents), \ |
66 | NULL, NULL, \ |
67 | &name ## _rate_hw, &name ## _rate_ops, \ |
68 | NULL, NULL, CLK_GET_RATE_NOCACHE); \ |
69 | } |
70 | |
71 | #define MUX_OPS(name, clk_name, flags) \ |
72 | static struct clk_hw name ## _mux_hw; \ |
73 | static const struct clk_ops name ## _mux_ops = { \ |
74 | .get_parent = name ## _get_parent, \ |
75 | .set_parent = name ## _set_parent, \ |
76 | .determine_rate = name ## _determine_rate, \ |
77 | }; \ |
78 | static struct clk * __init clk_register_ ## name(void) \ |
79 | { \ |
80 | return clk_register_composite(NULL, clk_name, \ |
81 | name ## _parents, \ |
82 | ARRAY_SIZE(name ## _parents), \ |
83 | &name ## _mux_hw, &name ## _mux_ops, \ |
84 | NULL, NULL, \ |
85 | NULL, NULL, \ |
86 | CLK_GET_RATE_NOCACHE | flags); \ |
87 | } |
88 | |
89 | /* |
90 | * CKEN clock type |
91 | * This clock takes it source from 2 possible parents : |
92 | * - a low power parent |
93 | * - a normal parent |
94 | * |
95 | * +------------+ +-----------+ |
96 | * | Low Power | --- | x mult_lp | |
97 | * | Clock | | / div_lp |\ |
98 | * +------------+ +-----------+ \+-----+ +-----------+ |
99 | * | Mux |---| CKEN gate | |
100 | * +------------+ +-----------+ /+-----+ +-----------+ |
101 | * | High Power | | x mult_hp |/ |
102 | * | Clock | --- | / div_hp | |
103 | * +------------+ +-----------+ |
104 | */ |
105 | struct desc_clk_cken { |
106 | struct clk_hw hw; |
107 | int ckid; |
108 | int cken_reg; |
109 | const char *name; |
110 | const char *dev_id; |
111 | const char *con_id; |
112 | const char * const *parent_names; |
113 | struct clk_fixed_factor lp; |
114 | struct clk_fixed_factor hp; |
115 | struct clk_gate gate; |
116 | bool (*is_in_low_power)(void); |
117 | const unsigned long flags; |
118 | }; |
119 | |
120 | #define PXA_CKEN(_dev_id, _con_id, _name, parents, _mult_lp, _div_lp, \ |
121 | _mult_hp, _div_hp, is_lp, _cken_reg, _cken_bit, flag) \ |
122 | { .ckid = CLK_ ## _name, .name = #_name, \ |
123 | .cken_reg = _cken_reg, \ |
124 | .dev_id = _dev_id, .con_id = _con_id, .parent_names = parents,\ |
125 | .lp = { .mult = _mult_lp, .div = _div_lp }, \ |
126 | .hp = { .mult = _mult_hp, .div = _div_hp }, \ |
127 | .is_in_low_power = is_lp, \ |
128 | .gate = { .bit_idx = _cken_bit }, \ |
129 | .flags = flag, \ |
130 | } |
131 | #define PXA_CKEN_1RATE(dev_id, con_id, name, parents, cken_reg, \ |
132 | cken_bit, flag) \ |
133 | PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \ |
134 | NULL, cken_reg, cken_bit, flag) |
135 | |
136 | struct pxa2xx_freq { |
137 | unsigned long cpll; |
138 | unsigned int membus_khz; |
139 | unsigned int cccr; |
140 | unsigned int div2; |
141 | unsigned int clkcfg; |
142 | }; |
143 | |
144 | static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index) |
145 | { |
146 | return 0; |
147 | } |
148 | |
149 | extern void clkdev_pxa_register(int ckid, const char *con_id, |
150 | const char *dev_id, struct clk *clk); |
151 | extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, |
152 | int nb_clks, void __iomem *clk_regs); |
153 | void clk_pxa_dt_common_init(struct device_node *np); |
154 | |
155 | void pxa2xx_core_turbo_switch(bool on); |
156 | void pxa2xx_cpll_change(struct pxa2xx_freq *freq, |
157 | u32 (*mdrefr_dri)(unsigned int), |
158 | void __iomem *cccr); |
159 | int pxa2xx_determine_rate(struct clk_rate_request *req, |
160 | struct pxa2xx_freq *freqs, int nb_freqs); |
161 | |
162 | #endif |
163 | |