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
to_clk_regmap(struct clk_hw * hw)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 *
clk_get_regmap_gate_data(struct clk_regmap * clk)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 *
clk_get_regmap_div_data(struct clk_regmap * clk)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 *
clk_get_regmap_mux_data(struct clk_regmap * clk)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