/* SPDX-License-Identifier: GPL-2.0-only */1/*2* Copyright (C) 2020 BAIKAL ELECTRONICS, JSC3*4* Baikal-T1 CCU Dividers interface driver5*/6#ifndef __CLK_BT1_CCU_DIV_H__7#define __CLK_BT1_CCU_DIV_H__89#include <linux/clk-provider.h>10#include <linux/spinlock.h>11#include <linux/regmap.h>12#include <linux/bits.h>13#include <linux/of.h>1415/*16* CCU Divider private clock IDs17* @CCU_SYS_SATA_CLK: CCU SATA internal clock18* @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock19*/20#define CCU_SYS_SATA_CLK -121#define CCU_SYS_XGMAC_CLK -22223/*24* CCU Divider private flags25* @CCU_DIV_BASIC: Basic divider clock required by the kernel as early as26* possible.27* @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1.28* It can be 0 though, which is functionally the same.29* @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3].30* It can be either 0 or greater than 3.31* @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position.32* @CCU_DIV_RESET_DOMAIN: There is a clock domain reset handle.33*/34#define CCU_DIV_BASIC BIT(0)35#define CCU_DIV_SKIP_ONE BIT(1)36#define CCU_DIV_SKIP_ONE_TO_THREE BIT(2)37#define CCU_DIV_LOCK_SHIFTED BIT(3)38#define CCU_DIV_RESET_DOMAIN BIT(4)3940/*41* enum ccu_div_type - CCU Divider types42* @CCU_DIV_VAR: Clocks gate with variable divider.43* @CCU_DIV_GATE: Clocks gate with fixed divider.44* @CCU_DIV_BUF: Clock gate with no divider.45* @CCU_DIV_FIXED: Ungateable clock with fixed divider.46*/47enum ccu_div_type {48CCU_DIV_VAR,49CCU_DIV_GATE,50CCU_DIV_BUF,51CCU_DIV_FIXED52};5354/*55* struct ccu_div_init_data - CCU Divider initialization data56* @id: Clocks private identifier.57* @name: Clocks name.58* @parent_name: Parent clocks name in a fw node.59* @base: Divider register base address with respect to the sys_regs base.60* @sys_regs: Baikal-T1 System Controller registers map.61* @np: Pointer to the node describing the CCU Dividers.62* @type: CCU divider type (variable, fixed with and without gate).63* @width: Divider width if it's variable.64* @divider: Divider fixed value.65* @flags: CCU Divider clock flags.66* @features: CCU Divider private features.67*/68struct ccu_div_init_data {69unsigned int id;70const char *name;71const char *parent_name;72unsigned int base;73struct regmap *sys_regs;74struct device_node *np;75enum ccu_div_type type;76union {77unsigned int width;78unsigned int divider;79};80unsigned long flags;81unsigned long features;82};8384/*85* struct ccu_div - CCU Divider descriptor86* @hw: clk_hw of the divider.87* @id: Clock private identifier.88* @reg_ctl: Divider control register base address.89* @sys_regs: Baikal-T1 System Controller registers map.90* @lock: Divider state change spin-lock.91* @mask: Divider field mask.92* @divider: Divider fixed value.93* @flags: Divider clock flags.94* @features: CCU Divider private features.95*/96struct ccu_div {97struct clk_hw hw;98unsigned int id;99unsigned int reg_ctl;100struct regmap *sys_regs;101spinlock_t lock;102union {103u32 mask;104unsigned int divider;105};106unsigned long flags;107unsigned long features;108};109#define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw)110111static inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)112{113return div ? &div->hw : NULL;114}115116struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);117118void ccu_div_hw_unregister(struct ccu_div *div);119120#endif /* __CLK_BT1_CCU_DIV_H__ */121122123