xref: /openbsd/sys/dev/fdt/imxanatop.c (revision f6aab3d8)
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
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
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
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
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
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
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
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
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