1 /* $OpenBSD: imxanatop.c,v 1.6 2021/10/24 17:52:26 mpi Exp $ */
2 /*
3 * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_misc.h>
28 #include <dev/ofw/ofw_regulator.h>
29 #include <dev/ofw/fdt.h>
30
31 #include <dev/fdt/imxanatopvar.h>
32
33 #define ANALOG_PLL_ARM 0x0000
34 #define ANALOG_PLL_ARM_SET 0x0004
35 #define ANALOG_PLL_ARM_CLR 0x0008
36 #define ANALOG_PLL_ARM_DIV_SELECT_MASK 0x7f
37 #define ANALOG_PLL_ARM_BYPASS (1 << 16)
38 #define ANALOG_PLL_USB1 0x0010
39 #define ANALOG_PLL_USB1_SET 0x0014
40 #define ANALOG_PLL_USB1_CLR 0x0018
41 #define ANALOG_PLL_USB1_DIV_SELECT_MASK 0x1
42 #define ANALOG_PLL_USB1_EN_USB_CLKS (1 << 6)
43 #define ANALOG_PLL_USB1_POWER (1 << 12)
44 #define ANALOG_PLL_USB1_ENABLE (1 << 13)
45 #define ANALOG_PLL_USB1_BYPASS (1 << 16)
46 #define ANALOG_PLL_USB1_LOCK (1U << 31)
47 #define ANALOG_PLL_USB2 0x0020
48 #define ANALOG_PLL_USB2_SET 0x0024
49 #define ANALOG_PLL_USB2_CLR 0x0028
50 #define ANALOG_PLL_USB2_DIV_SELECT_MASK 0x1
51 #define ANALOG_PLL_USB2_EN_USB_CLKS (1 << 6)
52 #define ANALOG_PLL_USB2_POWER (1 << 12)
53 #define ANALOG_PLL_USB2_ENABLE (1 << 13)
54 #define ANALOG_PLL_USB2_BYPASS (1 << 16)
55 #define ANALOG_PLL_USB2_LOCK (1U << 31)
56 #define ANALOG_PLL_SYS 0x0030
57 #define ANALOG_PLL_SYS_DIV_SELECT_MASK 0x1
58 #define ANALOG_PLL_ENET 0x00e0
59 #define ANALOG_PLL_ENET_SET 0x00e4
60 #define ANALOG_PLL_ENET_CLR 0x00e8
61 #define ANALOG_PLL_ENET_DIV_125M (1 << 11)
62 #define ANALOG_PLL_ENET_POWERDOWN (1 << 12)
63 #define ANALOG_PLL_ENET_ENABLE (1 << 13)
64 #define ANALOG_PLL_ENET_BYPASS (1 << 16)
65 #define ANALOG_PLL_ENET_125M_PCIE (1 << 19)
66 #define ANALOG_PLL_ENET_100M_SATA (1 << 20)
67 #define ANALOG_PLL_ENET_LOCK (1U << 31)
68 #define ANALOG_PFD_480 0x00f0
69 #define ANALOG_PFD_480_SET 0x00f4
70 #define ANALOG_PFD_480_CLR 0x00f8
71 #define ANALOG_PFD_480_PFDx_FRAC(x, y) (((x) >> ((y) << 3)) & 0x3f)
72 #define ANALOG_PFD_528 0x0100
73 #define ANALOG_PFD_528_SET 0x0104
74 #define ANALOG_PFD_528_CLR 0x0108
75 #define ANALOG_PFD_528_PFDx_FRAC(x, y) (((x) >> ((y) << 3)) & 0x3f)
76 #define ANALOG_USB1_CHRG_DETECT 0x01b0
77 #define ANALOG_USB1_CHRG_DETECT_SET 0x01b4
78 #define ANALOG_USB1_CHRG_DETECT_CLR 0x01b8
79 #define ANALOG_USB1_CHRG_DETECT_CHK_CHRG_B (1 << 19)
80 #define ANALOG_USB1_CHRG_DETECT_EN_B (1 << 20)
81 #define ANALOG_USB2_CHRG_DETECT 0x0210
82 #define ANALOG_USB2_CHRG_DETECT_SET 0x0214
83 #define ANALOG_USB2_CHRG_DETECT_CLR 0x0218
84 #define ANALOG_USB2_CHRG_DETECT_CHK_CHRG_B (1 << 19)
85 #define ANALOG_USB2_CHRG_DETECT_EN_B (1 << 20)
86 #define ANALOG_DIGPROG 0x0260
87 #define ANALOG_DIGPROG_MINOR_MASK 0xff
88
89 #define HCLK_FREQ 24000000
90
91 #define HREAD4(sc, reg) \
92 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
93 #define HWRITE4(sc, reg, val) \
94 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
95 #define HSET4(sc, reg, bits) \
96 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
97 #define HCLR4(sc, reg, bits) \
98 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
99
100 struct imxanatop_softc {
101 struct device sc_dev;
102 bus_space_tag_t sc_iot;
103 bus_space_handle_t sc_ioh;
104 };
105
106 struct imxanatop_softc *imxanatop_sc;
107
108 struct imxanatop_regulator {
109 struct imxanatop_softc *ir_sc;
110
111 uint32_t ir_reg_offset;
112 uint32_t ir_vol_bit_shift;
113 uint32_t ir_vol_bit_width;
114 uint32_t ir_min_bit_val;
115 uint32_t ir_min_voltage;
116 uint32_t ir_max_voltage;
117
118 uint32_t ir_delay_reg_offset;
119 uint32_t ir_delay_bit_shift;
120 uint32_t ir_delay_bit_width;
121
122 struct regulator_device ir_rd;
123 };
124
125 int imxanatop_match(struct device *, void *, void *);
126 void imxanatop_attach(struct device *, struct device *, void *);
127
128 const struct cfattach imxanatop_ca = {
129 sizeof(struct imxanatop_softc), imxanatop_match, imxanatop_attach
130 };
131
132 struct cfdriver imxanatop_cd = {
133 NULL, "imxanatop", DV_DULL
134 };
135
136 void imxanatop_attach_regulator(struct imxanatop_softc *, int);
137 uint32_t imxanatop_get_voltage(void *);
138 int imxanatop_set_voltage(void *, uint32_t);
139
140 int
imxanatop_match(struct device * parent,void * match,void * aux)141 imxanatop_match(struct device *parent, void *match, void *aux)
142 {
143 struct fdt_attach_args *faa = aux;
144
145 if (OF_is_compatible(faa->fa_node, "fsl,imx6q-anatop"))
146 return 10; /* Must beat simplebus(4) and syscon(4). */
147
148 return 0;
149 }
150
151 void
imxanatop_attach(struct device * parent,struct device * self,void * aux)152 imxanatop_attach(struct device *parent, struct device *self, void *aux)
153 {
154 struct imxanatop_softc *sc = (struct imxanatop_softc *)self;
155 struct fdt_attach_args *faa = aux;
156 int node;
157
158 if (faa->fa_nreg < 1) {
159 printf(": no registers\n");
160 return;
161 }
162
163 sc->sc_iot = faa->fa_iot;
164
165 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
166 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
167 printf(": can't map registers\n");
168 return;
169 }
170
171 regmap_register(faa->fa_node, sc->sc_iot, sc->sc_ioh,
172 faa->fa_reg[0].size);
173
174 printf("\n");
175
176 for (node = OF_child(faa->fa_node); node; node = OF_peer(node))
177 if (OF_is_compatible(node, "fsl,anatop-regulator"))
178 imxanatop_attach_regulator(sc, node);
179
180 imxanatop_sc = sc;
181 }
182
183 void
imxanatop_attach_regulator(struct imxanatop_softc * sc,int node)184 imxanatop_attach_regulator(struct imxanatop_softc *sc, int node)
185 {
186 struct imxanatop_regulator *ir;
187
188 ir = malloc(sizeof(*ir), M_DEVBUF, M_WAITOK | M_ZERO);
189 ir->ir_sc = sc;
190
191 ir->ir_reg_offset = OF_getpropint(node, "anatop-reg-offset", -1);
192 ir->ir_vol_bit_shift = OF_getpropint(node, "anatop-vol-bit-shift", -1);
193 ir->ir_vol_bit_width = OF_getpropint(node, "anatop-vol-bit-width", -1);
194 ir->ir_min_bit_val = OF_getpropint(node, "anatop-min-bit-val", -1);
195 ir->ir_min_voltage = OF_getpropint(node, "anatop-min-voltage", -1);
196 ir->ir_max_voltage = OF_getpropint(node, "anatop-max-voltage", -1);
197 if (ir->ir_reg_offset == -1 || ir->ir_vol_bit_shift == -1 ||
198 ir->ir_vol_bit_width == -1 || ir->ir_min_bit_val == -1 ||
199 ir->ir_min_voltage == -1 || ir->ir_max_voltage == -1) {
200 free(ir, M_DEVBUF, sizeof(*ir));
201 return;
202 }
203
204 ir->ir_delay_reg_offset =
205 OF_getpropint(node, "anatop-delay-reg-offset", 0);
206 ir->ir_delay_bit_shift =
207 OF_getpropint(node, "anatop-delay-bit-shift", 0);
208 ir->ir_delay_bit_width =
209 OF_getpropint(node, "anatop-delay-bit-width", 0);
210
211 ir->ir_rd.rd_node = node;
212 ir->ir_rd.rd_cookie = ir;
213 ir->ir_rd.rd_get_voltage = imxanatop_get_voltage;
214 ir->ir_rd.rd_set_voltage = imxanatop_set_voltage;
215 regulator_register(&ir->ir_rd);
216 }
217
218 uint32_t
imxanatop_get_voltage(void * cookie)219 imxanatop_get_voltage(void *cookie)
220 {
221 struct imxanatop_regulator *ir = cookie;
222 uint32_t bit_val;
223
224 bit_val = HREAD4(ir->ir_sc, ir->ir_reg_offset) >> ir->ir_vol_bit_shift;
225 bit_val &= ((1 << ir->ir_vol_bit_width) - 1);
226 return (ir->ir_min_voltage + (bit_val - ir->ir_min_bit_val) * 25000);
227 }
228
229 int
imxanatop_set_voltage(void * cookie,uint32_t voltage)230 imxanatop_set_voltage(void *cookie, uint32_t voltage)
231 {
232 struct imxanatop_regulator *ir = cookie;
233 uint32_t bit_val, old_bit_val, reg;
234 int steps, usecs;
235
236 if (voltage < ir->ir_min_voltage || voltage > ir->ir_max_voltage)
237 return -1;
238
239 bit_val = ir->ir_min_bit_val + (voltage - ir->ir_min_voltage) / 25000;
240 reg = HREAD4(ir->ir_sc, ir->ir_reg_offset);
241 old_bit_val = (reg >> ir->ir_vol_bit_shift);
242 old_bit_val &= ((1 << ir->ir_vol_bit_width) -1);
243 reg &= ~((1 << ir->ir_vol_bit_width) - 1) << ir->ir_vol_bit_shift;
244 reg |= (bit_val << ir->ir_vol_bit_shift);
245 HWRITE4(ir->ir_sc, ir->ir_reg_offset, reg);
246
247 steps = bit_val - old_bit_val;
248 if (steps > 0 && ir->ir_delay_bit_width > 0) {
249 reg = HREAD4(ir->ir_sc, ir->ir_delay_reg_offset);
250 reg >>= ir->ir_delay_bit_shift;
251 reg &= ((1 << ir->ir_delay_bit_width) - 1);
252 usecs = ((reg + 1) * steps * 64 * 1000000) / 24000000;
253 delay(usecs);
254 }
255
256 return 0;
257 }
258
259 uint32_t
imxanatop_decode_pll(enum imxanatop_clocks pll,uint32_t freq)260 imxanatop_decode_pll(enum imxanatop_clocks pll, uint32_t freq)
261 {
262 struct imxanatop_softc *sc = imxanatop_sc;
263 uint32_t div;
264
265 KASSERT(sc != NULL);
266
267 switch (pll) {
268 case ARM_PLL1:
269 if (HREAD4(sc, ANALOG_PLL_ARM)
270 & ANALOG_PLL_ARM_BYPASS)
271 return freq;
272 div = HREAD4(sc, ANALOG_PLL_ARM)
273 & ANALOG_PLL_ARM_DIV_SELECT_MASK;
274 return (freq * div) / 2;
275 case SYS_PLL2:
276 div = HREAD4(sc, ANALOG_PLL_SYS)
277 & ANALOG_PLL_SYS_DIV_SELECT_MASK;
278 return freq * (20 + (div << 1));
279 case USB1_PLL3:
280 div = HREAD4(sc, ANALOG_PLL_USB2)
281 & ANALOG_PLL_USB2_DIV_SELECT_MASK;
282 return freq * (20 + (div << 1));
283 default:
284 return 0;
285 }
286 }
287
288 uint32_t
imxanatop_get_pll2_pfd(unsigned int pfd)289 imxanatop_get_pll2_pfd(unsigned int pfd)
290 {
291 struct imxanatop_softc *sc = imxanatop_sc;
292 KASSERT(sc != NULL);
293
294 return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ) * 18ULL
295 / ANALOG_PFD_528_PFDx_FRAC(HREAD4(sc, ANALOG_PFD_528), pfd);
296 }
297
298 uint32_t
imxanatop_get_pll3_pfd(unsigned int pfd)299 imxanatop_get_pll3_pfd(unsigned int pfd)
300 {
301 struct imxanatop_softc *sc = imxanatop_sc;
302 KASSERT(sc != NULL);
303
304 return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ) * 18ULL
305 / ANALOG_PFD_480_PFDx_FRAC(HREAD4(sc, ANALOG_PFD_480), pfd);
306 }
307