Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp240182iob; Wed, 18 May 2022 00:50:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzIlhT5waUKgXtPJhApAkgJw8xdGNfZLxtyJtUuQKrw0jwPZKXGr0pVrePnsRt92MVc282F X-Received: by 2002:a17:903:22d1:b0:161:ac9e:60bc with SMTP id y17-20020a17090322d100b00161ac9e60bcmr6101407plg.13.1652860221355; Wed, 18 May 2022 00:50:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652860221; cv=none; d=google.com; s=arc-20160816; b=GNm97yEKkWMgqwu1rJ7CEKtzhY7PMYMFDQ/ME7kuLeDdEpwWn/gg1/iASmTjKkyvqR Ah76iPoL5irAWCvYX4zPI8adYMCc/diqD/c8iJw2iB5HAzzkri/toh9gYLoItPEQb9Co sdrvkEGN0tGWWVbWv/pMWMzVJy5EriUazU+pqHEGwnbSRCoQSrj96OPiAY44iZgPzgk8 Mbay/AXTZPrynhhIx7lsYlNV9cNM3znzHF/f7uoQnLqFBlhcxjECdDIIy4XLHyHDGOvs BwuGRnPdtOR0RTG2b9Pcnz08lX6ryT9FpqrICimHf5hU/0ZUMFy/hqAyQEYP3m32rDJi tPWg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=YXZfjMQjUYv74UOxyPEdQftsBYoYCO06rHvgPycGMF8=; b=fhh0+nqX1xUdp+dUKvkxjmYY8XLHC0jxRO8RT6ErbovJAexecQGwcpcQxtuozeKJe8 utmKq6iU7A8SzoW5lxnQ52Up8AFAURMO0xXtkDBieCD8OYTLEgl0v0swoBpBIpwBA4nv fcv2TWo98N9ruTPblEM1jYjaEkY9OcFb298+QWG0ipY8KVw7TznGfT3TpcBNO5xqWNJa B/wDa6S5DyiSTTrRDtRRNZFD0ATSkWsQakX1OZfZNpihPfyNojWr6oz/jOcr9DH+criO ubNzIBV6uqdC8B4hi9gdQ7hpAifkY0y0G3m2Tl9m59J1WtIH/5/cbXuVQItEb1MSr+UW F57A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=ZAvNySM6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id s19-20020a656913000000b003c60d889162si1728556pgq.244.2022.05.18.00.50.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 00:50:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcdkim header.b=ZAvNySM6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6D73E122B59; Wed, 18 May 2022 00:50:19 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232614AbiERHtz (ORCPT + 99 others); Wed, 18 May 2022 03:49:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232600AbiERHtw (ORCPT ); Wed, 18 May 2022 03:49:52 -0400 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0AC21207F0; Wed, 18 May 2022 00:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1652860191; x=1684396191; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=YXZfjMQjUYv74UOxyPEdQftsBYoYCO06rHvgPycGMF8=; b=ZAvNySM6n3yl2pZeG1iXhTqolcDLZaADSHpvy3vuynfXl/faTsnXvTAW 9dYy498KbpKXU2t4bxZ5yBApZyWpfAVS11h2a6re6tcPbsnmG86W+IrGZ aID367ji8W1AhFCNt2YXWmv931bK5OejVxrKjvYE8Dqvewi0z7wx/+3GS c=; Received: from unknown (HELO ironmsg02-sd.qualcomm.com) ([10.53.140.142]) by alexa-out-sd-02.qualcomm.com with ESMTP; 18 May 2022 00:49:50 -0700 X-QCInternal: smtphost Received: from unknown (HELO nasanex01a.na.qualcomm.com) ([10.52.223.231]) by ironmsg02-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2022 00:49:50 -0700 Received: from blr-ubuntu-185.qualcomm.com (10.80.80.8) by nasanex01a.na.qualcomm.com (10.52.223.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.22; Wed, 18 May 2022 00:49:41 -0700 From: Vivek Kumar To: , , , , , , , , , , , , , CC: , , , , , , , , , , , , , , Vivek Kumar , Prasanna Kumar Subject: [RFC 6/6] irqchip/gic-v3: Re-init GIC hardware upon hibernation restore Date: Wed, 18 May 2022 13:18:41 +0530 Message-ID: <1652860121-24092-7-git-send-email-quic_vivekuma@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1652860121-24092-1-git-send-email-quic_vivekuma@quicinc.com> References: <1652860121-24092-1-git-send-email-quic_vivekuma@quicinc.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nasanex01a.na.qualcomm.com (10.52.223.231) X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Code added in this patch takes backup of different set of registers during hibernation suspend. On receiving hibernation restore callback, it restores register values from backup. This ensures state of hardware to be same just before hibernation and after restore. Signed-off-by: Vivek Kumar Signed-off-by: Prasanna Kumar --- drivers/irqchip/irq-gic-v3.c | 138 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 2be8dea..442d32f 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -29,6 +29,10 @@ #include #include +#include +#include +#include + #include "irq-gic-common.h" #define GICD_INT_NMI_PRI (GICD_INT_DEF_PRI & ~0x80) @@ -56,6 +60,14 @@ struct gic_chip_data { bool has_rss; unsigned int ppi_nr; struct partition_desc **ppi_descs; +#ifdef CONFIG_HIBERNATION + unsigned int enabled_irqs[32]; + unsigned int active_irqs[32]; + unsigned int irq_edg_lvl[64]; + unsigned int ppi_edg_lvl; + unsigned int enabled_sgis; + unsigned int pending_sgis; +#endif }; static struct gic_chip_data gic_data __read_mostly; @@ -170,6 +182,9 @@ static enum gic_intid_range get_intid_range(struct irq_data *d) return __get_intid_range(d->hwirq); } +static void gic_dist_init(void); +static void gic_cpu_init(void); + static inline unsigned int gic_irq(struct irq_data *d) { return d->hwirq; @@ -828,7 +843,7 @@ static bool gic_has_group0(void) return val != 0; } -static void __init gic_dist_init(void) +static void gic_dist_init(void) { unsigned int i; u64 affinity; @@ -1399,6 +1414,120 @@ static void gic_cpu_pm_init(void) static inline void gic_cpu_pm_init(void) { } #endif /* CONFIG_CPU_PM */ +#ifdef CONFIG_PM +#ifdef CONFIG_HIBERNATION +extern int in_suspend; +static bool hibernation; + +static int gic_suspend_notifier(struct notifier_block *nb, + unsigned long event, + void *dummy) +{ + if (event == PM_HIBERNATION_PREPARE) + hibernation = true; + else if (event == PM_POST_HIBERNATION) + hibernation = false; + return NOTIFY_OK; +} + +static struct notifier_block gic_notif_block = { + .notifier_call = gic_suspend_notifier, +}; + +static void gic_hibernation_suspend(void) +{ + int i; + void __iomem *base = gic_data.dist_base; + void __iomem *rdist_base = gic_data_rdist_sgi_base(); + + gic_data.enabled_sgis = readl_relaxed(rdist_base + GICD_ISENABLER); + gic_data.pending_sgis = readl_relaxed(rdist_base + GICD_ISPENDR); + /* Store edge level for PPIs by reading GICR_ICFGR1 */ + gic_data.ppi_edg_lvl = readl_relaxed(rdist_base + GICR_ICFGR0 + 4); + + for (i = 0; i * 32 < GIC_LINE_NR; i++) { + gic_data.enabled_irqs[i] = readl_relaxed(base + + GICD_ISENABLER + i * 4); + gic_data.active_irqs[i] = readl_relaxed(base + + GICD_ISPENDR + i * 4); + } + + for (i = 2; i < GIC_LINE_NR / 16; i++) + gic_data.irq_edg_lvl[i] = readl_relaxed(base + + GICD_ICFGR + i * 4); +} +#endif + +static int gic_suspend(void) +{ +#ifdef CONFIG_HIBERNATION + if (unlikely(hibernation)) + gic_hibernation_suspend(); +#endif + return 0; +} + +void gic_resume(void) +{ +#ifdef CONFIG_HIBERNATION + int i; + void __iomem *base = gic_data.dist_base; + void __iomem *rdist_base = gic_data_rdist_sgi_base(); + + /* + * in_suspend is defined in hibernate.c and will be 0 during + * hibernation restore case. Also it willl be 0 for suspend to ram case + * and similar cases. Underlying code will not get executed in regular + * cases and will be executed only for hibernation restore. + */ + if (unlikely((in_suspend == 0 && hibernation))) { + pr_info("Re-initializing gic in hibernation restore\n"); + gic_dist_init(); + gic_cpu_init(); + /* Activate and enable SGIs and PPIs */ + writel_relaxed(gic_data.enabled_sgis, + rdist_base + GICD_ISENABLER); + writel_relaxed(gic_data.pending_sgis, + rdist_base + GICD_ISPENDR); + /* Restore edge and level triggers for PPIs from GICR_ICFGR1 */ + writel_relaxed(gic_data.ppi_edg_lvl, + rdist_base + GICR_ICFGR0 + 4); + + /* Restore edge and level triggers */ + for (i = 2; i < GIC_LINE_NR / 16; i++) + writel_relaxed(gic_data.irq_edg_lvl[i], + base + GICD_ICFGR + i * 4); + gic_dist_wait_for_rwp(); + + /* Activate and enable interrupts from backup */ + for (i = 0; i * 32 < GIC_LINE_NR; i++) { + writel_relaxed(gic_data.active_irqs[i], + base + GICD_ISPENDR + i * 4); + + writel_relaxed(gic_data.enabled_irqs[i], + base + GICD_ISENABLER + i * 4); + } + gic_dist_wait_for_rwp(); + } +#endif +} +EXPORT_SYMBOL_GPL(gic_resume); + +static struct syscore_ops gic_syscore_ops = { + .suspend = gic_suspend, + .resume = gic_resume, +}; + +static void gic_syscore_init(void) +{ + register_syscore_ops(&gic_syscore_ops); +} + +#else +static inline void gic_syscore_init(void) { } +void gic_resume(void) { } +#endif + static struct irq_chip gic_chip = { .name = "GICv3", .irq_mask = gic_mask_irq, @@ -1887,6 +2016,7 @@ static int __init gic_init_bases(void __iomem *dist_base, gic_cpu_init(); gic_smp_init(); gic_cpu_pm_init(); + gic_syscore_init(); if (gic_dist_supports_lpis()) { its_init(handle, &gic_data.rdists, gic_data.domain); @@ -2092,7 +2222,11 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare redist_stride, &node->fwnode); if (err) goto out_unmap_rdist; - +#ifdef CONFIG_HIBERNATION + err = register_pm_notifier(&gic_notif_block); + if (err) + goto out_unmap_rdist; +#endif gic_populate_ppi_partitions(node); if (static_branch_likely(&supports_deactivate_key)) -- 2.7.4