1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (c) 2018 BayLibre, SAS. 4 * Author: Jerome Brunet <jbrunet@baylibre.com> 5 */ 6 7 #ifndef __CLK_REGMAP_H 8 #define __CLK_REGMAP_H 9 10 #include <linux/clk-provider.h> 11 #include <linux/regmap.h> 12 13 /** 14 * struct clk_regmap - regmap backed clock 15 * 16 * @hw: handle between common and hardware-specific interfaces 17 * @map: pointer to the regmap structure controlling the clock 18 * @data: data specific to the clock type 19 * 20 * Clock which is controlled by regmap backed registers. The actual type of 21 * of the clock is controlled by the clock_ops and data. 22 */ 23 struct clk_regmap { 24 struct clk_hw hw; 25 struct regmap *map; 26 void *data; 27 }; 28 29 static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw) 30 { 31 return container_of(hw, struct clk_regmap, hw); 32 } 33 34 /** 35 * struct clk_regmap_gate_data - regmap backed gate specific data 36 * 37 * @offset: offset of the register controlling gate 38 * @bit_idx: single bit controlling gate 39 * @flags: hardware-specific flags 40 * 41 * Flags: 42 * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored 43 */ 44 struct clk_regmap_gate_data { 45 unsigned int offset; 46 u8 bit_idx; 47 u8 flags; 48 }; 49 50 static inline struct clk_regmap_gate_data * 51 clk_get_regmap_gate_data(struct clk_regmap *clk) 52 { 53 return (struct clk_regmap_gate_data *)clk->data; 54 } 55 56 extern const struct clk_ops clk_regmap_gate_ops; 57 extern const struct clk_ops clk_regmap_gate_ro_ops; 58 59 /** 60 * struct clk_regmap_div_data - regmap backed adjustable divider specific data 61 * 62 * @offset: offset of the register controlling the divider 63 * @shift: shift to the divider bit field 64 * @width: width of the divider bit field 65 * @table: array of value/divider pairs, last entry should have div = 0 66 * 67 * Flags: 68 * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored 69 */ 70 struct clk_regmap_div_data { 71 unsigned int offset; 72 u8 shift; 73 u8 width; 74 u8 flags; 75 const struct clk_div_table *table; 76 }; 77 78 static inline struct clk_regmap_div_data * 79 clk_get_regmap_div_data(struct clk_regmap *clk) 80 { 81 return (struct clk_regmap_div_data *)clk->data; 82 } 83 84 extern const struct clk_ops clk_regmap_divider_ops; 85 extern const struct clk_ops clk_regmap_divider_ro_ops; 86 87 /** 88 * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data 89 * 90 * @hw: handle between common and hardware-specific interfaces 91 * @offset: offset of theregister controlling multiplexer 92 * @table: array of parent indexed register values 93 * @shift: shift to multiplexer bit field 94 * @mask: mask of mutliplexer bit field 95 * @flags: hardware-specific flags 96 * 97 * Flags: 98 * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored 99 */ 100 struct clk_regmap_mux_data { 101 unsigned int offset; 102 u32 *table; 103 u32 mask; 104 u8 shift; 105 u8 flags; 106 }; 107 108 static inline struct clk_regmap_mux_data * 109 clk_get_regmap_mux_data(struct clk_regmap *clk) 110 { 111 return (struct clk_regmap_mux_data *)clk->data; 112 } 113 114 extern const struct clk_ops clk_regmap_mux_ops; 115 extern const struct clk_ops clk_regmap_mux_ro_ops; 116 117 #define __MESON_PCLK(_name, _reg, _bit, _ops, _pname) \ 118 struct clk_regmap _name = { \ 119 .data = &(struct clk_regmap_gate_data){ \ 120 .offset = (_reg), \ 121 .bit_idx = (_bit), \ 122 }, \ 123 .hw.init = &(struct clk_init_data) { \ 124 .name = #_name, \ 125 .ops = _ops, \ 126 .parent_hws = (const struct clk_hw *[]) { _pname }, \ 127 .num_parents = 1, \ 128 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ 129 }, \ 130 } 131 132 #define MESON_PCLK(_name, _reg, _bit, _pname) \ 133 __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname) 134 135 #define MESON_PCLK_RO(_name, _reg, _bit, _pname) \ 136 __MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname) 137 #endif /* __CLK_REGMAP_H */ 138