]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/nvidia/tegra210/tegra210_pmc.c
libarchive: merge from vendor branch
[FreeBSD/FreeBSD.git] / sys / arm64 / nvidia / tegra210 / tegra210_pmc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
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 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/mutex.h>
38 #include <sys/rman.h>
39
40 #include <machine/bus.h>
41
42 #include <dev/extres/clk/clk.h>
43 #include <dev/extres/hwreset/hwreset.h>
44 #include <dev/ofw/ofw_bus.h>
45 #include <dev/ofw/ofw_bus_subr.h>
46 #include <dev/psci/smccc.h>
47
48 #include <arm/nvidia/tegra_pmc.h>
49
50 #define PMC_CNTRL                       0x000
51 #define  PMC_CNTRL_SHUTDOWN_OE                  (1 << 22)
52 #define  PMC_CNTRL_CPUPWRGOOD_SEL_MASK          (0x3 << 20)
53 #define  PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT         20
54 #define  PMC_CNTRL_CPUPWRGOOD_EN                (1 << 19)
55 #define  PMC_CNTRL_FUSE_OVERRIDE                (1 << 18)
56 #define  PMC_CNTRL_INTR_POLARITY                (1 << 17)
57 #define  PMC_CNTRL_CPU_PWRREQ_OE                (1 << 16)
58 #define  PMC_CNTRL_CPU_PWRREQ_POLARITY          (1 << 15)
59 #define  PMC_CNTRL_SIDE_EFFECT_LP0              (1 << 14)
60 #define  PMC_CNTRL_AOINIT                       (1 << 13)
61 #define  PMC_CNTRL_PWRGATE_DIS                  (1 << 12)
62 #define  PMC_CNTRL_SYSCLK_OE                    (1 << 11)
63 #define  PMC_CNTRL_SYSCLK_POLARITY              (1 << 10)
64 #define  PMC_CNTRL_PWRREQ_OE                    (1 <<  9)
65 #define  PMC_CNTRL_PWRREQ_POLARITY              (1 <<  8)
66 #define  PMC_CNTRL_BLINK_EN                     (1 <<  7)
67 #define  PMC_CNTRL_GLITCHDET_DIS                (1 <<  6)
68 #define  PMC_CNTRL_LATCHWAKE_EN                 (1 <<  5)
69 #define  PMC_CNTRL_MAIN_RST                     (1 <<  4)
70 #define  PMC_CNTRL_KBC_RST                      (1 <<  3)
71 #define  PMC_CNTRL_RTC_RST                      (1 <<  2)
72 #define  PMC_CNTRL_RTC_CLK_DIS                  (1 <<  1)
73 #define  PMC_CNTRL_KBC_CLK_DIS                  (1 <<  0)
74
75 #define PMC_DPD_SAMPLE                  0x020
76
77 #define PMC_CLAMP_STATUS                0x02C
78 #define   PMC_CLAMP_STATUS_PARTID(x)            (1 << ((x) & 0x1F))
79
80 #define PMC_PWRGATE_TOGGLE              0x030
81 #define  PMC_PWRGATE_TOGGLE_START               (1 << 8)
82 #define  PMC_PWRGATE_TOGGLE_PARTID(x)           (((x) & 0x1F) << 0)
83
84 #define PMC_REMOVE_CLAMPING_CMD         0x034
85 #define   PMC_REMOVE_CLAMPING_CMD_PARTID(x)     (1 << ((x) & 0x1F))
86
87 #define PMC_PWRGATE_STATUS              0x038
88 #define PMC_PWRGATE_STATUS_PARTID(x)            (1 << ((x) & 0x1F))
89
90 #define PMC_SCRATCH0                    0x050
91 #define  PMC_SCRATCH0_MODE_RECOVERY             (1 << 31)
92 #define  PMC_SCRATCH0_MODE_BOOTLOADER           (1 << 30)
93 #define  PMC_SCRATCH0_MODE_RCM                  (1 << 1)
94 #define  PMC_SCRATCH0_MODE_MASK                 (PMC_SCRATCH0_MODE_RECOVERY | \
95                                                 PMC_SCRATCH0_MODE_BOOTLOADER | \
96                                                 PMC_SCRATCH0_MODE_RCM)
97
98 #define PMC_CPUPWRGOOD_TIMER            0x0c8
99 #define PMC_CPUPWROFF_TIMER             0x0cc
100
101 #define PMC_SCRATCH41                   0x140
102
103 #define PMC_SENSOR_CTRL                 0x1b0
104 #define PMC_SENSOR_CTRL_BLOCK_SCRATCH_WRITE     (1 << 2)
105 #define PMC_SENSOR_CTRL_ENABLE_RST              (1 << 1)
106 #define PMC_SENSOR_CTRL_ENABLE_PG               (1 << 0)
107
108 #define PMC_IO_DPD_REQ                  0x1b8
109 #define  PMC_IO_DPD_REQ_CODE_IDLE               (0 << 30)
110 #define  PMC_IO_DPD_REQ_CODE_OFF                (1 << 30)
111 #define  PMC_IO_DPD_REQ_CODE_ON                 (2 << 30)
112 #define  PMC_IO_DPD_REQ_CODE_MASK               (3 << 30)
113
114 #define PMC_IO_DPD_STATUS               0x1bc
115 #define  PMC_IO_DPD_STATUS_HDMI                 (1 << 28)
116 #define PMC_IO_DPD2_REQ                 0x1c0
117 #define PMC_IO_DPD2_STATUS              0x1c4
118 #define  PMC_IO_DPD2_STATUS_HV                  (1 << 6)
119 #define PMC_SEL_DPD_TIM                 0x1c8
120
121 #define PMC_SCRATCH54                   0x258
122 #define PMC_SCRATCH54_DATA_SHIFT                8
123 #define PMC_SCRATCH54_ADDR_SHIFT                0
124
125 #define PMC_SCRATCH55                   0x25c
126 #define PMC_SCRATCH55_RST_ENABLE                (1 << 31)
127 #define PMC_SCRATCH55_CNTRL_TYPE                (1 << 30)
128 #define PMC_SCRATCH55_CNTRL_ID_SHIFT            27
129 #define PMC_SCRATCH55_CNTRL_ID_MASK             0x07
130 #define PMC_SCRATCH55_PINMUX_SHIFT              24
131 #define PMC_SCRATCH55_PINMUX_MASK               0x07
132 #define PMC_SCRATCH55_CHECKSUM_SHIFT            16
133 #define PMC_SCRATCH55_CHECKSUM_MASK             0xFF
134 #define PMC_SCRATCH55_16BITOP                   (1 << 15)
135 #define PMC_SCRATCH55_I2CSLV1_SHIFT             0
136 #define PMC_SCRATCH55_I2CSLV1_MASK              0x7F
137
138 #define PMC_GPU_RG_CNTRL                0x2d4
139
140 /* Secure access */
141 #define PMC_SMC                         0xc2fffe00
142 #define PMC_SMC_READ                    0xaa
143 #define PMC_SMC_WRITE                   0xbb
144
145 #define PMC_LOCK(_sc)           mtx_lock(&(_sc)->mtx)
146 #define PMC_UNLOCK(_sc)         mtx_unlock(&(_sc)->mtx)
147 #define PMC_LOCK_INIT(_sc)      mtx_init(&(_sc)->mtx,                   \
148             device_get_nameunit(_sc->dev), "tegra210_pmc", MTX_DEF)
149 #define PMC_LOCK_DESTROY(_sc)   mtx_destroy(&(_sc)->mtx);
150 #define PMC_ASSERT_LOCKED(_sc)  mtx_assert(&(_sc)->mtx, MA_OWNED);
151 #define PMC_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
152
153 struct tegra210_pmc_softc {
154         device_t                dev;
155         struct resource         *mem_res;
156         clk_t                   clk;
157         struct mtx              mtx;
158         bool                    secure_access;
159
160         uint32_t                rate;
161         enum tegra_suspend_mode suspend_mode;
162         uint32_t                cpu_good_time;
163         uint32_t                cpu_off_time;
164         uint32_t                core_osc_time;
165         uint32_t                core_pmu_time;
166         uint32_t                core_off_time;
167         int                     corereq_high;
168         int                     sysclkreq_high;
169         int                     combined_req;
170         int                     cpu_pwr_good_en;
171         uint32_t                lp0_vec_phys;
172         uint32_t                lp0_vec_size;
173 };
174
175 static struct ofw_compat_data compat_data[] = {
176         {"nvidia,tegra210-pmc",         1},
177         {NULL,                          0},
178 };
179
180 static struct tegra210_pmc_softc *pmc_sc;
181
182 static inline struct tegra210_pmc_softc *
183 tegra210_pmc_get_sc(void)
184 {
185         if (pmc_sc == NULL)
186                 panic("To early call to Tegra PMC driver.\n");
187         return (pmc_sc);
188 }
189
190 static void
191 WR4(struct tegra210_pmc_softc *sc, bus_size_t r, uint32_t v)
192 {
193         struct arm_smccc_res res;
194
195         if (sc->secure_access) {
196                 arm_smccc_smc(PMC_SMC, PMC_SMC_WRITE, r, v, 0, 0, 0, 0, &res);
197                 if (res.a0 != 0)
198                         device_printf(sc->dev," PMC SMC write failed: %lu\n",
199                             res.a0);
200         }
201
202         bus_write_4(sc->mem_res, r, v);
203 }
204
205 static uint32_t
206 RD4(struct tegra210_pmc_softc *sc, bus_size_t r)
207 {
208         struct arm_smccc_res res;
209
210         if (sc->secure_access) {
211                 arm_smccc_smc(PMC_SMC, PMC_SMC_READ, r, 0, 0, 0, 0, 0, &res);
212                 if (res.a0 != 0)
213                         device_printf(sc->dev," PMC SMC write failed: %lu\n",
214                             res.a0);
215                 return((uint32_t)res.a1);
216         }
217
218         return(bus_read_4(sc->mem_res, r));
219 }
220
221 static int
222 tegra210_pmc_set_powergate(struct tegra210_pmc_softc *sc,
223     enum tegra_powergate_id id, int ena)
224 {
225         uint32_t reg;
226         int i;
227
228         PMC_LOCK(sc);
229
230         reg = RD4(sc, PMC_PWRGATE_STATUS) & PMC_PWRGATE_STATUS_PARTID(id);
231         if (((reg != 0) && ena) || ((reg == 0) && !ena)) {
232                 PMC_UNLOCK(sc);
233                 return (0);
234         }
235
236         for (i = 100; i > 0; i--) {
237                 reg = RD4(sc, PMC_PWRGATE_TOGGLE);
238                 if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
239                         break;
240                 DELAY(1);
241         }
242         if (i <= 0)
243                 device_printf(sc->dev,
244                     "Timeout when waiting for TOGGLE_START\n");
245
246         WR4(sc, PMC_PWRGATE_TOGGLE,
247             PMC_PWRGATE_TOGGLE_START | PMC_PWRGATE_TOGGLE_PARTID(id));
248
249         for (i = 100; i > 0; i--) {
250                 reg = RD4(sc, PMC_PWRGATE_TOGGLE);
251                 if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
252                         break;
253                 DELAY(1);
254         }
255         if (i <= 0)
256                 device_printf(sc->dev,
257                     "Timeout when waiting for TOGGLE_START\n");
258                 PMC_UNLOCK(sc);
259         return (0);
260 }
261
262 int
263 tegra_powergate_remove_clamping(enum tegra_powergate_id  id)
264 {
265         struct tegra210_pmc_softc *sc;
266         uint32_t reg;
267         enum tegra_powergate_id swid;
268         int i;
269
270         sc = tegra210_pmc_get_sc();
271
272         if (id == TEGRA_POWERGATE_3D) {
273                 WR4(sc, PMC_GPU_RG_CNTRL, 0);
274                 return (0);
275         }
276
277         reg = RD4(sc, PMC_PWRGATE_STATUS);
278         if ((reg & PMC_PWRGATE_STATUS_PARTID(id)) == 0)
279                 panic("Attempt to remove clamping for unpowered partition.\n");
280
281         if (id == TEGRA_POWERGATE_PCX)
282                 swid = TEGRA_POWERGATE_VDE;
283         else if (id == TEGRA_POWERGATE_VDE)
284                 swid = TEGRA_POWERGATE_PCX;
285         else
286                 swid = id;
287         WR4(sc, PMC_REMOVE_CLAMPING_CMD, PMC_REMOVE_CLAMPING_CMD_PARTID(swid));
288
289         for (i = 100; i > 0; i--) {
290                 reg = RD4(sc, PMC_REMOVE_CLAMPING_CMD);
291                 if ((reg & PMC_REMOVE_CLAMPING_CMD_PARTID(swid)) == 0)
292                         break;
293                 DELAY(1);
294         }
295         if (i <= 0)
296                 device_printf(sc->dev, "Timeout when remove clamping\n");
297
298         reg = RD4(sc, PMC_CLAMP_STATUS);
299         if ((reg & PMC_CLAMP_STATUS_PARTID(id)) != 0)
300                 panic("Cannot remove clamping\n");
301
302         return (0);
303 }
304
305 int
306 tegra_powergate_is_powered(enum tegra_powergate_id id)
307 {
308         struct tegra210_pmc_softc *sc;
309         uint32_t reg;
310
311         sc = tegra210_pmc_get_sc();
312
313         reg = RD4(sc, PMC_PWRGATE_STATUS);
314         return ((reg & PMC_PWRGATE_STATUS_PARTID(id)) ? 1 : 0);
315 }
316
317 int
318 tegra_powergate_power_on(enum tegra_powergate_id id)
319 {
320         struct tegra210_pmc_softc *sc;
321         int rv, i;
322
323         sc = tegra210_pmc_get_sc();
324
325         rv = tegra210_pmc_set_powergate(sc, id, 1);
326         if (rv != 0) {
327                 device_printf(sc->dev, "Cannot set powergate: %d\n", id);
328                 return (rv);
329         }
330
331         for (i = 100; i > 0; i--) {
332                 if (tegra_powergate_is_powered(id))
333                         break;
334                 DELAY(1);
335         }
336         if (i <= 0) {
337                 device_printf(sc->dev, "Timeout when waiting on power up\n");
338                 return(ETIMEDOUT);
339         }
340
341         return (rv);
342 }
343
344 int
345 tegra_powergate_power_off(enum tegra_powergate_id id)
346 {
347         struct tegra210_pmc_softc *sc;
348         int rv, i;
349
350         sc = tegra210_pmc_get_sc();
351
352         rv = tegra210_pmc_set_powergate(sc, id, 0);
353         if (rv != 0) {
354                 device_printf(sc->dev, "Cannot set powergate: %d\n", id);
355                 return (rv);
356         }
357         for (i = 100; i > 0; i--) {
358                 if (!tegra_powergate_is_powered(id))
359                         break;
360                 DELAY(1);
361         }
362         if (i <= 0)
363                 device_printf(sc->dev, "Timeout when waiting on power off\n");
364
365         return (rv);
366 }
367
368 int
369 tegra_powergate_sequence_power_up(enum tegra_powergate_id id, clk_t clk,
370     hwreset_t rst)
371 {
372         struct tegra210_pmc_softc *sc;
373         int rv;
374
375         sc = tegra210_pmc_get_sc();
376
377         rv = hwreset_assert(rst);
378         if (rv != 0) {
379                 device_printf(sc->dev, "Cannot assert reset\n");
380                 return (rv);
381         }
382
383         rv = clk_stop(clk);
384         if (rv != 0) {
385                 device_printf(sc->dev, "Cannot stop clock\n");
386                 goto clk_fail;
387         }
388
389         rv = tegra_powergate_power_on(id);
390         if (rv != 0) {
391                 device_printf(sc->dev, "Cannot power on powergate\n");
392                 goto clk_fail;
393         }
394
395         rv = clk_enable(clk);
396         if (rv != 0) {
397                 device_printf(sc->dev, "Cannot enable clock\n");
398                 goto clk_fail;
399         }
400         DELAY(20);
401
402         rv = tegra_powergate_remove_clamping(id);
403         if (rv != 0) {
404                 device_printf(sc->dev, "Cannot remove clamping\n");
405                 goto fail;
406         }
407         rv = hwreset_deassert(rst);
408         if (rv != 0) {
409                 device_printf(sc->dev, "Cannot unreset reset\n");
410                 goto fail;
411         }
412         return 0;
413
414 fail:
415         clk_disable(clk);
416 clk_fail:
417         hwreset_assert(rst);
418         tegra_powergate_power_off(id);
419         return (rv);
420 }
421
422 static int
423 tegra210_pmc_parse_fdt(struct tegra210_pmc_softc *sc, phandle_t node)
424 {
425         int rv;
426         uint32_t tmp;
427         uint32_t tmparr[2];
428
429         rv = OF_getencprop(node, "nvidia,suspend-mode", &tmp, sizeof(tmp));
430         if (rv > 0) {
431                 switch (tmp) {
432                 case 0:
433                         sc->suspend_mode = TEGRA_SUSPEND_LP0;
434                         break;
435
436                 case 1:
437                         sc->suspend_mode = TEGRA_SUSPEND_LP1;
438                         break;
439
440                 case 2:
441                         sc->suspend_mode = TEGRA_SUSPEND_LP2;
442                         break;
443
444                 default:
445                         sc->suspend_mode = TEGRA_SUSPEND_NONE;
446                         break;
447                 }
448         }
449
450         rv = OF_getencprop(node, "nvidia,cpu-pwr-good-time", &tmp, sizeof(tmp));
451         if (rv > 0) {
452                 sc->cpu_good_time = tmp;
453                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
454         }
455
456         rv = OF_getencprop(node, "nvidia,cpu-pwr-off-time", &tmp, sizeof(tmp));
457         if (rv > 0) {
458                 sc->cpu_off_time = tmp;
459                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
460         }
461
462         rv = OF_getencprop(node, "nvidia,core-pwr-good-time", tmparr,
463             sizeof(tmparr));
464         if (rv == sizeof(tmparr)) {
465                 sc->core_osc_time = tmparr[0];
466                 sc->core_pmu_time = tmparr[1];
467                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
468         }
469
470         rv = OF_getencprop(node, "nvidia,core-pwr-off-time", &tmp, sizeof(tmp));
471         if (rv > 0) {
472                 sc->core_off_time = tmp;
473                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
474         }
475
476         sc->corereq_high =
477             OF_hasprop(node, "nvidia,core-power-req-active-high");
478         sc->sysclkreq_high =
479             OF_hasprop(node, "nvidia,sys-clock-req-active-high");
480         sc->combined_req =
481             OF_hasprop(node, "nvidia,combined-power-req");
482         sc->cpu_pwr_good_en =
483             OF_hasprop(node, "nvidia,cpu-pwr-good-en");
484
485         rv = OF_getencprop(node, "nvidia,lp0-vec", tmparr, sizeof(tmparr));
486         if (rv == sizeof(tmparr)) {
487
488                 sc->lp0_vec_phys = tmparr[0];
489                 sc->core_pmu_time = tmparr[1];
490                 sc->lp0_vec_size = TEGRA_SUSPEND_NONE;
491                 if (sc->suspend_mode == TEGRA_SUSPEND_LP0)
492                         sc->suspend_mode = TEGRA_SUSPEND_LP1;
493         }
494         return 0;
495 }
496
497 static void
498 tegra210_pmc_check_secure(struct tegra210_pmc_softc *sc)
499 {
500         uint32_t orig;
501
502         sc->secure_access = false;
503
504         /*
505          * If PMC is coverd by secure trust zone, all reads returns 0,
506          * Use scratch0 register acvcess test
507          */
508         orig = RD4(sc, PMC_SCRATCH0);
509         WR4(sc, PMC_SCRATCH0, 0xDEADBEEF);
510         if (RD4(sc, PMC_SCRATCH0) == 0) {
511                 sc->secure_access = true;
512                 return;
513         }
514         WR4(sc, PMC_SCRATCH0, 0xBADC0DE);
515         if (RD4(sc, PMC_SCRATCH0) == 0) {
516                 sc->secure_access = true;
517                 return;
518         }
519         WR4(sc, PMC_SCRATCH0, orig);
520 }
521
522 static int
523 tegra210_pmc_probe(device_t dev)
524 {
525
526         if (!ofw_bus_status_okay(dev))
527                 return (ENXIO);
528
529         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
530                 return (ENXIO);
531
532         device_set_desc(dev, "Tegra PMC");
533         return (BUS_PROBE_DEFAULT);
534 }
535
536 static int
537 tegra210_pmc_detach(device_t dev)
538 {
539
540         /* This device is always present. */
541         return (EBUSY);
542 }
543
544 static int
545 tegra210_pmc_attach(device_t dev)
546 {
547         struct tegra210_pmc_softc *sc;
548         int rid, rv;
549         uint32_t reg;
550         phandle_t node;
551
552         sc = device_get_softc(dev);
553         sc->dev = dev;
554         node = ofw_bus_get_node(dev);
555         PMC_LOCK_INIT(sc);
556
557         rv = tegra210_pmc_parse_fdt(sc, node);
558         if (rv != 0) {
559                 device_printf(sc->dev, "Cannot parse FDT data\n");
560                 return (rv);
561         }
562
563         rv = clk_get_by_ofw_name(sc->dev, 0, "pclk", &sc->clk);
564         if (rv != 0) {
565                 device_printf(sc->dev, "Cannot get \"pclk\" clock\n");
566                 return (ENXIO);
567         }
568
569         rid = 0;
570         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
571             RF_ACTIVE);
572         if (sc->mem_res == NULL) {
573                 device_printf(dev, "Cannot allocate memory resources\n");
574                 return (ENXIO);
575         }
576
577         tegra210_pmc_check_secure(sc);
578
579         /* Enable CPU power request. */
580         reg = RD4(sc, PMC_CNTRL);
581         reg |= PMC_CNTRL_CPU_PWRREQ_OE;
582         WR4(sc, PMC_CNTRL, reg);
583
584         /* Set sysclk output polarity */
585         reg = RD4(sc, PMC_CNTRL);
586         if (sc->sysclkreq_high)
587                 reg &= ~PMC_CNTRL_SYSCLK_POLARITY;
588         else
589                 reg |= PMC_CNTRL_SYSCLK_POLARITY;
590         WR4(sc, PMC_CNTRL, reg);
591
592         /* Enable sysclk request. */
593         reg = RD4(sc, PMC_CNTRL);
594         reg |= PMC_CNTRL_SYSCLK_OE;
595         WR4(sc, PMC_CNTRL, reg);
596
597         /*
598          * Remove HDMI from deep power down mode.
599          * XXX mote this to HDMI driver
600          */
601         reg = RD4(sc, PMC_IO_DPD_STATUS);
602         reg &= ~ PMC_IO_DPD_STATUS_HDMI;
603         WR4(sc, PMC_IO_DPD_STATUS, reg);
604
605         reg = RD4(sc, PMC_IO_DPD2_STATUS);
606         reg &= ~ PMC_IO_DPD2_STATUS_HV;
607         WR4(sc, PMC_IO_DPD2_STATUS, reg);
608
609         if (pmc_sc != NULL)
610                 panic("tegra210_pmc: double driver attach");
611         pmc_sc = sc;
612         return (0);
613 }
614
615 static device_method_t tegra210_pmc_methods[] = {
616         /* Device interface */
617         DEVMETHOD(device_probe,         tegra210_pmc_probe),
618         DEVMETHOD(device_attach,        tegra210_pmc_attach),
619         DEVMETHOD(device_detach,        tegra210_pmc_detach),
620
621         DEVMETHOD_END
622 };
623
624 static DEFINE_CLASS_0(pmc, tegra210_pmc_driver, tegra210_pmc_methods,
625     sizeof(struct tegra210_pmc_softc));
626 EARLY_DRIVER_MODULE(tegra210_pmc, simplebus, tegra210_pmc_driver, NULL, NULL,
627     70);