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