xref: /openbmc/linux/drivers/clk/baikal-t1/ccu-div.h (revision 35b76602)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
4  *
5  * Baikal-T1 CCU Dividers interface driver
6  */
7 #ifndef __CLK_BT1_CCU_DIV_H__
8 #define __CLK_BT1_CCU_DIV_H__
9 
10 #include <linux/clk-provider.h>
11 #include <linux/spinlock.h>
12 #include <linux/regmap.h>
13 #include <linux/bits.h>
14 #include <linux/of.h>
15 
16 /*
17  * CCU Divider private clock IDs
18  * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock
19  */
20 #define CCU_SYS_XGMAC_CLK		-2
21 
22 /*
23  * CCU Divider private flags
24  * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1.
25  *		      It can be 0 though, which is functionally the same.
26  * @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3].
27  *			       It can be either 0 or greater than 3.
28  * @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position.
29  * @CCU_DIV_RESET_DOMAIN: Provide reset clock domain method.
30  */
31 #define CCU_DIV_SKIP_ONE		BIT(1)
32 #define CCU_DIV_SKIP_ONE_TO_THREE	BIT(2)
33 #define CCU_DIV_LOCK_SHIFTED		BIT(3)
34 #define CCU_DIV_RESET_DOMAIN		BIT(4)
35 
36 /*
37  * enum ccu_div_type - CCU Divider types
38  * @CCU_DIV_VAR: Clocks gate with variable divider.
39  * @CCU_DIV_GATE: Clocks gate with fixed divider.
40  * @CCU_DIV_FIXED: Ungateable clock with fixed divider.
41  */
42 enum ccu_div_type {
43 	CCU_DIV_VAR,
44 	CCU_DIV_GATE,
45 	CCU_DIV_FIXED
46 };
47 
48 /*
49  * struct ccu_div_init_data - CCU Divider initialization data
50  * @id: Clocks private identifier.
51  * @name: Clocks name.
52  * @parent_name: Parent clocks name in a fw node.
53  * @base: Divider register base address with respect to the sys_regs base.
54  * @sys_regs: Baikal-T1 System Controller registers map.
55  * @np: Pointer to the node describing the CCU Dividers.
56  * @type: CCU divider type (variable, fixed with and without gate).
57  * @width: Divider width if it's variable.
58  * @divider: Divider fixed value.
59  * @flags: CCU Divider clock flags.
60  * @features: CCU Divider private features.
61  */
62 struct ccu_div_init_data {
63 	unsigned int id;
64 	const char *name;
65 	const char *parent_name;
66 	unsigned int base;
67 	struct regmap *sys_regs;
68 	struct device_node *np;
69 	enum ccu_div_type type;
70 	union {
71 		unsigned int width;
72 		unsigned int divider;
73 	};
74 	unsigned long flags;
75 	unsigned long features;
76 };
77 
78 /*
79  * struct ccu_div - CCU Divider descriptor
80  * @hw: clk_hw of the divider.
81  * @id: Clock private identifier.
82  * @reg_ctl: Divider control register base address.
83  * @sys_regs: Baikal-T1 System Controller registers map.
84  * @lock: Divider state change spin-lock.
85  * @mask: Divider field mask.
86  * @divider: Divider fixed value.
87  * @flags: Divider clock flags.
88  * @features: CCU Divider private features.
89  */
90 struct ccu_div {
91 	struct clk_hw hw;
92 	unsigned int id;
93 	unsigned int reg_ctl;
94 	struct regmap *sys_regs;
95 	spinlock_t lock;
96 	union {
97 		u32 mask;
98 		unsigned int divider;
99 	};
100 	unsigned long flags;
101 	unsigned long features;
102 };
103 #define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw)
104 
105 static inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)
106 {
107 	return div ? &div->hw : NULL;
108 }
109 
110 struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);
111 
112 void ccu_div_hw_unregister(struct ccu_div *div);
113 
114 int ccu_div_reset_domain(struct ccu_div *div);
115 
116 #endif /* __CLK_BT1_CCU_DIV_H__ */
117