blob: 4968c851209971eaa27544c3213a35e747cab546 [file] [log] [blame]
Angel Ponsa2ee7612020-04-04 18:51:15 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Georgi40a3e322015-06-22 19:41:29 +02002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02004#include <assert.h>
5#include <console/console.h>
6#include <soc/addressmap.h>
7#include <soc/pmc.h>
8#include <soc/power.h>
9
10static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE;
11
12enum {
13 POWER_GATE = 0,
14 POWER_UNGATE = 1,
15};
16
17static 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
Elyes HAOUAS39303d52018-07-08 12:40:45 +020025static const char *const power_gate_string[] = {
Patrick Georgi40a3e322015-06-22 19:41:29 +020026 [POWER_GATE] = "Gat",
27 [POWER_UNGATE] = "Ungat",
28};
29
30static 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
64void power_gate_partition(uint32_t id)
65{
66 power_gate_toggle_request(id, POWER_GATE);
67}
68
69void power_ungate_partition(uint32_t id)
70{
71 power_gate_toggle_request(id, POWER_UNGATE);
72}
73
74uint8_t pmc_rst_status(void)
75{
76 return read32(&pmc->rst_status) & PMC_RST_STATUS_SOURCE_MASK;
77}
78
79static 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
87void 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
95static int partition_clamp_on(int id)
96{
97 return read32(&pmc->clamp_status) & (1 << id);
98}
99
100void 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
113void 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}