1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __CLK_STARFIVE_JH7100_H
3 #define __CLK_STARFIVE_JH7100_H
4 
5 #include <linux/bits.h>
6 #include <linux/clk-provider.h>
7 
8 /* register fields */
9 #define JH7100_CLK_ENABLE	BIT(31)
10 #define JH7100_CLK_INVERT	BIT(30)
11 #define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
12 #define JH7100_CLK_MUX_SHIFT	24
13 #define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
14 #define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
15 #define JH7100_CLK_FRAC_SHIFT	8
16 #define JH7100_CLK_INT_MASK	GENMASK(7, 0)
17 
18 /* fractional divider min/max */
19 #define JH7100_CLK_FRAC_MIN	100UL
20 #define JH7100_CLK_FRAC_MAX	25599UL
21 
22 /* clock data */
23 struct jh7100_clk_data {
24 	const char *name;
25 	unsigned long flags;
26 	u32 max;
27 	u8 parents[4];
28 };
29 
30 #define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {			\
31 	.name = _name,								\
32 	.flags = CLK_SET_RATE_PARENT | (_flags),				\
33 	.max = JH7100_CLK_ENABLE,						\
34 	.parents = { [0] = _parent },						\
35 }
36 
37 #define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = {			\
38 	.name = _name,								\
39 	.flags = 0,								\
40 	.max = _max,								\
41 	.parents = { [0] = _parent },						\
42 }
43 
44 #define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = {		\
45 	.name = _name,								\
46 	.flags = _flags,							\
47 	.max = JH7100_CLK_ENABLE | (_max),					\
48 	.parents = { [0] = _parent },						\
49 }
50 
51 #define JH7100_FDIV(_idx, _name, _parent) [_idx] = {				\
52 	.name = _name,								\
53 	.flags = 0,								\
54 	.max = JH7100_CLK_FRAC_MAX,						\
55 	.parents = { [0] = _parent },						\
56 }
57 
58 #define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {			\
59 	.name = _name,								\
60 	.flags = 0,								\
61 	.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT,			\
62 	.parents = { __VA_ARGS__ },						\
63 }
64 
65 #define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = {		\
66 	.name = _name,								\
67 	.flags = _flags,							\
68 	.max = JH7100_CLK_ENABLE |						\
69 		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT),			\
70 	.parents = { __VA_ARGS__ },						\
71 }
72 
73 #define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = {		\
74 	.name = _name,								\
75 	.flags = 0,								\
76 	.max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
77 	.parents = { __VA_ARGS__ },						\
78 }
79 
80 #define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = {	\
81 	.name = _name,								\
82 	.flags = _flags,							\
83 	.max = JH7100_CLK_ENABLE |						\
84 		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
85 	.parents = { __VA_ARGS__ },						\
86 }
87 
88 #define JH7100__INV(_idx, _name, _parent) [_idx] = {				\
89 	.name = _name,								\
90 	.flags = CLK_SET_RATE_PARENT,						\
91 	.max = JH7100_CLK_INVERT,						\
92 	.parents = { [0] = _parent },						\
93 }
94 
95 struct jh7100_clk {
96 	struct clk_hw hw;
97 	unsigned int idx;
98 	unsigned int max_div;
99 };
100 
101 struct jh7100_clk_priv {
102 	/* protect clk enable and set rate/parent from happening at the same time */
103 	spinlock_t rmw_lock;
104 	struct device *dev;
105 	void __iomem *base;
106 	struct clk_hw *pll[3];
107 	struct jh7100_clk reg[];
108 };
109 
110 const struct clk_ops *starfive_jh7100_clk_ops(u32 max);
111 
112 #endif
113