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