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 */
25struct 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, _nparents, ...)				\
65[_idx] = {									\
66	.name = _name,								\
67	.flags = 0,								\
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
106struct jh71x0_clk {
107	struct clk_hw hw;
108	unsigned int idx;
109	unsigned int max_div;
110};
111
112struct 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
121const struct clk_ops *starfive_jh71x0_clk_ops(u32 max);
122
123#endif
124