162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2018 MediaTek Inc.
462306a36Sopenharmony_ci * Author: Owen Chen <owen.chen@mediatek.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __DRV_CLK_MTK_MUX_H
862306a36Sopenharmony_ci#define __DRV_CLK_MTK_MUX_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/notifier.h>
1162306a36Sopenharmony_ci#include <linux/spinlock.h>
1262306a36Sopenharmony_ci#include <linux/types.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct clk;
1562306a36Sopenharmony_cistruct clk_hw_onecell_data;
1662306a36Sopenharmony_cistruct clk_ops;
1762306a36Sopenharmony_cistruct device;
1862306a36Sopenharmony_cistruct device_node;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct mtk_mux {
2162306a36Sopenharmony_ci	int id;
2262306a36Sopenharmony_ci	const char *name;
2362306a36Sopenharmony_ci	const char * const *parent_names;
2462306a36Sopenharmony_ci	unsigned int flags;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	u32 mux_ofs;
2762306a36Sopenharmony_ci	u32 set_ofs;
2862306a36Sopenharmony_ci	u32 clr_ofs;
2962306a36Sopenharmony_ci	u32 upd_ofs;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	u8 mux_shift;
3262306a36Sopenharmony_ci	u8 mux_width;
3362306a36Sopenharmony_ci	u8 gate_shift;
3462306a36Sopenharmony_ci	s8 upd_shift;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	const struct clk_ops *ops;
3762306a36Sopenharmony_ci	signed char num_parents;
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,		\
4162306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
4262306a36Sopenharmony_ci			_gate, _upd_ofs, _upd, _flags, _ops) {		\
4362306a36Sopenharmony_ci		.id = _id,						\
4462306a36Sopenharmony_ci		.name = _name,						\
4562306a36Sopenharmony_ci		.mux_ofs = _mux_ofs,					\
4662306a36Sopenharmony_ci		.set_ofs = _mux_set_ofs,				\
4762306a36Sopenharmony_ci		.clr_ofs = _mux_clr_ofs,				\
4862306a36Sopenharmony_ci		.upd_ofs = _upd_ofs,					\
4962306a36Sopenharmony_ci		.mux_shift = _shift,					\
5062306a36Sopenharmony_ci		.mux_width = _width,					\
5162306a36Sopenharmony_ci		.gate_shift = _gate,					\
5262306a36Sopenharmony_ci		.upd_shift = _upd,					\
5362306a36Sopenharmony_ci		.parent_names = _parents,				\
5462306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(_parents),			\
5562306a36Sopenharmony_ci		.flags = _flags,					\
5662306a36Sopenharmony_ci		.ops = &_ops,						\
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciextern const struct clk_ops mtk_mux_clr_set_upd_ops;
6062306a36Sopenharmony_ciextern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
6362306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
6462306a36Sopenharmony_ci			_gate, _upd_ofs, _upd, _flags)			\
6562306a36Sopenharmony_ci		GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
6662306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
6762306a36Sopenharmony_ci			_gate, _upd_ofs, _upd, _flags,			\
6862306a36Sopenharmony_ci			mtk_mux_gate_clr_set_upd_ops)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs,		\
7162306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
7262306a36Sopenharmony_ci			_gate, _upd_ofs, _upd)				\
7362306a36Sopenharmony_ci		MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents,	\
7462306a36Sopenharmony_ci			_mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift,	\
7562306a36Sopenharmony_ci			_width, _gate, _upd_ofs, _upd,			\
7662306a36Sopenharmony_ci			CLK_SET_RATE_PARENT)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs,			\
7962306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
8062306a36Sopenharmony_ci			_upd_ofs, _upd)					\
8162306a36Sopenharmony_ci		GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,	\
8262306a36Sopenharmony_ci			_mux_set_ofs, _mux_clr_ofs, _shift, _width,	\
8362306a36Sopenharmony_ci			0, _upd_ofs, _upd, CLK_SET_RATE_PARENT,		\
8462306a36Sopenharmony_ci			mtk_mux_clr_set_upd_ops)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciint mtk_clk_register_muxes(struct device *dev,
8762306a36Sopenharmony_ci			   const struct mtk_mux *muxes,
8862306a36Sopenharmony_ci			   int num, struct device_node *node,
8962306a36Sopenharmony_ci			   spinlock_t *lock,
9062306a36Sopenharmony_ci			   struct clk_hw_onecell_data *clk_data);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_civoid mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
9362306a36Sopenharmony_ci			      struct clk_hw_onecell_data *clk_data);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistruct mtk_mux_nb {
9662306a36Sopenharmony_ci	struct notifier_block	nb;
9762306a36Sopenharmony_ci	const struct clk_ops	*ops;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	u8	bypass_index;	/* Which parent to temporarily use */
10062306a36Sopenharmony_ci	u8	original_index;	/* Set by notifier callback */
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define to_mtk_mux_nb(_nb)	container_of(_nb, struct mtk_mux_nb, nb)
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ciint devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
10662306a36Sopenharmony_ci				       struct mtk_mux_nb *mux_nb);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#endif /* __DRV_CLK_MTK_MUX_H */
109