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