1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Baikal-T1 CCU Dividers interface driver 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun #ifndef __CLK_BT1_CCU_DIV_H__ 8*4882a593Smuzhiyun #define __CLK_BT1_CCU_DIV_H__ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #include <linux/clk-provider.h> 11*4882a593Smuzhiyun #include <linux/spinlock.h> 12*4882a593Smuzhiyun #include <linux/regmap.h> 13*4882a593Smuzhiyun #include <linux/bits.h> 14*4882a593Smuzhiyun #include <linux/of.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun /* 17*4882a593Smuzhiyun * CCU Divider private clock IDs 18*4882a593Smuzhiyun * @CCU_SYS_SATA_CLK: CCU SATA internal clock 19*4882a593Smuzhiyun * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock 20*4882a593Smuzhiyun */ 21*4882a593Smuzhiyun #define CCU_SYS_SATA_CLK -1 22*4882a593Smuzhiyun #define CCU_SYS_XGMAC_CLK -2 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun /* 25*4882a593Smuzhiyun * CCU Divider private flags 26*4882a593Smuzhiyun * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1. 27*4882a593Smuzhiyun * It can be 0 though, which is functionally the same. 28*4882a593Smuzhiyun * @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3]. 29*4882a593Smuzhiyun * It can be either 0 or greater than 3. 30*4882a593Smuzhiyun * @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position. 31*4882a593Smuzhiyun * @CCU_DIV_RESET_DOMAIN: Provide reset clock domain method. 32*4882a593Smuzhiyun */ 33*4882a593Smuzhiyun #define CCU_DIV_SKIP_ONE BIT(1) 34*4882a593Smuzhiyun #define CCU_DIV_SKIP_ONE_TO_THREE BIT(2) 35*4882a593Smuzhiyun #define CCU_DIV_LOCK_SHIFTED BIT(3) 36*4882a593Smuzhiyun #define CCU_DIV_RESET_DOMAIN BIT(4) 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun /* 39*4882a593Smuzhiyun * enum ccu_div_type - CCU Divider types 40*4882a593Smuzhiyun * @CCU_DIV_VAR: Clocks gate with variable divider. 41*4882a593Smuzhiyun * @CCU_DIV_GATE: Clocks gate with fixed divider. 42*4882a593Smuzhiyun * @CCU_DIV_BUF: Clock gate with no divider. 43*4882a593Smuzhiyun * @CCU_DIV_FIXED: Ungateable clock with fixed divider. 44*4882a593Smuzhiyun */ 45*4882a593Smuzhiyun enum ccu_div_type { 46*4882a593Smuzhiyun CCU_DIV_VAR, 47*4882a593Smuzhiyun CCU_DIV_GATE, 48*4882a593Smuzhiyun CCU_DIV_BUF, 49*4882a593Smuzhiyun CCU_DIV_FIXED 50*4882a593Smuzhiyun }; 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* 53*4882a593Smuzhiyun * struct ccu_div_init_data - CCU Divider initialization data 54*4882a593Smuzhiyun * @id: Clocks private identifier. 55*4882a593Smuzhiyun * @name: Clocks name. 56*4882a593Smuzhiyun * @parent_name: Parent clocks name in a fw node. 57*4882a593Smuzhiyun * @base: Divider register base address with respect to the sys_regs base. 58*4882a593Smuzhiyun * @sys_regs: Baikal-T1 System Controller registers map. 59*4882a593Smuzhiyun * @np: Pointer to the node describing the CCU Dividers. 60*4882a593Smuzhiyun * @type: CCU divider type (variable, fixed with and without gate). 61*4882a593Smuzhiyun * @width: Divider width if it's variable. 62*4882a593Smuzhiyun * @divider: Divider fixed value. 63*4882a593Smuzhiyun * @flags: CCU Divider clock flags. 64*4882a593Smuzhiyun * @features: CCU Divider private features. 65*4882a593Smuzhiyun */ 66*4882a593Smuzhiyun struct ccu_div_init_data { 67*4882a593Smuzhiyun unsigned int id; 68*4882a593Smuzhiyun const char *name; 69*4882a593Smuzhiyun const char *parent_name; 70*4882a593Smuzhiyun unsigned int base; 71*4882a593Smuzhiyun struct regmap *sys_regs; 72*4882a593Smuzhiyun struct device_node *np; 73*4882a593Smuzhiyun enum ccu_div_type type; 74*4882a593Smuzhiyun union { 75*4882a593Smuzhiyun unsigned int width; 76*4882a593Smuzhiyun unsigned int divider; 77*4882a593Smuzhiyun }; 78*4882a593Smuzhiyun unsigned long flags; 79*4882a593Smuzhiyun unsigned long features; 80*4882a593Smuzhiyun }; 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun /* 83*4882a593Smuzhiyun * struct ccu_div - CCU Divider descriptor 84*4882a593Smuzhiyun * @hw: clk_hw of the divider. 85*4882a593Smuzhiyun * @id: Clock private identifier. 86*4882a593Smuzhiyun * @reg_ctl: Divider control register base address. 87*4882a593Smuzhiyun * @sys_regs: Baikal-T1 System Controller registers map. 88*4882a593Smuzhiyun * @lock: Divider state change spin-lock. 89*4882a593Smuzhiyun * @mask: Divider field mask. 90*4882a593Smuzhiyun * @divider: Divider fixed value. 91*4882a593Smuzhiyun * @flags: Divider clock flags. 92*4882a593Smuzhiyun * @features: CCU Divider private features. 93*4882a593Smuzhiyun */ 94*4882a593Smuzhiyun struct ccu_div { 95*4882a593Smuzhiyun struct clk_hw hw; 96*4882a593Smuzhiyun unsigned int id; 97*4882a593Smuzhiyun unsigned int reg_ctl; 98*4882a593Smuzhiyun struct regmap *sys_regs; 99*4882a593Smuzhiyun spinlock_t lock; 100*4882a593Smuzhiyun union { 101*4882a593Smuzhiyun u32 mask; 102*4882a593Smuzhiyun unsigned int divider; 103*4882a593Smuzhiyun }; 104*4882a593Smuzhiyun unsigned long flags; 105*4882a593Smuzhiyun unsigned long features; 106*4882a593Smuzhiyun }; 107*4882a593Smuzhiyun #define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw) 108*4882a593Smuzhiyun ccu_div_get_clk_hw(struct ccu_div * div)109*4882a593Smuzhiyunstatic inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div) 110*4882a593Smuzhiyun { 111*4882a593Smuzhiyun return div ? &div->hw : NULL; 112*4882a593Smuzhiyun } 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init); 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun void ccu_div_hw_unregister(struct ccu_div *div); 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun int ccu_div_reset_domain(struct ccu_div *div); 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun #endif /* __CLK_BT1_CCU_DIV_H__ */ 121