mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 11:21:26 -04:00
Add clock drivers for the EIC7700 SoC. The clock controller on the ESWIN EIC7700 provides various clocks to different IP blocks within the SoC. Signed-off-by: Yifeng Huang <huangyifeng@eswincomputing.com> Tested-by: Marcel Ziswiler <marcel@ziswiler.com> # ebc77 Reviewed-by: Brian Masney <bmasney@redhat.com> Signed-off-by: Xuyang Dong <dongxuyang@eswincomputing.com> Tested-by: Bo Gan <ganboing@gmail.com> # hfp550 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
341 lines
8.0 KiB
C
341 lines
8.0 KiB
C
/* 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__ */
|