blob: d8e5e65458941ce79215c97f226219274e30d743 [file]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
* All rights reserved.
*
* Authors:
* Yifeng Huang <huangyifeng@eswincomputing.com>
* Xuyang Dong <dongxuyang@eswincomputing.com>
*/
#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__ */