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