/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd.. * All rights reserved. * * Authors: * Yifeng Huang * Xuyang Dong */ #ifndef __ESWIN_COMMON_H__ #define __ESWIN_COMMON_H__ #define APLL_HIGH_FREQ 983040000 #define APLL_LOW_FREQ 225792000 #define PLL_HIGH_FREQ 1800000000 #define PLL_LOW_FREQ 24000000 /* * ESWIN_PRIV_DIV_MIN_2: If ESWIN_PRIV_DIV_MIN_2 is set, the minimum value of * the register is 2, i.e. the minimum division ratio is 2. */ #define ESWIN_PRIV_DIV_MIN_2 BIT(0) enum eswin_clk_type { CLK_FIXED_FACTOR, CLK_MUX, CLK_DIVIDER, CLK_GATE, }; struct eswin_clock_data { void __iomem *base; struct clk_hw *original_clk; struct notifier_block pll_nb; spinlock_t lock; /* protect register read-modify-write cycle */ struct clk_hw_onecell_data clk_data; }; struct eswin_divider_clock { struct clk_hw hw; unsigned int id; const char *name; const struct clk_parent_data *parent_data; void __iomem *ctrl_reg; /* register address of the divider clock */ unsigned long flags; unsigned long reg; /* register offset */ u8 shift; u8 width; unsigned long div_flags; unsigned long priv_flag; spinlock_t *lock; /* protect register read-modify-write cycle */ }; struct eswin_fixed_rate_clock { struct clk_hw hw; unsigned int id; const char *name; unsigned long flags; unsigned long rate; }; struct eswin_fixed_factor_clock { struct clk_hw hw; unsigned int id; const char *name; const struct clk_parent_data *parent_data; unsigned long mult; unsigned long div; unsigned long flags; }; struct eswin_gate_clock { struct clk_hw hw; unsigned int id; const char *name; const struct clk_parent_data *parent_data; unsigned long flags; unsigned long reg; u8 bit_idx; u8 gate_flags; }; struct eswin_mux_clock { struct clk_hw hw; unsigned int id; const char *name; const struct clk_parent_data *parent_data; u8 num_parents; unsigned long flags; unsigned long reg; u8 shift; u8 width; u8 mux_flags; u32 *table; }; struct eswin_pll_clock { struct clk_hw hw; u32 id; const char *name; const struct clk_parent_data *parent_data; const u32 ctrl_reg0; const u8 fbdiv_shift; const u32 ctrl_reg1; const u8 frac_shift; const u32 ctrl_reg2; const u32 status_reg; const u8 lock_shift; const u8 lock_width; const u64 max_rate; const u64 min_rate; }; struct eswin_clk_pll { struct clk_hw hw; u32 id; void __iomem *ctrl_reg0; u8 fbdiv_shift; void __iomem *ctrl_reg1; u8 frac_shift; void __iomem *ctrl_reg2; void __iomem *status_reg; u8 lock_shift; u8 lock_width; u64 max_rate; u64 min_rate; }; struct eswin_clk_info { unsigned int type; unsigned int pid; unsigned int id; struct clk_hw hw; union { struct eswin_divider_clock div; struct eswin_fixed_factor_clock factor; struct eswin_gate_clock gate; struct eswin_mux_clock mux; } data; }; struct eswin_clock_data *eswin_clk_init(struct platform_device *pdev, size_t nr_clks); int eswin_clk_register_fixed_rate(struct device *dev, struct eswin_fixed_rate_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_pll(struct device *dev, struct eswin_pll_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_fixed_factor(struct device *dev, struct eswin_fixed_factor_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_mux(struct device *dev, struct eswin_mux_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_divider(struct device *dev, struct eswin_divider_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_gate(struct device *dev, struct eswin_gate_clock *clks, int nums, struct eswin_clock_data *data); int eswin_clk_register_clks(struct device *dev, struct eswin_clk_info *clks, int nums, struct eswin_clock_data *data); struct clk_hw *eswin_register_clkdiv(struct device *dev, unsigned int id, const char *name, const struct clk_hw *parent_hw, unsigned long flags, void __iomem *reg, u8 shift, u8 width, unsigned long clk_divider_flags, unsigned long priv_flag, spinlock_t *lock); #define ESWIN_DIV(_id, _name, _pdata, _flags, _reg, _shift, _width, \ _dflags, _pflag) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .flags = _flags, \ .reg = _reg, \ .shift = _shift, \ .width = _width, \ .div_flags = _dflags, \ .priv_flag = _pflag, \ } #define ESWIN_DIV_TYPE(_id, _name, _pid, _flags, _reg, _shift, _width, \ _dflags, _pflag) \ { \ .type = CLK_DIVIDER, \ .pid = _pid, \ .id = _id, \ .data = { \ .div = { \ .name = _name, \ .flags = _flags, \ .reg = _reg, \ .shift = _shift, \ .width = _width, \ .div_flags = _dflags, \ .priv_flag = _pflag, \ }, \ }, \ } #define ESWIN_FACTOR(_id, _name, _pdata, _mult, _div, _flags) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .mult = _mult, \ .div = _div, \ .flags = _flags, \ } #define ESWIN_FACTOR_TYPE(_id, _name, _pid, _mult, _div, _flags) \ { \ .type = CLK_FIXED_FACTOR, \ .pid = _pid, \ .id = _id, \ .data = { \ .factor = { \ .name = _name, \ .mult = _mult, \ .div = _div, \ .flags = _flags, \ }, \ }, \ } #define ESWIN_FIXED(_id, _name, _flags, _rate) \ { \ .id = _id, \ .name = _name, \ .flags = _flags, \ .rate = _rate, \ } #define ESWIN_GATE(_id, _name, _pdata, _flags, _reg, _idx, _gflags) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .flags = _flags, \ .reg = _reg, \ .bit_idx = _idx, \ .gate_flags = _gflags, \ } #define ESWIN_GATE_TYPE(_id, _name, _pid, _flags, _reg, _idx, _gflags) \ { \ .type = CLK_GATE, \ .pid = _pid, \ .id = _id, \ .data = { \ .gate = { \ .name = _name, \ .flags = _flags, \ .reg = _reg, \ .bit_idx = _idx, \ .gate_flags = _gflags, \ }, \ }, \ } #define ESWIN_MUX(_id, _name, _pdata, _num_parents, _flags, _reg, \ _shift, _width, _mflags) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .num_parents = _num_parents, \ .flags = _flags, \ .reg = _reg, \ .shift = _shift, \ .width = _width, \ .mux_flags = _mflags, \ .table = NULL, \ } #define ESWIN_MUX_TBL(_id, _name, _pdata, _num_parents, _flags, _reg, \ _shift, _width, _mflags, _table) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .num_parents = _num_parents, \ .flags = _flags, \ .reg = _reg, \ .shift = _shift, \ .width = _width, \ .mux_flags = _mflags, \ .table = _table, \ } #define ESWIN_MUX_TYPE(_id, _name, _pdata, _num_parents, _flags, _reg, \ _shift, _width, _mflags, _table) \ { \ .type = CLK_MUX, \ .id = _id, \ .data = { \ .mux = { \ .name = _name, \ .parent_data = _pdata, \ .num_parents = _num_parents, \ .flags = _flags, \ .reg = _reg, \ .shift = _shift, \ .width = _width, \ .mux_flags = _mflags, \ .table = _table, \ }, \ }, \ } #define ESWIN_PLL(_id, _name, _pdata, _reg0, _fb_shift, _reg1, \ _frac_shift, _reg2, _reg, _lock_shift, _lock_width, \ _max_rate, _min_rate) \ { \ .id = _id, \ .name = _name, \ .parent_data = _pdata, \ .ctrl_reg0 = _reg0, \ .fbdiv_shift = _fb_shift, \ .ctrl_reg1 = _reg1, \ .frac_shift = _frac_shift, \ .ctrl_reg2 = _reg2, \ .status_reg = _reg, \ .lock_shift = _lock_shift, \ .lock_width = _lock_width, \ .max_rate = _max_rate, \ .min_rate = _min_rate, \ } #endif /* __ESWIN_COMMON_H__ */