1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef __CLK_STARFIVE_JH71X0_H |
3 | #define __CLK_STARFIVE_JH71X0_H |
4 | |
5 | #include <linux/bits.h> |
6 | #include <linux/clk-provider.h> |
7 | #include <linux/device.h> |
8 | #include <linux/spinlock.h> |
9 | |
10 | /* register fields */ |
11 | #define JH71X0_CLK_ENABLE BIT(31) |
12 | #define JH71X0_CLK_INVERT BIT(30) |
13 | #define JH71X0_CLK_MUX_MASK GENMASK(27, 24) |
14 | #define JH71X0_CLK_MUX_SHIFT 24 |
15 | #define JH71X0_CLK_DIV_MASK GENMASK(23, 0) |
16 | #define JH71X0_CLK_FRAC_MASK GENMASK(15, 8) |
17 | #define JH71X0_CLK_FRAC_SHIFT 8 |
18 | #define JH71X0_CLK_INT_MASK GENMASK(7, 0) |
19 | |
20 | /* fractional divider min/max */ |
21 | #define JH71X0_CLK_FRAC_MIN 100UL |
22 | #define JH71X0_CLK_FRAC_MAX 25599UL |
23 | |
24 | /* clock data */ |
25 | struct jh71x0_clk_data { |
26 | const char *name; |
27 | unsigned long flags; |
28 | u32 max; |
29 | u8 parents[4]; |
30 | }; |
31 | |
32 | #define JH71X0_GATE(_idx, _name, _flags, _parent) \ |
33 | [_idx] = { \ |
34 | .name = _name, \ |
35 | .flags = CLK_SET_RATE_PARENT | (_flags), \ |
36 | .max = JH71X0_CLK_ENABLE, \ |
37 | .parents = { [0] = _parent }, \ |
38 | } |
39 | |
40 | #define JH71X0__DIV(_idx, _name, _max, _parent) \ |
41 | [_idx] = { \ |
42 | .name = _name, \ |
43 | .flags = 0, \ |
44 | .max = _max, \ |
45 | .parents = { [0] = _parent }, \ |
46 | } |
47 | |
48 | #define JH71X0_GDIV(_idx, _name, _flags, _max, _parent) \ |
49 | [_idx] = { \ |
50 | .name = _name, \ |
51 | .flags = _flags, \ |
52 | .max = JH71X0_CLK_ENABLE | (_max), \ |
53 | .parents = { [0] = _parent }, \ |
54 | } |
55 | |
56 | #define JH71X0_FDIV(_idx, _name, _parent) \ |
57 | [_idx] = { \ |
58 | .name = _name, \ |
59 | .flags = 0, \ |
60 | .max = JH71X0_CLK_FRAC_MAX, \ |
61 | .parents = { [0] = _parent }, \ |
62 | } |
63 | |
64 | #define JH71X0__MUX(_idx, _name, _flags, _nparents, ...) \ |
65 | [_idx] = { \ |
66 | .name = _name, \ |
67 | .flags = _flags, \ |
68 | .max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT, \ |
69 | .parents = { __VA_ARGS__ }, \ |
70 | } |
71 | |
72 | #define JH71X0_GMUX(_idx, _name, _flags, _nparents, ...) \ |
73 | [_idx] = { \ |
74 | .name = _name, \ |
75 | .flags = _flags, \ |
76 | .max = JH71X0_CLK_ENABLE | \ |
77 | (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT), \ |
78 | .parents = { __VA_ARGS__ }, \ |
79 | } |
80 | |
81 | #define JH71X0_MDIV(_idx, _name, _max, _nparents, ...) \ |
82 | [_idx] = { \ |
83 | .name = _name, \ |
84 | .flags = 0, \ |
85 | .max = (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max), \ |
86 | .parents = { __VA_ARGS__ }, \ |
87 | } |
88 | |
89 | #define JH71X0__GMD(_idx, _name, _flags, _max, _nparents, ...) \ |
90 | [_idx] = { \ |
91 | .name = _name, \ |
92 | .flags = _flags, \ |
93 | .max = JH71X0_CLK_ENABLE | \ |
94 | (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max), \ |
95 | .parents = { __VA_ARGS__ }, \ |
96 | } |
97 | |
98 | #define JH71X0__INV(_idx, _name, _parent) \ |
99 | [_idx] = { \ |
100 | .name = _name, \ |
101 | .flags = CLK_SET_RATE_PARENT, \ |
102 | .max = JH71X0_CLK_INVERT, \ |
103 | .parents = { [0] = _parent }, \ |
104 | } |
105 | |
106 | struct jh71x0_clk { |
107 | struct clk_hw hw; |
108 | unsigned int idx; |
109 | unsigned int max_div; |
110 | }; |
111 | |
112 | struct jh71x0_clk_priv { |
113 | /* protect clk enable and set rate/parent from happening at the same time */ |
114 | spinlock_t rmw_lock; |
115 | struct device *dev; |
116 | void __iomem *base; |
117 | struct clk_hw *pll[3]; |
118 | struct jh71x0_clk reg[]; |
119 | }; |
120 | |
121 | const struct clk_ops *starfive_jh71x0_clk_ops(u32 max); |
122 | |
123 | #endif |
124 | |