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