soc/tegra: pmc: Add wake event support on Tegra210
This patch implements PMC wakeup sequence for Tegra210 and defines the commonly used RTC alarm wake event. Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
aba19827fc
commit
7e9ae849eb
|
@ -58,6 +58,11 @@
|
|||
#define PMC_CNTRL_SYSCLK_POLARITY BIT(10) /* sys clk polarity */
|
||||
#define PMC_CNTRL_MAIN_RST BIT(4)
|
||||
|
||||
#define PMC_WAKE_MASK 0x0c
|
||||
#define PMC_WAKE_LEVEL 0x10
|
||||
#define PMC_WAKE_STATUS 0x14
|
||||
#define PMC_SW_WAKE_STATUS 0x18
|
||||
|
||||
#define DPD_SAMPLE 0x020
|
||||
#define DPD_SAMPLE_ENABLE BIT(0)
|
||||
#define DPD_SAMPLE_DISABLE (0 << 0)
|
||||
|
@ -87,6 +92,11 @@
|
|||
|
||||
#define PMC_SCRATCH41 0x140
|
||||
|
||||
#define PMC_WAKE2_MASK 0x160
|
||||
#define PMC_WAKE2_LEVEL 0x164
|
||||
#define PMC_WAKE2_STATUS 0x168
|
||||
#define PMC_SW_WAKE2_STATUS 0x16c
|
||||
|
||||
#define PMC_SENSOR_CTRL 0x1b0
|
||||
#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
|
||||
#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
|
||||
|
@ -1948,6 +1958,86 @@ static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
|
|||
.alloc = tegra_pmc_irq_alloc,
|
||||
};
|
||||
|
||||
static int tegra210_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
|
||||
{
|
||||
struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
|
||||
unsigned int offset, bit;
|
||||
u32 value;
|
||||
|
||||
if (data->hwirq == ULONG_MAX)
|
||||
return 0;
|
||||
|
||||
offset = data->hwirq / 32;
|
||||
bit = data->hwirq % 32;
|
||||
|
||||
/* clear wake status */
|
||||
tegra_pmc_writel(pmc, 0, PMC_SW_WAKE_STATUS);
|
||||
tegra_pmc_writel(pmc, 0, PMC_SW_WAKE2_STATUS);
|
||||
|
||||
tegra_pmc_writel(pmc, 0, PMC_WAKE_STATUS);
|
||||
tegra_pmc_writel(pmc, 0, PMC_WAKE2_STATUS);
|
||||
|
||||
/* enable PMC wake */
|
||||
if (data->hwirq >= 32)
|
||||
offset = PMC_WAKE2_MASK;
|
||||
else
|
||||
offset = PMC_WAKE_MASK;
|
||||
|
||||
value = tegra_pmc_readl(pmc, offset);
|
||||
|
||||
if (on)
|
||||
value |= BIT(bit);
|
||||
else
|
||||
value &= ~BIT(bit);
|
||||
|
||||
tegra_pmc_writel(pmc, value, offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
|
||||
{
|
||||
struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
|
||||
unsigned int offset, bit;
|
||||
u32 value;
|
||||
|
||||
if (data->hwirq == ULONG_MAX)
|
||||
return 0;
|
||||
|
||||
offset = data->hwirq / 32;
|
||||
bit = data->hwirq % 32;
|
||||
|
||||
if (data->hwirq >= 32)
|
||||
offset = PMC_WAKE2_LEVEL;
|
||||
else
|
||||
offset = PMC_WAKE_LEVEL;
|
||||
|
||||
value = tegra_pmc_readl(pmc, offset);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
value |= BIT(bit);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
value &= ~BIT(bit);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
|
||||
value ^= BIT(bit);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tegra_pmc_writel(pmc, value, offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
|
||||
{
|
||||
struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
|
||||
|
@ -2566,6 +2656,10 @@ static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
|
|||
TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
|
||||
};
|
||||
|
||||
static const struct tegra_wake_event tegra210_wake_events[] = {
|
||||
TEGRA_WAKE_IRQ("rtc", 16, 2),
|
||||
};
|
||||
|
||||
static const struct tegra_pmc_soc tegra210_pmc_soc = {
|
||||
.num_powergates = ARRAY_SIZE(tegra210_powergates),
|
||||
.powergates = tegra210_powergates,
|
||||
|
@ -2583,10 +2677,14 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
|
|||
.regs = &tegra20_pmc_regs,
|
||||
.init = tegra20_pmc_init,
|
||||
.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
|
||||
.irq_set_wake = tegra210_pmc_irq_set_wake,
|
||||
.irq_set_type = tegra210_pmc_irq_set_type,
|
||||
.reset_sources = tegra210_reset_sources,
|
||||
.num_reset_sources = ARRAY_SIZE(tegra210_reset_sources),
|
||||
.reset_levels = NULL,
|
||||
.num_reset_levels = 0,
|
||||
.num_wake_events = ARRAY_SIZE(tegra210_wake_events),
|
||||
.wake_events = tegra210_wake_events,
|
||||
};
|
||||
|
||||
#define TEGRA186_IO_PAD_TABLE(_pad) \
|
||||
|
|
Loading…
Reference in a new issue