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