summaryrefslogtreecommitdiffstats
path: root/drivers/clk/mediatek/clk-mux.h
blob: 943ad1d7ce4bed5c6b6e644fe368393b7eebbd17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2018 MediaTek Inc.
 * Author: Owen Chen <owen.chen@mediatek.com>
 */

#ifndef __DRV_CLK_MTK_MUX_H
#define __DRV_CLK_MTK_MUX_H

#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <linux/types.h>

struct clk;
struct clk_hw_onecell_data;
struct clk_ops;
struct device;
struct device_node;

struct mtk_mux {
	int id;
	const char *name;
	const char * const *parent_names;
	const u8 *parent_index;
	unsigned int flags;

	u32 mux_ofs;
	u32 set_ofs;
	u32 clr_ofs;
	u32 upd_ofs;

	u8 mux_shift;
	u8 mux_width;
	u8 gate_shift;
	s8 upd_shift;

	const struct clk_ops *ops;
	signed char num_parents;
};

#define __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _paridx,		\
			 _num_parents, _mux_ofs, _mux_set_ofs,		\
			 _mux_clr_ofs, _shift, _width, _gate, _upd_ofs,	\
			 _upd, _flags, _ops) {				\
		.id = _id,						\
		.name = _name,						\
		.mux_ofs = _mux_ofs,					\
		.set_ofs = _mux_set_ofs,				\
		.clr_ofs = _mux_clr_ofs,				\
		.upd_ofs = _upd_ofs,					\
		.mux_shift = _shift,					\
		.mux_width = _width,					\
		.gate_shift = _gate,					\
		.upd_shift = _upd,					\
		.parent_names = _parents,				\
		.parent_index = _paridx,				\
		.num_parents = _num_parents,				\
		.flags = _flags,					\
		.ops = &_ops,						\
	}

#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,		\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd, _flags, _ops)		\
		__GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents,		\
			NULL, ARRAY_SIZE(_parents), _mux_ofs,		\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd, _flags, _ops)		\

#define GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, _paridx,	\
			 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift,	\
			 _width, _gate, _upd_ofs, _upd, _flags, _ops)	\
		__GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents,		\
			_paridx, ARRAY_SIZE(_paridx), _mux_ofs,		\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd, _flags, _ops)		\

extern const struct clk_ops mtk_mux_clr_set_upd_ops;
extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;

#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd, _flags)			\
		GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd, _flags,			\
			mtk_mux_gate_clr_set_upd_ops)

#define MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents,	\
			_paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs,	\
			_shift, _width, _gate, _upd_ofs, _upd, _flags)	\
		GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents,	\
			_paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs,	\
			_shift, _width, _gate, _upd_ofs, _upd, _flags,	\
			mtk_mux_gate_clr_set_upd_ops)

#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs,		\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_gate, _upd_ofs, _upd)				\
		MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents,	\
			_mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift,	\
			_width, _gate, _upd_ofs, _upd,			\
			CLK_SET_RATE_PARENT)

#define MUX_GATE_CLR_SET_UPD_INDEXED(_id, _name, _parents, _paridx,	\
			_mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift,	\
			_width, _gate, _upd_ofs, _upd)			\
		MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name,		\
			_parents, _paridx, _mux_ofs, _mux_set_ofs,	\
			_mux_clr_ofs, _shift, _width, _gate, _upd_ofs,	\
			_upd, CLK_SET_RATE_PARENT)

#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs,			\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			_upd_ofs, _upd)					\
		GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
			0, _upd_ofs, _upd, CLK_SET_RATE_PARENT,		\
			mtk_mux_clr_set_upd_ops)

int mtk_clk_register_muxes(struct device *dev,
			   const struct mtk_mux *muxes,
			   int num, struct device_node *node,
			   spinlock_t *lock,
			   struct clk_hw_onecell_data *clk_data);

void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
			      struct clk_hw_onecell_data *clk_data);

struct mtk_mux_nb {
	struct notifier_block	nb;
	const struct clk_ops	*ops;

	u8	bypass_index;	/* Which parent to temporarily use */
	u8	original_index;	/* Set by notifier callback */
};

#define to_mtk_mux_nb(_nb)	container_of(_nb, struct mtk_mux_nb, nb)

int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
				       struct mtk_mux_nb *mux_nb);

#endif /* __DRV_CLK_MTK_MUX_H */