2025-04-16 13:54:03 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2024 SpacemiT Technology Co. Ltd
|
|
|
|
* Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _CCU_MIX_H_
|
|
|
|
#define _CCU_MIX_H_
|
|
|
|
|
|
|
|
#include <linux/clk-provider.h>
|
|
|
|
|
|
|
|
#include "ccu_common.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ccu_gate_config - Gate configuration
|
|
|
|
*
|
|
|
|
* @mask: Mask to enable the gate. Some clocks may have more than one bit
|
|
|
|
* set in this field.
|
|
|
|
*/
|
|
|
|
struct ccu_gate_config {
|
|
|
|
u32 mask;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ccu_factor_config {
|
|
|
|
u32 div;
|
|
|
|
u32 mul;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ccu_mux_config {
|
|
|
|
u8 shift;
|
|
|
|
u8 width;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ccu_div_config {
|
|
|
|
u8 shift;
|
|
|
|
u8 width;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ccu_mix {
|
|
|
|
struct ccu_factor_config factor;
|
|
|
|
struct ccu_gate_config gate;
|
|
|
|
struct ccu_div_config div;
|
|
|
|
struct ccu_mux_config mux;
|
|
|
|
struct ccu_common common;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define CCU_GATE_INIT(_mask) { .mask = _mask }
|
|
|
|
#define CCU_FACTOR_INIT(_div, _mul) { .div = _div, .mul = _mul }
|
|
|
|
#define CCU_MUX_INIT(_shift, _width) { .shift = _shift, .width = _width }
|
|
|
|
#define CCU_DIV_INIT(_shift, _width) { .shift = _shift, .width = _width }
|
|
|
|
|
|
|
|
#define CCU_PARENT_HW(_parent) { .hw = &_parent.common.hw }
|
|
|
|
#define CCU_PARENT_NAME(_name) { .fw_name = #_name }
|
|
|
|
|
|
|
|
#define CCU_MIX_INITHW(_name, _parent, _ops, _flags) \
|
|
|
|
.hw.init = &(struct clk_init_data) { \
|
|
|
|
.flags = _flags, \
|
|
|
|
.name = #_name, \
|
|
|
|
.parent_data = (const struct clk_parent_data[]) \
|
|
|
|
{ _parent }, \
|
|
|
|
.num_parents = 1, \
|
|
|
|
.ops = &_ops, \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MIX_INITHW_PARENTS(_name, _parents, _ops, _flags) \
|
|
|
|
.hw.init = CLK_HW_INIT_PARENTS_DATA(#_name, _parents, &_ops, _flags)
|
|
|
|
|
|
|
|
#define CCU_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags), \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_FACTOR_DEFINE(_name, _parent, _div, _mul) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.factor = CCU_FACTOR_INIT(_div, _mul), \
|
|
|
|
.common = { \
|
|
|
|
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_ops, 0), \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MUX_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.mux = CCU_MUX_INIT(_shift, _width), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
|
|
|
|
_flags), \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_DIV_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.div = CCU_DIV_INIT(_shift, _width), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_ops, _flags) \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2025-06-12 17:48:55 -05:00
|
|
|
#define CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \
|
|
|
|
_mul, _flags) \
|
2025-04-16 13:54:03 +00:00
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.factor = CCU_FACTOR_INIT(_div, _mul), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
2025-06-12 17:48:55 -05:00
|
|
|
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, _flags) \
|
2025-04-16 13:54:03 +00:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2025-06-12 17:48:55 -05:00
|
|
|
#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \
|
|
|
|
_mul) \
|
|
|
|
CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \
|
|
|
|
_mul, 0)
|
|
|
|
|
2025-04-16 13:54:03 +00:00
|
|
|
#define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, \
|
|
|
|
_mask_gate, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.mux = CCU_MUX_INIT(_shift, _width), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
|
|
|
spacemit_ccu_mux_gate_ops, _flags), \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_DIV_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, \
|
|
|
|
_mask_gate, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.div = CCU_DIV_INIT(_shift, _width), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops, \
|
|
|
|
_flags), \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
|
|
|
|
_muxshift, _muxwidth, _mask_gate, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
|
|
|
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
|
|
|
spacemit_ccu_mux_div_gate_ops, _flags), \
|
|
|
|
}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_fc, \
|
|
|
|
_mshift, _mwidth, _mask_fc, _muxshift, \
|
|
|
|
_muxwidth, _mask_gate, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.gate = CCU_GATE_INIT(_mask_gate), \
|
|
|
|
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
|
|
|
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
.reg_fc = _reg_fc, \
|
|
|
|
.mask_fc = _mask_fc, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
|
|
|
spacemit_ccu_mux_div_gate_ops, _flags), \
|
|
|
|
}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MUX_DIV_GATE_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,\
|
|
|
|
_mask_fc, _muxshift, _muxwidth, _mask_gate, \
|
|
|
|
_flags) \
|
|
|
|
CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_ctrl, _mshift,\
|
|
|
|
_mwidth, _mask_fc, _muxshift, _muxwidth, \
|
|
|
|
_mask_gate, _flags)
|
|
|
|
|
|
|
|
#define CCU_MUX_DIV_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth, \
|
|
|
|
_mask_fc, _muxshift, _muxwidth, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.div = CCU_DIV_INIT(_mshift, _mwidth), \
|
|
|
|
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
.reg_fc = _reg_ctrl, \
|
|
|
|
.mask_fc = _mask_fc, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, \
|
|
|
|
spacemit_ccu_mux_div_ops, _flags), \
|
|
|
|
}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CCU_MUX_FC_DEFINE(_name, _parents, _reg_ctrl, _mask_fc, _muxshift, \
|
|
|
|
_muxwidth, _flags) \
|
|
|
|
static struct ccu_mix _name = { \
|
|
|
|
.mux = CCU_MUX_INIT(_muxshift, _muxwidth), \
|
|
|
|
.common = { \
|
|
|
|
.reg_ctrl = _reg_ctrl, \
|
|
|
|
.reg_fc = _reg_ctrl, \
|
|
|
|
.mask_fc = _mask_fc, \
|
|
|
|
CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops, \
|
|
|
|
_flags) \
|
|
|
|
}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
|
|
|
|
{
|
|
|
|
struct ccu_common *common = hw_to_ccu_common(hw);
|
|
|
|
|
|
|
|
return container_of(common, struct ccu_mix, common);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern const struct clk_ops spacemit_ccu_gate_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_factor_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_mux_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_div_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_factor_gate_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_div_gate_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_mux_gate_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_mux_div_ops;
|
|
|
|
extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
|
|
|
|
#endif /* _CCU_DIV_H_ */
|