xref: /aosp_15_r20/external/coreboot/src/soc/nvidia/tegra210/power.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <assert.h>
5 #include <console/console.h>
6 #include <soc/addressmap.h>
7 #include <soc/pmc.h>
8 #include <soc/power.h>
9 
10 static struct tegra_pmc_regs *const pmc = (void *)TEGRA_PMC_BASE;
11 
12 enum {
13 	POWER_GATE = 0,
14 	POWER_UNGATE = 1,
15 };
16 
partition_powered(int id)17 static int partition_powered(int id)
18 {
19 	if (read32(&pmc->pwrgate_status) & (0x1 << id))
20 		return POWER_UNGATE;
21 
22 	return POWER_GATE;
23 }
24 
25 static const char *const power_gate_string[] = {
26 	[POWER_GATE] = "Gat",
27 	[POWER_UNGATE] = "Ungat",
28 };
29 
power_gate_toggle_request(uint32_t id,int request)30 static void power_gate_toggle_request(uint32_t id, int request)
31 {
32 	printk(BIOS_INFO, "%sing power partition %d.\n",
33 	       power_gate_string[request], id);
34 
35 	int part_powered = partition_powered(id);
36 
37 	if (request == part_powered) {
38 		printk(BIOS_INFO, "Partition %d already %sed.\n", id,
39 		       power_gate_string[request]);
40 		return;
41 	}
42 
43 	uint32_t pwrgate_toggle = read32(&pmc->pwrgate_toggle);
44 	pwrgate_toggle &= ~(PMC_PWRGATE_TOGGLE_PARTID_MASK);
45 	pwrgate_toggle |= (id << PMC_PWRGATE_TOGGLE_PARTID_SHIFT);
46 	pwrgate_toggle |= PMC_PWRGATE_TOGGLE_START;
47 	write32(&pmc->pwrgate_toggle, pwrgate_toggle);
48 
49 	// Wait for the request to be accepted.
50 	while (read32(&pmc->pwrgate_toggle) & PMC_PWRGATE_TOGGLE_START)
51 		;
52 	printk(BIOS_INFO, "Power gate toggle request accepted.\n");
53 
54 	while (1) {
55 		part_powered = partition_powered(id);
56 		if (request == part_powered) {
57 			printk(BIOS_INFO, "Partition %d %sed.\n", id,
58 			       power_gate_string[request]);
59 			return;
60 		}
61 	}
62 }
63 
power_gate_partition(uint32_t id)64 void power_gate_partition(uint32_t id)
65 {
66 	power_gate_toggle_request(id, POWER_GATE);
67 }
68 
power_ungate_partition(uint32_t id)69 void power_ungate_partition(uint32_t id)
70 {
71 	power_gate_toggle_request(id, POWER_UNGATE);
72 }
73 
pmc_rst_status(void)74 uint8_t pmc_rst_status(void)
75 {
76 	return read32(&pmc->rst_status) & PMC_RST_STATUS_SOURCE_MASK;
77 }
78 
79 static const char *pmc_rst_status_str[PMC_RST_STATUS_NUM_SOURCES] = {
80 	[PMC_RST_STATUS_SOURCE_POR] = "POR",
81 	[PMC_RST_STATUS_SOURCE_WATCHDOG] = "Watchdog",
82 	[PMC_RST_STATUS_SOURCE_SENSOR] = "Sensor",
83 	[PMC_RST_STATUS_SOURCE_SW_MAIN] = "SW Main",
84 	[PMC_RST_STATUS_SOURCE_LP0] = "LP0",
85 };
86 
pmc_print_rst_status(void)87 void pmc_print_rst_status(void)
88 {
89 	uint8_t rst_status = pmc_rst_status();
90 	assert(rst_status < PMC_RST_STATUS_NUM_SOURCES);
91 	printk(BIOS_INFO, "PMC Reset Status: %s\n",
92 	       pmc_rst_status_str[rst_status]);
93 }
94 
partition_clamp_on(int id)95 static int partition_clamp_on(int id)
96 {
97 	return read32(&pmc->clamp_status) & (1 << id);
98 }
99 
remove_clamps(int id)100 void remove_clamps(int id)
101 {
102 	if (!partition_clamp_on(id))
103 		return;
104 
105 	/* Remove clamp */
106 	write32(&pmc->remove_clamping_cmd, (1 << id));
107 
108 	/* Wait for clamp off */
109 	while (partition_clamp_on(id))
110 		;
111 }
112 
pmc_override_pwr_det(uint32_t bits,uint32_t override)113 void pmc_override_pwr_det(uint32_t bits, uint32_t override)
114 {
115 	uint32_t val = read32(&pmc->pwr_det_val);
116 	val &= ~bits;
117 	val |= (override & bits);
118 	write32(&pmc->pwr_det_val, val);
119 }
120