Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

soc/tegra: pmc: Process wake events during resume

During system resume, translate tier2 SC7 wake sources back into IRQs
and do generic_handle_irq() to invoke the interrupt handlers for edge
triggered wake events such as SW-wake.

Signed-off-by: Prathamesh Shete <pshete@nvidia.com>
Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Petlozu Pravareshwar and committed by
Thierry Reding
0474cc84 1ddb8f6d

+41
+41
drivers/soc/tegra/pmc.c
··· 23 23 #include <linux/err.h> 24 24 #include <linux/export.h> 25 25 #include <linux/init.h> 26 + #include <linux/interrupt.h> 26 27 #include <linux/io.h> 27 28 #include <linux/iopoll.h> 28 29 #include <linux/irqdomain.h> ··· 3148 3147 } 3149 3148 } 3150 3149 3150 + /* translate sc7 wake sources back into IRQs to catch edge triggered wakeups */ 3151 + static void tegra186_pmc_process_wake_events(struct tegra_pmc *pmc, unsigned int index, 3152 + unsigned long status) 3153 + { 3154 + unsigned int wake; 3155 + 3156 + dev_dbg(pmc->dev, "Wake[%d:%d] status=%#lx\n", (index * 32) + 31, index * 32, status); 3157 + 3158 + for_each_set_bit(wake, &status, 32) { 3159 + irq_hw_number_t hwirq = wake + 32 * index; 3160 + struct irq_desc *desc; 3161 + unsigned int irq; 3162 + 3163 + irq = irq_find_mapping(pmc->domain, hwirq); 3164 + 3165 + desc = irq_to_desc(irq); 3166 + if (!desc || !desc->action || !desc->action->name) { 3167 + dev_dbg(pmc->dev, "Resume caused by WAKE%ld, IRQ %d\n", hwirq, irq); 3168 + continue; 3169 + } 3170 + 3171 + dev_dbg(pmc->dev, "Resume caused by WAKE%ld, %s\n", hwirq, desc->action->name); 3172 + generic_handle_irq(irq); 3173 + } 3174 + } 3175 + 3176 + static void tegra186_pmc_wake_syscore_resume(void) 3177 + { 3178 + u32 status, mask; 3179 + unsigned int i; 3180 + 3181 + for (i = 0; i < pmc->soc->max_wake_vectors; i++) { 3182 + mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); 3183 + status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; 3184 + 3185 + tegra186_pmc_process_wake_events(pmc, i, status); 3186 + } 3187 + } 3188 + 3151 3189 static int tegra186_pmc_wake_syscore_suspend(void) 3152 3190 { 3153 3191 wke_read_sw_wake_status(pmc); ··· 3852 3812 static void tegra186_pmc_init(struct tegra_pmc *pmc) 3853 3813 { 3854 3814 pmc->syscore.suspend = tegra186_pmc_wake_syscore_suspend; 3815 + pmc->syscore.resume = tegra186_pmc_wake_syscore_resume; 3855 3816 3856 3817 register_syscore_ops(&pmc->syscore); 3857 3818 }