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