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