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