2
2
* drivers/soc/tegra/pmc.c
3
3
*
4
4
* Copyright (c) 2010 Google, Inc
5
+ * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
5
6
*
6
7
* Author:
7
8
92
93
#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
93
94
#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
94
95
95
- #define PMC_RST_STATUS 0x1b4
96
96
#define PMC_RST_STATUS_POR 0
97
97
#define PMC_RST_STATUS_WATCHDOG 1
98
98
#define PMC_RST_STATUS_SENSOR 2
@@ -151,6 +151,11 @@ struct tegra_pmc_regs {
151
151
unsigned int dpd_status ;
152
152
unsigned int dpd2_req ;
153
153
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 ;
154
159
};
155
160
156
161
struct tegra_pmc_soc {
@@ -175,6 +180,42 @@ struct tegra_pmc_soc {
175
180
void (* setup_irq_polarity )(struct tegra_pmc * pmc ,
176
181
struct device_node * np ,
177
182
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"
178
219
};
179
220
180
221
/**
@@ -1527,6 +1568,56 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1527
1568
return err ;
1528
1569
}
1529
1570
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
+
1530
1621
static int tegra_pmc_probe (struct platform_device * pdev )
1531
1622
{
1532
1623
void __iomem * base ;
@@ -1596,6 +1687,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1596
1687
1597
1688
tegra_pmc_init_tsense_reset (pmc );
1598
1689
1690
+ tegra_pmc_reset_sysfs_init (pmc );
1691
+
1599
1692
if (IS_ENABLED (CONFIG_DEBUG_FS )) {
1600
1693
err = tegra_powergate_debugfs_init ();
1601
1694
if (err < 0 )
@@ -1662,6 +1755,11 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
1662
1755
.dpd_status = 0x1bc ,
1663
1756
.dpd2_req = 0x1c0 ,
1664
1757
.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 ,
1665
1763
};
1666
1764
1667
1765
static void tegra20_pmc_init (struct tegra_pmc * pmc )
@@ -1719,6 +1817,10 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
1719
1817
.regs = & tegra20_pmc_regs ,
1720
1818
.init = tegra20_pmc_init ,
1721
1819
.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 ,
1722
1824
};
1723
1825
1724
1826
static const char * const tegra30_powergates [] = {
@@ -1760,6 +1862,10 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
1760
1862
.regs = & tegra20_pmc_regs ,
1761
1863
.init = tegra20_pmc_init ,
1762
1864
.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 ,
1763
1869
};
1764
1870
1765
1871
static const char * const tegra114_powergates [] = {
@@ -1805,6 +1911,10 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
1805
1911
.regs = & tegra20_pmc_regs ,
1806
1912
.init = tegra20_pmc_init ,
1807
1913
.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 ,
1808
1918
};
1809
1919
1810
1920
static const char * const tegra124_powergates [] = {
@@ -1910,6 +2020,10 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
1910
2020
.regs = & tegra20_pmc_regs ,
1911
2021
.init = tegra20_pmc_init ,
1912
2022
.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 ,
1913
2027
};
1914
2028
1915
2029
static const char * const tegra210_powergates [] = {
@@ -2011,6 +2125,10 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
2011
2125
.regs = & tegra20_pmc_regs ,
2012
2126
.init = tegra20_pmc_init ,
2013
2127
.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 ,
2014
2132
};
2015
2133
2016
2134
#define TEGRA186_IO_PAD_TABLE (_pad ) \
@@ -2068,6 +2186,11 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = {
2068
2186
.dpd_status = 0x78 ,
2069
2187
.dpd2_req = 0x7c ,
2070
2188
.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 ,
2071
2194
};
2072
2195
2073
2196
static void tegra186_pmc_setup_irq_polarity (struct tegra_pmc * pmc ,
@@ -2120,6 +2243,10 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
2120
2243
.regs = & tegra186_pmc_regs ,
2121
2244
.init = NULL ,
2122
2245
.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 ,
2123
2250
};
2124
2251
2125
2252
static const struct of_device_id tegra_pmc_match [] = {
0 commit comments