mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
Device composite clocks tend to reproduce the usual sel/div/gate arrangement. Add macros to help define simple composite clocks in the system. The idea is _not_ to replace all instances of mux, div or gate with those macros. It is rather to use it for recurring and/or simple composite clocks, reducing controller verbosity where it makes sense. This should help reviews focus on the tricky parts. Link: https://lore.kernel.org/r/20250825-meson-clk-cleanup-24-v2-10-0f402f01e117@baylibre.com Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
109 lines
3.0 KiB
C
109 lines
3.0 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* Copyright (c) 2023 Neil Armstrong <neil.armstrong@linaro.org>
|
|
*/
|
|
|
|
#ifndef __MESON_CLKC_UTILS_H__
|
|
#define __MESON_CLKC_UTILS_H__
|
|
|
|
#include <linux/of_device.h>
|
|
#include <linux/clk-provider.h>
|
|
|
|
struct platform_device;
|
|
|
|
struct meson_clk_hw_data {
|
|
struct clk_hw **hws;
|
|
unsigned int num;
|
|
};
|
|
|
|
struct clk_hw *meson_clk_hw_get(struct of_phandle_args *clkspec, void *clk_hw_data);
|
|
|
|
struct meson_clkc_data {
|
|
const struct reg_sequence *init_regs;
|
|
unsigned int init_count;
|
|
struct meson_clk_hw_data hw_clks;
|
|
};
|
|
|
|
int meson_clkc_syscon_probe(struct platform_device *pdev);
|
|
int meson_clkc_mmio_probe(struct platform_device *pdev);
|
|
|
|
#define __MESON_PCLK(_name, _reg, _bit, _ops, _pdata, _flags) \
|
|
struct clk_regmap _name = { \
|
|
.data = &(struct clk_regmap_gate_data) { \
|
|
.offset = (_reg), \
|
|
.bit_idx = (_bit), \
|
|
}, \
|
|
.hw.init = &(struct clk_init_data) { \
|
|
.name = #_name, \
|
|
.ops = _ops, \
|
|
.parent_data = (_pdata), \
|
|
.num_parents = 1, \
|
|
.flags = (_flags), \
|
|
}, \
|
|
}
|
|
|
|
#define MESON_PCLK(_name, _reg, _bit, _pdata, _flags) \
|
|
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pdata, _flags)
|
|
|
|
#define MESON_PCLK_RO(_name, _reg, _bit, _pdata, _flags) \
|
|
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pdata, _flags)
|
|
|
|
/* Helpers for the usual sel/div/gate composite clocks */
|
|
#define MESON_COMP_SEL(_prefix, _name, _reg, _shift, _mask, _pdata, \
|
|
_table, _dflags, _iflags) \
|
|
struct clk_regmap _prefix##_name##_sel = { \
|
|
.data = &(struct clk_regmap_mux_data) { \
|
|
.offset = (_reg), \
|
|
.mask = (_mask), \
|
|
.shift = (_shift), \
|
|
.flags = (_dflags), \
|
|
.table = (_table), \
|
|
}, \
|
|
.hw.init = &(struct clk_init_data){ \
|
|
.name = #_name "_sel", \
|
|
.ops = &clk_regmap_mux_ops, \
|
|
.parent_data = _pdata, \
|
|
.num_parents = ARRAY_SIZE(_pdata), \
|
|
.flags = (_iflags), \
|
|
}, \
|
|
}
|
|
|
|
#define MESON_COMP_DIV(_prefix, _name, _reg, _shift, _width, \
|
|
_dflags, _iflags) \
|
|
struct clk_regmap _prefix##_name##_div = { \
|
|
.data = &(struct clk_regmap_div_data) { \
|
|
.offset = (_reg), \
|
|
.shift = (_shift), \
|
|
.width = (_width), \
|
|
.flags = (_dflags), \
|
|
}, \
|
|
.hw.init = &(struct clk_init_data) { \
|
|
.name = #_name "_div", \
|
|
.ops = &clk_regmap_divider_ops, \
|
|
.parent_hws = (const struct clk_hw *[]) { \
|
|
&_prefix##_name##_sel.hw \
|
|
}, \
|
|
.num_parents = 1, \
|
|
.flags = (_iflags), \
|
|
}, \
|
|
}
|
|
|
|
#define MESON_COMP_GATE(_prefix, _name, _reg, _bit, _iflags) \
|
|
struct clk_regmap _prefix##_name = { \
|
|
.data = &(struct clk_regmap_gate_data) { \
|
|
.offset = (_reg), \
|
|
.bit_idx = (_bit), \
|
|
}, \
|
|
.hw.init = &(struct clk_init_data) { \
|
|
.name = #_name, \
|
|
.ops = &clk_regmap_gate_ops, \
|
|
.parent_hws = (const struct clk_hw *[]) { \
|
|
&_prefix##_name##_div.hw \
|
|
}, \
|
|
.num_parents = 1, \
|
|
.flags = (_iflags), \
|
|
}, \
|
|
}
|
|
|
|
#endif
|