1 /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ 2 /* 3 * Copyright (c) 2023 Neil Armstrong <neil.armstrong@linaro.org> 4 */ 5 6 #ifndef __MESON_CLKC_UTILS_H__ 7 #define __MESON_CLKC_UTILS_H__ 8 9 #include <linux/of_device.h> 10 #include <linux/clk-provider.h> 11 12 struct platform_device; 13 14 struct meson_clk_hw_data { 15 struct clk_hw **hws; 16 unsigned int num; 17 }; 18 19 struct clk_hw *meson_clk_hw_get(struct of_phandle_args *clkspec, void *clk_hw_data); 20 21 struct meson_clkc_data { 22 const struct reg_sequence *init_regs; 23 unsigned int init_count; 24 struct meson_clk_hw_data hw_clks; 25 }; 26 27 int meson_clkc_syscon_probe(struct platform_device *pdev); 28 int meson_clkc_mmio_probe(struct platform_device *pdev); 29 30 #define __MESON_PCLK(_name, _reg, _bit, _ops, _pdata, _flags) \ 31 struct clk_regmap _name = { \ 32 .data = &(struct clk_regmap_gate_data) { \ 33 .offset = (_reg), \ 34 .bit_idx = (_bit), \ 35 }, \ 36 .hw.init = &(struct clk_init_data) { \ 37 .name = #_name, \ 38 .ops = _ops, \ 39 .parent_data = (_pdata), \ 40 .num_parents = 1, \ 41 .flags = (_flags), \ 42 }, \ 43 } 44 45 #define MESON_PCLK(_name, _reg, _bit, _pdata, _flags) \ 46 __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pdata, _flags) 47 48 #define MESON_PCLK_RO(_name, _reg, _bit, _pdata, _flags) \ 49 __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pdata, _flags) 50 51 /* Helpers for the usual sel/div/gate composite clocks */ 52 #define MESON_COMP_SEL(_prefix, _name, _reg, _shift, _mask, _pdata, \ 53 _table, _dflags, _iflags) \ 54 struct clk_regmap _prefix##_name##_sel = { \ 55 .data = &(struct clk_regmap_mux_data) { \ 56 .offset = (_reg), \ 57 .mask = (_mask), \ 58 .shift = (_shift), \ 59 .flags = (_dflags), \ 60 .table = (_table), \ 61 }, \ 62 .hw.init = &(struct clk_init_data){ \ 63 .name = #_name "_sel", \ 64 .ops = &clk_regmap_mux_ops, \ 65 .parent_data = _pdata, \ 66 .num_parents = ARRAY_SIZE(_pdata), \ 67 .flags = (_iflags), \ 68 }, \ 69 } 70 71 #define MESON_COMP_DIV(_prefix, _name, _reg, _shift, _width, \ 72 _dflags, _iflags) \ 73 struct clk_regmap _prefix##_name##_div = { \ 74 .data = &(struct clk_regmap_div_data) { \ 75 .offset = (_reg), \ 76 .shift = (_shift), \ 77 .width = (_width), \ 78 .flags = (_dflags), \ 79 }, \ 80 .hw.init = &(struct clk_init_data) { \ 81 .name = #_name "_div", \ 82 .ops = &clk_regmap_divider_ops, \ 83 .parent_hws = (const struct clk_hw *[]) { \ 84 &_prefix##_name##_sel.hw \ 85 }, \ 86 .num_parents = 1, \ 87 .flags = (_iflags), \ 88 }, \ 89 } 90 91 #define MESON_COMP_GATE(_prefix, _name, _reg, _bit, _iflags) \ 92 struct clk_regmap _prefix##_name = { \ 93 .data = &(struct clk_regmap_gate_data) { \ 94 .offset = (_reg), \ 95 .bit_idx = (_bit), \ 96 }, \ 97 .hw.init = &(struct clk_init_data) { \ 98 .name = #_name, \ 99 .ops = &clk_regmap_gate_ops, \ 100 .parent_hws = (const struct clk_hw *[]) { \ 101 &_prefix##_name##_div.hw \ 102 }, \ 103 .num_parents = 1, \ 104 .flags = (_iflags), \ 105 }, \ 106 } 107 108 #endif 109