Skip to content

Commit 5f84bb1

Browse files
Sandipan Patrathierryreding
authored andcommitted
soc/tegra: pmc: Add sysfs entries for reset info
Implement read-only reset_reason and reset_level sysfs attributes that can be used to query the reset reason and level at runtime. Signed-off-by: Sandipan Patra <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 3bb2f84 commit 5f84bb1

File tree

1 file changed

+128
-1
lines changed

1 file changed

+128
-1
lines changed

drivers/soc/tegra/pmc.c

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* drivers/soc/tegra/pmc.c
33
*
44
* Copyright (c) 2010 Google, Inc
5+
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
56
*
67
* Author:
78
* Colin Cross <[email protected]>
@@ -92,7 +93,6 @@
9293
#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
9394
#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
9495

95-
#define PMC_RST_STATUS 0x1b4
9696
#define PMC_RST_STATUS_POR 0
9797
#define PMC_RST_STATUS_WATCHDOG 1
9898
#define PMC_RST_STATUS_SENSOR 2
@@ -151,6 +151,11 @@ struct tegra_pmc_regs {
151151
unsigned int dpd_status;
152152
unsigned int dpd2_req;
153153
unsigned int dpd2_status;
154+
unsigned int rst_status;
155+
unsigned int rst_source_shift;
156+
unsigned int rst_source_mask;
157+
unsigned int rst_level_shift;
158+
unsigned int rst_level_mask;
154159
};
155160

156161
struct tegra_pmc_soc {
@@ -175,6 +180,42 @@ struct tegra_pmc_soc {
175180
void (*setup_irq_polarity)(struct tegra_pmc *pmc,
176181
struct device_node *np,
177182
bool invert);
183+
184+
const char * const *reset_sources;
185+
unsigned int num_reset_sources;
186+
const char * const *reset_levels;
187+
unsigned int num_reset_levels;
188+
};
189+
190+
static const char * const tegra186_reset_sources[] = {
191+
"SYS_RESET",
192+
"AOWDT",
193+
"MCCPLEXWDT",
194+
"BPMPWDT",
195+
"SCEWDT",
196+
"SPEWDT",
197+
"APEWDT",
198+
"BCCPLEXWDT",
199+
"SENSOR",
200+
"AOTAG",
201+
"VFSENSOR",
202+
"SWREST",
203+
"SC7",
204+
"HSM",
205+
"CORESIGHT"
206+
};
207+
208+
static const char * const tegra186_reset_levels[] = {
209+
"L0", "L1", "L2", "WARM"
210+
};
211+
212+
static const char * const tegra30_reset_sources[] = {
213+
"POWER_ON_RESET",
214+
"WATCHDOG",
215+
"SENSOR",
216+
"SW_MAIN",
217+
"LP0",
218+
"AOTAG"
178219
};
179220

180221
/**
@@ -1527,6 +1568,56 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
15271568
return err;
15281569
}
15291570

1571+
static ssize_t reset_reason_show(struct device *dev,
1572+
struct device_attribute *attr, char *buf)
1573+
{
1574+
u32 value, rst_src;
1575+
1576+
value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1577+
rst_src = (value & pmc->soc->regs->rst_source_mask) >>
1578+
pmc->soc->regs->rst_source_shift;
1579+
1580+
return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
1581+
}
1582+
1583+
static DEVICE_ATTR_RO(reset_reason);
1584+
1585+
static ssize_t reset_level_show(struct device *dev,
1586+
struct device_attribute *attr, char *buf)
1587+
{
1588+
u32 value, rst_lvl;
1589+
1590+
value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1591+
rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
1592+
pmc->soc->regs->rst_level_shift;
1593+
1594+
return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
1595+
}
1596+
1597+
static DEVICE_ATTR_RO(reset_level);
1598+
1599+
static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
1600+
{
1601+
struct device *dev = pmc->dev;
1602+
int err = 0;
1603+
1604+
if (pmc->soc->reset_sources) {
1605+
err = device_create_file(dev, &dev_attr_reset_reason);
1606+
if (err < 0)
1607+
dev_warn(dev,
1608+
"failed to create attr \"reset_reason\": %d\n",
1609+
err);
1610+
}
1611+
1612+
if (pmc->soc->reset_levels) {
1613+
err = device_create_file(dev, &dev_attr_reset_level);
1614+
if (err < 0)
1615+
dev_warn(dev,
1616+
"failed to create attr \"reset_level\": %d\n",
1617+
err);
1618+
}
1619+
}
1620+
15301621
static int tegra_pmc_probe(struct platform_device *pdev)
15311622
{
15321623
void __iomem *base;
@@ -1596,6 +1687,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
15961687

15971688
tegra_pmc_init_tsense_reset(pmc);
15981689

1690+
tegra_pmc_reset_sysfs_init(pmc);
1691+
15991692
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
16001693
err = tegra_powergate_debugfs_init();
16011694
if (err < 0)
@@ -1662,6 +1755,11 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
16621755
.dpd_status = 0x1bc,
16631756
.dpd2_req = 0x1c0,
16641757
.dpd2_status = 0x1c4,
1758+
.rst_status = 0x1b4,
1759+
.rst_source_shift = 0x0,
1760+
.rst_source_mask = 0x7,
1761+
.rst_level_shift = 0x0,
1762+
.rst_level_mask = 0x0,
16651763
};
16661764

16671765
static void tegra20_pmc_init(struct tegra_pmc *pmc)
@@ -1719,6 +1817,10 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
17191817
.regs = &tegra20_pmc_regs,
17201818
.init = tegra20_pmc_init,
17211819
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
1820+
.reset_sources = NULL,
1821+
.num_reset_sources = 0,
1822+
.reset_levels = NULL,
1823+
.num_reset_levels = 0,
17221824
};
17231825

17241826
static const char * const tegra30_powergates[] = {
@@ -1760,6 +1862,10 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
17601862
.regs = &tegra20_pmc_regs,
17611863
.init = tegra20_pmc_init,
17621864
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
1865+
.reset_sources = tegra30_reset_sources,
1866+
.num_reset_sources = 5,
1867+
.reset_levels = NULL,
1868+
.num_reset_levels = 0,
17631869
};
17641870

17651871
static const char * const tegra114_powergates[] = {
@@ -1805,6 +1911,10 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
18051911
.regs = &tegra20_pmc_regs,
18061912
.init = tegra20_pmc_init,
18071913
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
1914+
.reset_sources = tegra30_reset_sources,
1915+
.num_reset_sources = 5,
1916+
.reset_levels = NULL,
1917+
.num_reset_levels = 0,
18081918
};
18091919

18101920
static const char * const tegra124_powergates[] = {
@@ -1910,6 +2020,10 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
19102020
.regs = &tegra20_pmc_regs,
19112021
.init = tegra20_pmc_init,
19122022
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2023+
.reset_sources = tegra30_reset_sources,
2024+
.num_reset_sources = 5,
2025+
.reset_levels = NULL,
2026+
.num_reset_levels = 0,
19132027
};
19142028

19152029
static const char * const tegra210_powergates[] = {
@@ -2011,6 +2125,10 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
20112125
.regs = &tegra20_pmc_regs,
20122126
.init = tegra20_pmc_init,
20132127
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2128+
.reset_sources = tegra30_reset_sources,
2129+
.num_reset_sources = 5,
2130+
.reset_levels = NULL,
2131+
.num_reset_levels = 0,
20142132
};
20152133

20162134
#define TEGRA186_IO_PAD_TABLE(_pad) \
@@ -2068,6 +2186,11 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = {
20682186
.dpd_status = 0x78,
20692187
.dpd2_req = 0x7c,
20702188
.dpd2_status = 0x80,
2189+
.rst_status = 0x70,
2190+
.rst_source_shift = 0x2,
2191+
.rst_source_mask = 0x3C,
2192+
.rst_level_shift = 0x0,
2193+
.rst_level_mask = 0x3,
20712194
};
20722195

20732196
static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
@@ -2120,6 +2243,10 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
21202243
.regs = &tegra186_pmc_regs,
21212244
.init = NULL,
21222245
.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
2246+
.reset_sources = tegra186_reset_sources,
2247+
.num_reset_sources = 14,
2248+
.reset_levels = tegra186_reset_levels,
2249+
.num_reset_levels = 3,
21232250
};
21242251

21252252
static const struct of_device_id tegra_pmc_match[] = {

0 commit comments

Comments
 (0)