122 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC4 *5 * Baikal-T1 CCU Dividers interface driver6 */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 IDs18 * @CCU_SYS_SATA_CLK: CCU SATA internal clock19 * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock20 */21#define CCU_SYS_SATA_CLK -122#define CCU_SYS_XGMAC_CLK -223 24/*25 * CCU Divider private flags26 * @CCU_DIV_BASIC: Basic divider clock required by the kernel as early as27 * 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 types43 * @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 */48enum ccu_div_type {49 CCU_DIV_VAR,50 CCU_DIV_GATE,51 CCU_DIV_BUF,52 CCU_DIV_FIXED53};54 55/*56 * struct ccu_div_init_data - CCU Divider initialization data57 * @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 */69struct 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 descriptor87 * @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 */97struct 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 112static inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)113{114 return div ? &div->hw : NULL;115}116 117struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);118 119void ccu_div_hw_unregister(struct ccu_div *div);120 121#endif /* __CLK_BT1_CCU_DIV_H__ */122