]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/freescale/imx/imx6_anatop.c
MFC 264052, 264057, 264065, 264094, 264103, 264120
[FreeBSD/stable/10.git] / sys / arm / freescale / imx / imx6_anatop.c
1 /*-
2  * Copyright (c) 2013 Ian Lepore <ian@freebsd.org>
3  * Copyright (c) 2014 Steven Lawrance <stl@koffein.net>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  * Analog PLL and power regulator driver for Freescale i.MX6 family of SoCs.
33  * Also, temperature montoring and cpu frequency control.  It was Freescale who
34  * kitchen-sinked this device, not us. :)
35  *
36  * We don't really do anything with analog PLLs, but the registers for
37  * controlling them belong to the same block as the power regulator registers.
38  * Since the newbus hierarchy makes it hard for anyone other than us to get at
39  * them, we just export a couple public functions to allow the imx6 CCM clock
40  * driver to read and write those registers.
41  *
42  * We also don't do anything about power regulation yet, but when the need
43  * arises, this would be the place for that code to live.
44  *
45  * I have no idea where the "anatop" name comes from.  It's in the standard DTS
46  * source describing i.MX6 SoCs, and in the linux and u-boot code which comes
47  * from Freescale, but it's not in the SoC manual.
48  *
49  * Note that temperature values throughout this code are handled in two types of
50  * units.  Items with '_cnt' in the name use the hardware temperature count
51  * units (higher counts are lower temperatures).  Items with '_val' in the name
52  * are deci-Celcius, which are converted to/from deci-Kelvins in the sysctl
53  * handlers (dK is the standard unit for temperature in sysctl).
54  */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/callout.h>
59 #include <sys/kernel.h>
60 #include <sys/limits.h>
61 #include <sys/sysctl.h>
62 #include <sys/module.h>
63 #include <sys/bus.h>
64 #include <sys/rman.h>
65
66 #include <dev/ofw/ofw_bus.h>
67 #include <dev/ofw/ofw_bus_subr.h>
68
69 #include <machine/bus.h>
70 #include <machine/fdt.h>
71
72 #include <arm/arm/mpcore_timervar.h>
73 #include <arm/freescale/fsl_ocotpreg.h>
74 #include <arm/freescale/fsl_ocotpvar.h>
75 #include <arm/freescale/imx/imx6_anatopreg.h>
76 #include <arm/freescale/imx/imx6_anatopvar.h>
77
78 static SYSCTL_NODE(_hw, OID_AUTO, imx6, CTLFLAG_RW, NULL, "i.MX6 container");
79
80 static struct resource_spec imx6_anatop_spec[] = {
81         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
82         { SYS_RES_IRQ,          0,      RF_ACTIVE },
83         { -1, 0 }
84 };
85 #define MEMRES  0
86 #define IRQRES  1
87
88 struct imx6_anatop_softc {
89         device_t        dev;
90         struct resource *res[2];
91         uint32_t        cpu_curmhz;
92         uint32_t        cpu_curmv;
93         uint32_t        cpu_minmhz;
94         uint32_t        cpu_minmv;
95         uint32_t        cpu_maxmhz;
96         uint32_t        cpu_maxmv;
97         uint32_t        cpu_maxmhz_hw;
98         boolean_t       cpu_overclock_enable;
99         uint32_t        refosc_mhz;
100         void            *temp_intrhand;
101         uint32_t        temp_high_val;
102         uint32_t        temp_high_cnt;
103         uint32_t        temp_last_cnt;
104         uint32_t        temp_room_cnt;
105         struct callout  temp_throttle_callout;
106         sbintime_t      temp_throttle_delay;
107         uint32_t        temp_throttle_reset_cnt;
108         uint32_t        temp_throttle_trigger_cnt;
109         uint32_t        temp_throttle_val;
110 };
111
112 static struct imx6_anatop_softc *imx6_anatop_sc;
113
114 /*
115  * Table of "operating points".
116  * These are combinations of frequency and voltage blessed by Freescale.
117  */
118 static struct oppt {
119         uint32_t        mhz;
120         uint32_t        mv;
121 } imx6_oppt_table[] = {
122 /*      { 396,   925},  XXX: need functional ccm code for this speed */
123         { 792,  1150},
124         { 852,  1225},
125         { 996,  1225},
126         {1200,  1275},
127 };
128
129 /*
130  * Table of CPU max frequencies.  This is used to translate the max frequency
131  * value (0-3) from the ocotp CFG3 register into a mhz value that can be looked
132  * up in the operating points table.
133  */
134 static uint32_t imx6_ocotp_mhz_tab[] = {792, 852, 996, 1200};
135
136 #define TZ_ZEROC        2732    /* deci-Kelvin <-> deci-Celcius offset. */
137
138 uint32_t
139 imx6_anatop_read_4(bus_size_t offset)
140 {
141
142         KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_read_4 sc NULL"));
143
144         return (bus_read_4(imx6_anatop_sc->res[MEMRES], offset));
145 }
146
147 void
148 imx6_anatop_write_4(bus_size_t offset, uint32_t value)
149 {
150
151         KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_write_4 sc NULL"));
152
153         bus_write_4(imx6_anatop_sc->res[MEMRES], offset, value);
154 }
155
156 static void
157 vdd_set(struct imx6_anatop_softc *sc, int mv)
158 {
159         int newtarg, oldtarg;
160         uint32_t delay, pmureg;
161         static boolean_t init_done = false;
162
163         /*
164          * The datasheet says VDD_PU and VDD_SOC must be equal, and VDD_ARM
165          * can't be more than 50mV above or 200mV below them.  For now to keep
166          * things simple we set all three to the same value.
167          */
168
169         pmureg = imx6_anatop_read_4(IMX6_ANALOG_PMU_REG_CORE);
170         oldtarg = pmureg & IMX6_ANALOG_PMU_REG0_TARG_MASK;
171
172         /* Convert mV to target value.  Clamp target to valid range. */
173         if (mv < 725)
174                 newtarg = 0x00;
175         else if (mv > 1450)
176                 newtarg = 0x1F;
177         else
178                 newtarg = (mv - 700) / 25;
179
180         /*
181          * The first time through the 3 voltages might not be equal so use a
182          * long conservative delay.  After that we need to delay 3uS for every
183          * 25mV step upward.  No need to delay at all when lowering.
184          */
185         if (init_done) {
186                 if (newtarg == oldtarg)
187                         return;
188                 else if (newtarg > oldtarg)
189                         delay = (newtarg - oldtarg) * 3;
190                 else
191                         delay = 0;
192         } else {
193                 delay = 700 / 25 * 3;
194                 init_done = true;
195         }
196
197         /*
198          * Make the change and wait for it to take effect.
199          */
200         pmureg &= ~(IMX6_ANALOG_PMU_REG0_TARG_MASK |
201             IMX6_ANALOG_PMU_REG1_TARG_MASK |
202             IMX6_ANALOG_PMU_REG2_TARG_MASK);
203
204         pmureg |= newtarg << IMX6_ANALOG_PMU_REG0_TARG_SHIFT;
205         pmureg |= newtarg << IMX6_ANALOG_PMU_REG1_TARG_SHIFT;
206         pmureg |= newtarg << IMX6_ANALOG_PMU_REG2_TARG_SHIFT;
207
208         imx6_anatop_write_4(IMX6_ANALOG_PMU_REG_CORE, pmureg);
209         DELAY(delay);
210         sc->cpu_curmv = newtarg * 25 + 700;
211 }
212
213 static inline uint32_t
214 cpufreq_mhz_from_div(struct imx6_anatop_softc *sc, uint32_t div)
215 {
216
217         return (sc->refosc_mhz * (div / 2));
218 }
219
220 static inline uint32_t
221 cpufreq_mhz_to_div(struct imx6_anatop_softc *sc, uint32_t cpu_mhz)
222 {
223
224         return (cpu_mhz / (sc->refosc_mhz / 2));
225 }
226
227 static inline uint32_t
228 cpufreq_actual_mhz(struct imx6_anatop_softc *sc, uint32_t cpu_mhz)
229 {
230
231         return (cpufreq_mhz_from_div(sc, cpufreq_mhz_to_div(sc, cpu_mhz)));
232 }
233
234 static struct oppt *
235 cpufreq_nearest_oppt(struct imx6_anatop_softc *sc, uint32_t cpu_newmhz)
236 {
237         int d, diff, i, nearest;
238
239         if (cpu_newmhz > sc->cpu_maxmhz_hw && !sc->cpu_overclock_enable)
240                 cpu_newmhz = sc->cpu_maxmhz_hw;
241
242         diff = INT_MAX;
243         nearest = 0;
244         for (i = 0; i < nitems(imx6_oppt_table); ++i) {
245                 d = abs((int)cpu_newmhz - (int)imx6_oppt_table[i].mhz);
246                 if (diff > d) {
247                         diff = d;
248                         nearest = i;
249                 }
250         }
251         return (&imx6_oppt_table[nearest]);
252 }
253
254 static void 
255 cpufreq_set_clock(struct imx6_anatop_softc * sc, struct oppt *op)
256 {
257         uint32_t timeout, wrk32;
258
259         /* If increasing the frequency, we must first increase the voltage. */
260         if (op->mhz > sc->cpu_curmhz) {
261                 vdd_set(sc, op->mv);
262         }
263
264         /*
265          * I can't find a documented procedure for changing the ARM PLL divisor,
266          * but some trial and error came up with this:
267          *  - Set the bypass clock source to REF_CLK_24M (source #0).
268          *  - Set the PLL into bypass mode; cpu should now be running at 24mhz.
269          *  - Change the divisor.
270          *  - Wait for the LOCK bit to come on; it takes ~50 loop iterations.
271          *  - Turn off bypass mode; cpu should now be running at the new speed.
272          */
273         imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, 
274             IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK);
275         imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_SET, 
276             IMX6_ANALOG_CCM_PLL_ARM_BYPASS);
277
278         wrk32 = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM);
279         wrk32 &= ~IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK;
280         wrk32 |= cpufreq_mhz_to_div(sc, op->mhz);
281         imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM, wrk32);
282
283         timeout = 10000;
284         while ((imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) &
285             IMX6_ANALOG_CCM_PLL_ARM_LOCK) == 0)
286                 if (--timeout == 0)
287                         panic("imx6_set_cpu_clock(): PLL never locked");
288
289         imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, 
290             IMX6_ANALOG_CCM_PLL_ARM_BYPASS);
291
292         /* If lowering the frequency, it is now safe to lower the voltage. */
293         if (op->mhz < sc->cpu_curmhz)
294                 vdd_set(sc, op->mv);
295         sc->cpu_curmhz = op->mhz;
296
297         /* Tell the mpcore timer that its frequency has changed. */
298         arm_tmr_change_frequency(
299             cpufreq_actual_mhz(sc, sc->cpu_curmhz) * 1000000 / 2);
300 }
301
302 static int
303 cpufreq_sysctl_minmhz(SYSCTL_HANDLER_ARGS)
304 {
305         struct imx6_anatop_softc *sc;
306         struct oppt * op;
307         uint32_t temp;
308         int err;
309
310         sc = arg1;
311
312         temp = sc->cpu_minmhz;
313         err = sysctl_handle_int(oidp, &temp, 0, req);
314         if (err != 0 || req->newptr == NULL)
315                 return (err);
316
317         op = cpufreq_nearest_oppt(sc, temp);
318         if (op->mhz > sc->cpu_maxmhz)
319                 return (ERANGE);
320         else if (op->mhz == sc->cpu_minmhz)
321                 return (0);
322
323         /*
324          * Value changed, update softc.  If the new min is higher than the
325          * current speed, raise the current speed to match.
326          */
327         sc->cpu_minmhz = op->mhz;
328         if (sc->cpu_minmhz > sc->cpu_curmhz) {
329                 cpufreq_set_clock(sc, op);
330         }
331         return (err);
332 }
333
334 static int
335 cpufreq_sysctl_maxmhz(SYSCTL_HANDLER_ARGS)
336 {
337         struct imx6_anatop_softc *sc;
338         struct oppt * op;
339         uint32_t temp;
340         int err;
341
342         sc = arg1;
343
344         temp = sc->cpu_maxmhz;
345         err = sysctl_handle_int(oidp, &temp, 0, req);
346         if (err != 0 || req->newptr == NULL)
347                 return (err);
348
349         op = cpufreq_nearest_oppt(sc, temp);
350         if (op->mhz < sc->cpu_minmhz)
351                 return (ERANGE);
352         else if (op->mhz == sc->cpu_maxmhz)
353                 return (0);
354
355         /*
356          *  Value changed, update softc and hardware.  The hardware update is
357          *  unconditional.  We always try to run at max speed, so any change of
358          *  the max means we need to change the current speed too, regardless of
359          *  whether it is higher or lower than the old max.
360          */
361         sc->cpu_maxmhz = op->mhz;
362         cpufreq_set_clock(sc, op);
363
364         return (err);
365 }
366
367 static void
368 cpufreq_initialize(struct imx6_anatop_softc *sc)
369 {
370         uint32_t cfg3speed;
371         struct oppt * op;
372
373         SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
374             OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0, 
375             "CPU frequency");
376
377         SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6), 
378             OID_AUTO, "cpu_minmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
379             cpufreq_sysctl_minmhz, "IU", "Minimum CPU frequency");
380
381         SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
382             OID_AUTO, "cpu_maxmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
383             cpufreq_sysctl_maxmhz, "IU", "Maximum CPU frequency");
384
385         SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
386             OID_AUTO, "cpu_maxmhz_hw", CTLFLAG_RD, &sc->cpu_maxmhz_hw, 0, 
387             "Maximum CPU frequency allowed by hardware");
388
389         SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
390             OID_AUTO, "cpu_overclock_enable", CTLFLAG_RWTUN, 
391             &sc->cpu_overclock_enable, 0, 
392             "Allow setting CPU frequency higher than cpu_maxmhz_hw");
393
394         /*
395          * XXX 24mhz shouldn't be hard-coded, should get this from imx6_ccm
396          * (even though in the real world it will always be 24mhz).  Oh wait a
397          * sec, I never wrote imx6_ccm.
398          */
399         sc->refosc_mhz = 24;
400
401         /*
402          * Get the maximum speed this cpu can be set to.  The values in the
403          * OCOTP CFG3 register are not documented in the reference manual.
404          * The following info was in an archived email found via web search:
405          *   - 2b'11: 1200000000Hz;
406          *   - 2b'10: 996000000Hz;
407          *   - 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
408          *   - 2b'00: 792000000Hz;
409          * The default hardware max speed can be overridden by a tunable.
410          */
411         cfg3speed = (fsl_ocotp_read_4(FSL_OCOTP_CFG3) & 
412             FSL_OCOTP_CFG3_SPEED_MASK) >> FSL_OCOTP_CFG3_SPEED_SHIFT;
413         sc->cpu_maxmhz_hw = imx6_ocotp_mhz_tab[cfg3speed];
414         sc->cpu_maxmhz = sc->cpu_maxmhz_hw;
415
416         TUNABLE_INT_FETCH("hw.imx6.cpu_overclock_enable",
417             &sc->cpu_overclock_enable);
418
419         TUNABLE_INT_FETCH("hw.imx6.cpu_minmhz", &sc->cpu_minmhz);
420         op = cpufreq_nearest_oppt(sc, sc->cpu_minmhz);
421         sc->cpu_minmhz = op->mhz;
422         sc->cpu_minmv = op->mv;
423
424         TUNABLE_INT_FETCH("hw.imx6.cpu_maxmhz", &sc->cpu_maxmhz);
425         op = cpufreq_nearest_oppt(sc, sc->cpu_maxmhz);
426         sc->cpu_maxmhz = op->mhz;
427         sc->cpu_maxmv = op->mv;
428
429         /*
430          * Set the CPU to maximum speed.
431          *
432          * We won't have thermal throttling until interrupts are enabled, but we
433          * want to run at full speed through all the device init stuff.  This
434          * basically assumes that a single core can't overheat before interrupts
435          * are enabled; empirical testing shows that to be a safe assumption.
436          */
437         cpufreq_set_clock(sc, op);
438 }
439
440 static inline uint32_t
441 temp_from_count(struct imx6_anatop_softc *sc, uint32_t count)
442 {
443
444         return (((sc->temp_high_val - (count - sc->temp_high_cnt) *
445             (sc->temp_high_val - 250) / 
446             (sc->temp_room_cnt - sc->temp_high_cnt))));
447 }
448
449 static inline uint32_t
450 temp_to_count(struct imx6_anatop_softc *sc, uint32_t temp)
451 {
452
453         return ((sc->temp_room_cnt - sc->temp_high_cnt) * 
454             (sc->temp_high_val - temp) / (sc->temp_high_val - 250) + 
455             sc->temp_high_cnt);
456 }
457
458 static void
459 temp_update_count(struct imx6_anatop_softc *sc)
460 {
461         uint32_t val;
462
463         val = imx6_anatop_read_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0);
464         if (!(val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_VALID))
465                 return;
466         sc->temp_last_cnt =
467             (val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_MASK) >>
468             IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT;
469 }
470
471 static int
472 temp_sysctl_handler(SYSCTL_HANDLER_ARGS)
473 {
474         struct imx6_anatop_softc *sc = arg1;
475         uint32_t t;
476
477         temp_update_count(sc);
478
479         t = temp_from_count(sc, sc->temp_last_cnt) + TZ_ZEROC;
480
481         return (sysctl_handle_int(oidp, &t, 0, req));
482 }
483
484 static int
485 temp_throttle_sysctl_handler(SYSCTL_HANDLER_ARGS)
486 {
487         struct imx6_anatop_softc *sc = arg1;
488         int err;
489         uint32_t temp;
490
491         temp = sc->temp_throttle_val + TZ_ZEROC;
492         err = sysctl_handle_int(oidp, &temp, 0, req);
493         if (temp < TZ_ZEROC)
494                 return (ERANGE);
495         temp -= TZ_ZEROC;
496         if (err != 0 || req->newptr == NULL || temp == sc->temp_throttle_val)
497                 return (err);
498
499         /* Value changed, update counts in softc and hardware. */
500         sc->temp_throttle_val = temp;
501         sc->temp_throttle_trigger_cnt = temp_to_count(sc, sc->temp_throttle_val);
502         sc->temp_throttle_reset_cnt = temp_to_count(sc, sc->temp_throttle_val - 100);
503         imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR,
504             IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK);
505         imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET,
506             (sc->temp_throttle_trigger_cnt <<
507              IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT));
508         return (err);
509 }
510
511 static void
512 tempmon_gofast(struct imx6_anatop_softc *sc)
513 {
514
515         if (sc->cpu_curmhz < sc->cpu_maxmhz) {
516                 cpufreq_set_clock(sc, cpufreq_nearest_oppt(sc, sc->cpu_maxmhz));
517         }
518 }
519
520 static void
521 tempmon_goslow(struct imx6_anatop_softc *sc)
522 {
523
524         if (sc->cpu_curmhz > sc->cpu_minmhz) {
525                 cpufreq_set_clock(sc, cpufreq_nearest_oppt(sc, sc->cpu_minmhz));
526         }
527 }
528
529 static int
530 tempmon_intr(void *arg)
531 {
532         struct imx6_anatop_softc *sc = arg;
533
534         /*
535          * XXX Note that this code doesn't currently run (for some mysterious
536          * reason we just never get an interrupt), so the real monitoring is
537          * done by tempmon_throttle_check().
538          */
539         tempmon_goslow(sc);
540         /* XXX Schedule callout to speed back up eventually. */
541         return (FILTER_HANDLED);
542 }
543
544 static void
545 tempmon_throttle_check(void *arg)
546 {
547         struct imx6_anatop_softc *sc = arg;
548
549         /* Lower counts are higher temperatures. */
550         if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt)
551                 tempmon_goslow(sc);
552         else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt))
553                 tempmon_gofast(sc);
554
555         callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
556                 0, tempmon_throttle_check, sc, 0);
557
558 }
559
560 static void
561 initialize_tempmon(struct imx6_anatop_softc *sc)
562 {
563         uint32_t cal;
564         struct sysctl_ctx_list *ctx;
565
566         /*
567          * Fetch calibration data: a sensor count at room temperature (25C),
568          * a sensor count at a high temperature, and that temperature
569          */
570         cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1);
571         sc->temp_room_cnt = (cal & 0xFFF00000) >> 20;
572         sc->temp_high_cnt = (cal & 0x000FFF00) >> 8;
573         sc->temp_high_val = (cal & 0x000000FF) * 10;
574
575         /*
576          * Throttle to a lower cpu freq at 10C below the "hot" temperature, and
577          * reset back to max cpu freq at 5C below the trigger.
578          */
579         sc->temp_throttle_val = sc->temp_high_val - 100;
580         sc->temp_throttle_trigger_cnt =
581             temp_to_count(sc, sc->temp_throttle_val);
582         sc->temp_throttle_reset_cnt = 
583             temp_to_count(sc, sc->temp_throttle_val - 50);
584
585         /*
586          * Set the sensor to sample automatically at 16Hz (32.768KHz/0x800), set
587          * the throttle count, and begin making measurements.
588          */
589         imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE1, 0x0800);
590         imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0,
591             (sc->temp_throttle_trigger_cnt << 
592             IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) |
593             IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE);
594
595         /*
596          * XXX Note that the alarm-interrupt feature isn't working yet, so
597          * we'll use a callout handler to check at 10Hz.  Make sure we have an
598          * initial temperature reading before starting up the callouts so we
599          * don't get a bogus reading of zero.
600          */
601         while (sc->temp_last_cnt == 0)
602                 temp_update_count(sc);
603         sc->temp_throttle_delay = 100 * SBT_1MS;
604         callout_init(&sc->temp_throttle_callout, 0);
605         callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay, 
606             0, tempmon_throttle_check, sc, 0);
607
608         ctx = device_get_sysctl_ctx(sc->dev);
609         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
610             OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
611             temp_sysctl_handler, "IK", "Current die temperature");
612         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
613             OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc,
614             0, temp_throttle_sysctl_handler, "IK", 
615             "Throttle CPU when exceeding this temperature");
616 }
617
618 static int
619 imx6_anatop_detach(device_t dev)
620 {
621
622         return (EBUSY);
623 }
624
625 static int
626 imx6_anatop_attach(device_t dev)
627 {
628         struct imx6_anatop_softc *sc;
629         int err;
630
631         sc = device_get_softc(dev);
632         sc->dev = dev;
633
634         /* Allocate bus_space resources. */
635         if (bus_alloc_resources(dev, imx6_anatop_spec, sc->res)) {
636                 device_printf(dev, "Cannot allocate resources\n");
637                 err = ENXIO;
638                 goto out;
639         }
640
641         err = bus_setup_intr(dev, sc->res[IRQRES], INTR_TYPE_MISC | INTR_MPSAFE,
642             tempmon_intr, NULL, sc, &sc->temp_intrhand);
643         if (err != 0)
644                 goto out;
645
646         SYSCTL_ADD_UINT(device_get_sysctl_ctx(sc->dev),
647             SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
648             OID_AUTO, "cpu_voltage", CTLFLAG_RD,
649             &sc->cpu_curmv, 0, "Current CPU voltage in millivolts");
650
651         imx6_anatop_sc = sc;
652
653         /*
654          * Other code seen on the net sets this SELFBIASOFF flag around the same
655          * time the temperature sensor is set up, although it's unclear how the
656          * two are related (if at all).
657          */
658         imx6_anatop_write_4(IMX6_ANALOG_PMU_MISC0_SET, 
659             IMX6_ANALOG_PMU_MISC0_SELFBIASOFF);
660
661         cpufreq_initialize(sc);
662         initialize_tempmon(sc);
663
664         if (bootverbose) {
665                 device_printf(sc->dev, "CPU %uMHz @ %umV\n", sc->cpu_curmhz,
666                     sc->cpu_curmv);
667         }
668         err = 0;
669
670 out:
671
672         if (err != 0) {
673                 bus_release_resources(dev, imx6_anatop_spec, sc->res);
674         }
675
676         return (err);
677 }
678
679 static int
680 imx6_anatop_probe(device_t dev)
681 {
682
683         if (!ofw_bus_status_okay(dev))
684                 return (ENXIO);
685
686         if (ofw_bus_is_compatible(dev, "fsl,imx6q-anatop") == 0)
687                 return (ENXIO);
688
689         device_set_desc(dev, "Freescale i.MX6 Analog PLLs and Power");
690
691         return (BUS_PROBE_DEFAULT);
692 }
693
694 uint32_t 
695 imx6_get_cpu_clock()
696 {
697         uint32_t div;
698
699         div = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) &
700             IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK;
701         return (cpufreq_mhz_from_div(imx6_anatop_sc, div));
702 }
703
704 static device_method_t imx6_anatop_methods[] = {
705         /* Device interface */
706         DEVMETHOD(device_probe,  imx6_anatop_probe),
707         DEVMETHOD(device_attach, imx6_anatop_attach),
708         DEVMETHOD(device_detach, imx6_anatop_detach),
709
710         DEVMETHOD_END
711 };
712
713 static driver_t imx6_anatop_driver = {
714         "imx6_anatop",
715         imx6_anatop_methods,
716         sizeof(struct imx6_anatop_softc)
717 };
718
719 static devclass_t imx6_anatop_devclass;
720
721 DRIVER_MODULE(imx6_anatop, simplebus, imx6_anatop_driver, imx6_anatop_devclass, 0, 0);
722