162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Baikal-T1 CCU Dividers interface driver 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#ifndef __CLK_BT1_CCU_DIV_H__ 862306a36Sopenharmony_ci#define __CLK_BT1_CCU_DIV_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/clk-provider.h> 1162306a36Sopenharmony_ci#include <linux/spinlock.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci#include <linux/bits.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* 1762306a36Sopenharmony_ci * CCU Divider private clock IDs 1862306a36Sopenharmony_ci * @CCU_SYS_SATA_CLK: CCU SATA internal clock 1962306a36Sopenharmony_ci * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci#define CCU_SYS_SATA_CLK -1 2262306a36Sopenharmony_ci#define CCU_SYS_XGMAC_CLK -2 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * CCU Divider private flags 2662306a36Sopenharmony_ci * @CCU_DIV_BASIC: Basic divider clock required by the kernel as early as 2762306a36Sopenharmony_ci * possible. 2862306a36Sopenharmony_ci * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1. 2962306a36Sopenharmony_ci * It can be 0 though, which is functionally the same. 3062306a36Sopenharmony_ci * @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3]. 3162306a36Sopenharmony_ci * It can be either 0 or greater than 3. 3262306a36Sopenharmony_ci * @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position. 3362306a36Sopenharmony_ci * @CCU_DIV_RESET_DOMAIN: There is a clock domain reset handle. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci#define CCU_DIV_BASIC BIT(0) 3662306a36Sopenharmony_ci#define CCU_DIV_SKIP_ONE BIT(1) 3762306a36Sopenharmony_ci#define CCU_DIV_SKIP_ONE_TO_THREE BIT(2) 3862306a36Sopenharmony_ci#define CCU_DIV_LOCK_SHIFTED BIT(3) 3962306a36Sopenharmony_ci#define CCU_DIV_RESET_DOMAIN BIT(4) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * enum ccu_div_type - CCU Divider types 4362306a36Sopenharmony_ci * @CCU_DIV_VAR: Clocks gate with variable divider. 4462306a36Sopenharmony_ci * @CCU_DIV_GATE: Clocks gate with fixed divider. 4562306a36Sopenharmony_ci * @CCU_DIV_BUF: Clock gate with no divider. 4662306a36Sopenharmony_ci * @CCU_DIV_FIXED: Ungateable clock with fixed divider. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_cienum ccu_div_type { 4962306a36Sopenharmony_ci CCU_DIV_VAR, 5062306a36Sopenharmony_ci CCU_DIV_GATE, 5162306a36Sopenharmony_ci CCU_DIV_BUF, 5262306a36Sopenharmony_ci CCU_DIV_FIXED 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * struct ccu_div_init_data - CCU Divider initialization data 5762306a36Sopenharmony_ci * @id: Clocks private identifier. 5862306a36Sopenharmony_ci * @name: Clocks name. 5962306a36Sopenharmony_ci * @parent_name: Parent clocks name in a fw node. 6062306a36Sopenharmony_ci * @base: Divider register base address with respect to the sys_regs base. 6162306a36Sopenharmony_ci * @sys_regs: Baikal-T1 System Controller registers map. 6262306a36Sopenharmony_ci * @np: Pointer to the node describing the CCU Dividers. 6362306a36Sopenharmony_ci * @type: CCU divider type (variable, fixed with and without gate). 6462306a36Sopenharmony_ci * @width: Divider width if it's variable. 6562306a36Sopenharmony_ci * @divider: Divider fixed value. 6662306a36Sopenharmony_ci * @flags: CCU Divider clock flags. 6762306a36Sopenharmony_ci * @features: CCU Divider private features. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistruct ccu_div_init_data { 7062306a36Sopenharmony_ci unsigned int id; 7162306a36Sopenharmony_ci const char *name; 7262306a36Sopenharmony_ci const char *parent_name; 7362306a36Sopenharmony_ci unsigned int base; 7462306a36Sopenharmony_ci struct regmap *sys_regs; 7562306a36Sopenharmony_ci struct device_node *np; 7662306a36Sopenharmony_ci enum ccu_div_type type; 7762306a36Sopenharmony_ci union { 7862306a36Sopenharmony_ci unsigned int width; 7962306a36Sopenharmony_ci unsigned int divider; 8062306a36Sopenharmony_ci }; 8162306a36Sopenharmony_ci unsigned long flags; 8262306a36Sopenharmony_ci unsigned long features; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* 8662306a36Sopenharmony_ci * struct ccu_div - CCU Divider descriptor 8762306a36Sopenharmony_ci * @hw: clk_hw of the divider. 8862306a36Sopenharmony_ci * @id: Clock private identifier. 8962306a36Sopenharmony_ci * @reg_ctl: Divider control register base address. 9062306a36Sopenharmony_ci * @sys_regs: Baikal-T1 System Controller registers map. 9162306a36Sopenharmony_ci * @lock: Divider state change spin-lock. 9262306a36Sopenharmony_ci * @mask: Divider field mask. 9362306a36Sopenharmony_ci * @divider: Divider fixed value. 9462306a36Sopenharmony_ci * @flags: Divider clock flags. 9562306a36Sopenharmony_ci * @features: CCU Divider private features. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_cistruct ccu_div { 9862306a36Sopenharmony_ci struct clk_hw hw; 9962306a36Sopenharmony_ci unsigned int id; 10062306a36Sopenharmony_ci unsigned int reg_ctl; 10162306a36Sopenharmony_ci struct regmap *sys_regs; 10262306a36Sopenharmony_ci spinlock_t lock; 10362306a36Sopenharmony_ci union { 10462306a36Sopenharmony_ci u32 mask; 10562306a36Sopenharmony_ci unsigned int divider; 10662306a36Sopenharmony_ci }; 10762306a36Sopenharmony_ci unsigned long flags; 10862306a36Sopenharmony_ci unsigned long features; 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci#define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci return div ? &div->hw : NULL; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistruct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_civoid ccu_div_hw_unregister(struct ccu_div *div); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#endif /* __CLK_BT1_CCU_DIV_H__ */ 122