1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright (c) 2018 MediaTek Inc. |
4 | * Author: Owen Chen <owen.chen@mediatek.com> |
5 | */ |
6 | |
7 | #ifndef __DRV_CLK_MTK_MUX_H |
8 | #define __DRV_CLK_MTK_MUX_H |
9 | |
10 | #include <linux/notifier.h> |
11 | #include <linux/spinlock.h> |
12 | #include <linux/types.h> |
13 | |
14 | struct clk; |
15 | struct clk_hw_onecell_data; |
16 | struct clk_ops; |
17 | struct device; |
18 | struct device_node; |
19 | |
20 | struct mtk_mux { |
21 | int id; |
22 | const char *name; |
23 | const char * const *parent_names; |
24 | unsigned int flags; |
25 | |
26 | u32 mux_ofs; |
27 | u32 set_ofs; |
28 | u32 clr_ofs; |
29 | u32 upd_ofs; |
30 | |
31 | u8 mux_shift; |
32 | u8 mux_width; |
33 | u8 gate_shift; |
34 | s8 upd_shift; |
35 | |
36 | const struct clk_ops *ops; |
37 | signed char num_parents; |
38 | }; |
39 | |
40 | #define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ |
41 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
42 | _gate, _upd_ofs, _upd, _flags, _ops) { \ |
43 | .id = _id, \ |
44 | .name = _name, \ |
45 | .mux_ofs = _mux_ofs, \ |
46 | .set_ofs = _mux_set_ofs, \ |
47 | .clr_ofs = _mux_clr_ofs, \ |
48 | .upd_ofs = _upd_ofs, \ |
49 | .mux_shift = _shift, \ |
50 | .mux_width = _width, \ |
51 | .gate_shift = _gate, \ |
52 | .upd_shift = _upd, \ |
53 | .parent_names = _parents, \ |
54 | .num_parents = ARRAY_SIZE(_parents), \ |
55 | .flags = _flags, \ |
56 | .ops = &_ops, \ |
57 | } |
58 | |
59 | extern const struct clk_ops mtk_mux_clr_set_upd_ops; |
60 | extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; |
61 | |
62 | #define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ |
63 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
64 | _gate, _upd_ofs, _upd, _flags) \ |
65 | GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ |
66 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
67 | _gate, _upd_ofs, _upd, _flags, \ |
68 | mtk_mux_gate_clr_set_upd_ops) |
69 | |
70 | #define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ |
71 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
72 | _gate, _upd_ofs, _upd) \ |
73 | MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \ |
74 | _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \ |
75 | _width, _gate, _upd_ofs, _upd, \ |
76 | CLK_SET_RATE_PARENT) |
77 | |
78 | #define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ |
79 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
80 | _upd_ofs, _upd) \ |
81 | GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ |
82 | _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ |
83 | 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \ |
84 | mtk_mux_clr_set_upd_ops) |
85 | |
86 | int mtk_clk_register_muxes(struct device *dev, |
87 | const struct mtk_mux *muxes, |
88 | int num, struct device_node *node, |
89 | spinlock_t *lock, |
90 | struct clk_hw_onecell_data *clk_data); |
91 | |
92 | void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, |
93 | struct clk_hw_onecell_data *clk_data); |
94 | |
95 | struct mtk_mux_nb { |
96 | struct notifier_block nb; |
97 | const struct clk_ops *ops; |
98 | |
99 | u8 bypass_index; /* Which parent to temporarily use */ |
100 | u8 original_index; /* Set by notifier callback */ |
101 | }; |
102 | |
103 | #define to_mtk_mux_nb(_nb) container_of(_nb, struct mtk_mux_nb, nb) |
104 | |
105 | int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk, |
106 | struct mtk_mux_nb *mux_nb); |
107 | |
108 | #endif /* __DRV_CLK_MTK_MUX_H */ |
109 | |