18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Baikal-T1 CCU Dividers interface driver
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#ifndef __CLK_BT1_CCU_DIV_H__
88c2ecf20Sopenharmony_ci#define __CLK_BT1_CCU_DIV_H__
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
118c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
128c2ecf20Sopenharmony_ci#include <linux/regmap.h>
138c2ecf20Sopenharmony_ci#include <linux/bits.h>
148c2ecf20Sopenharmony_ci#include <linux/of.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/*
178c2ecf20Sopenharmony_ci * CCU Divider private clock IDs
188c2ecf20Sopenharmony_ci * @CCU_SYS_SATA_CLK: CCU SATA internal clock
198c2ecf20Sopenharmony_ci * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci#define CCU_SYS_SATA_CLK		-1
228c2ecf20Sopenharmony_ci#define CCU_SYS_XGMAC_CLK		-2
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * CCU Divider private flags
268c2ecf20Sopenharmony_ci * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1.
278c2ecf20Sopenharmony_ci *		      It can be 0 though, which is functionally the same.
288c2ecf20Sopenharmony_ci * @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3].
298c2ecf20Sopenharmony_ci *			       It can be either 0 or greater than 3.
308c2ecf20Sopenharmony_ci * @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position.
318c2ecf20Sopenharmony_ci * @CCU_DIV_RESET_DOMAIN: Provide reset clock domain method.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci#define CCU_DIV_SKIP_ONE		BIT(1)
348c2ecf20Sopenharmony_ci#define CCU_DIV_SKIP_ONE_TO_THREE	BIT(2)
358c2ecf20Sopenharmony_ci#define CCU_DIV_LOCK_SHIFTED		BIT(3)
368c2ecf20Sopenharmony_ci#define CCU_DIV_RESET_DOMAIN		BIT(4)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * enum ccu_div_type - CCU Divider types
408c2ecf20Sopenharmony_ci * @CCU_DIV_VAR: Clocks gate with variable divider.
418c2ecf20Sopenharmony_ci * @CCU_DIV_GATE: Clocks gate with fixed divider.
428c2ecf20Sopenharmony_ci * @CCU_DIV_BUF: Clock gate with no divider.
438c2ecf20Sopenharmony_ci * @CCU_DIV_FIXED: Ungateable clock with fixed divider.
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_cienum ccu_div_type {
468c2ecf20Sopenharmony_ci	CCU_DIV_VAR,
478c2ecf20Sopenharmony_ci	CCU_DIV_GATE,
488c2ecf20Sopenharmony_ci	CCU_DIV_BUF,
498c2ecf20Sopenharmony_ci	CCU_DIV_FIXED
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/*
538c2ecf20Sopenharmony_ci * struct ccu_div_init_data - CCU Divider initialization data
548c2ecf20Sopenharmony_ci * @id: Clocks private identifier.
558c2ecf20Sopenharmony_ci * @name: Clocks name.
568c2ecf20Sopenharmony_ci * @parent_name: Parent clocks name in a fw node.
578c2ecf20Sopenharmony_ci * @base: Divider register base address with respect to the sys_regs base.
588c2ecf20Sopenharmony_ci * @sys_regs: Baikal-T1 System Controller registers map.
598c2ecf20Sopenharmony_ci * @np: Pointer to the node describing the CCU Dividers.
608c2ecf20Sopenharmony_ci * @type: CCU divider type (variable, fixed with and without gate).
618c2ecf20Sopenharmony_ci * @width: Divider width if it's variable.
628c2ecf20Sopenharmony_ci * @divider: Divider fixed value.
638c2ecf20Sopenharmony_ci * @flags: CCU Divider clock flags.
648c2ecf20Sopenharmony_ci * @features: CCU Divider private features.
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_cistruct ccu_div_init_data {
678c2ecf20Sopenharmony_ci	unsigned int id;
688c2ecf20Sopenharmony_ci	const char *name;
698c2ecf20Sopenharmony_ci	const char *parent_name;
708c2ecf20Sopenharmony_ci	unsigned int base;
718c2ecf20Sopenharmony_ci	struct regmap *sys_regs;
728c2ecf20Sopenharmony_ci	struct device_node *np;
738c2ecf20Sopenharmony_ci	enum ccu_div_type type;
748c2ecf20Sopenharmony_ci	union {
758c2ecf20Sopenharmony_ci		unsigned int width;
768c2ecf20Sopenharmony_ci		unsigned int divider;
778c2ecf20Sopenharmony_ci	};
788c2ecf20Sopenharmony_ci	unsigned long flags;
798c2ecf20Sopenharmony_ci	unsigned long features;
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/*
838c2ecf20Sopenharmony_ci * struct ccu_div - CCU Divider descriptor
848c2ecf20Sopenharmony_ci * @hw: clk_hw of the divider.
858c2ecf20Sopenharmony_ci * @id: Clock private identifier.
868c2ecf20Sopenharmony_ci * @reg_ctl: Divider control register base address.
878c2ecf20Sopenharmony_ci * @sys_regs: Baikal-T1 System Controller registers map.
888c2ecf20Sopenharmony_ci * @lock: Divider state change spin-lock.
898c2ecf20Sopenharmony_ci * @mask: Divider field mask.
908c2ecf20Sopenharmony_ci * @divider: Divider fixed value.
918c2ecf20Sopenharmony_ci * @flags: Divider clock flags.
928c2ecf20Sopenharmony_ci * @features: CCU Divider private features.
938c2ecf20Sopenharmony_ci */
948c2ecf20Sopenharmony_cistruct ccu_div {
958c2ecf20Sopenharmony_ci	struct clk_hw hw;
968c2ecf20Sopenharmony_ci	unsigned int id;
978c2ecf20Sopenharmony_ci	unsigned int reg_ctl;
988c2ecf20Sopenharmony_ci	struct regmap *sys_regs;
998c2ecf20Sopenharmony_ci	spinlock_t lock;
1008c2ecf20Sopenharmony_ci	union {
1018c2ecf20Sopenharmony_ci		u32 mask;
1028c2ecf20Sopenharmony_ci		unsigned int divider;
1038c2ecf20Sopenharmony_ci	};
1048c2ecf20Sopenharmony_ci	unsigned long flags;
1058c2ecf20Sopenharmony_ci	unsigned long features;
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci#define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw)
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	return div ? &div->hw : NULL;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistruct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_civoid ccu_div_hw_unregister(struct ccu_div *div);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ciint ccu_div_reset_domain(struct ccu_div *div);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#endif /* __CLK_BT1_CCU_DIV_H__ */
121