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