lkml.org 
[lkml]   [2019]   [Jul]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 15/20] soc/tegra: pmc: Add pmc wake support for tegra210
    Date
    This patch implements PMC wakeup sequence for Tegra210 and defines
    common used RTC alarm wake event.

    Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
    ---
    drivers/soc/tegra/pmc.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 98 insertions(+)

    diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
    index 91c84d0e66ae..3aa71c28a10a 100644
    --- a/drivers/soc/tegra/pmc.c
    +++ b/drivers/soc/tegra/pmc.c
    @@ -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)
    @@ -1922,6 +1932,43 @@ 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 |= 1 << bit;
    + else
    + value &= ~(1 << bit);
    +
    + 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);
    @@ -1954,6 +2001,49 @@ static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
    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 |= 1 << bit;
    + break;
    +
    + case IRQ_TYPE_EDGE_FALLING:
    + case IRQ_TYPE_LEVEL_LOW:
    + value &= ~(1 << bit);
    + break;
    +
    + case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
    + value ^= 1 << bit;
    + break;
    +
    + default:
    + return -EINVAL;
    + }
    +
    + tegra_pmc_writel(pmc, value, offset);
    +
    + return 0;
    +}
    +
    static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
    {
    struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
    @@ -2540,6 +2630,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,
    @@ -2557,10 +2651,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) \
    --
    2.7.4
    \
     
     \ /
      Last update: 2019-07-31 23:14    [W:4.209 / U:0.796 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site