Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1833613pxb; Mon, 8 Mar 2021 07:28:03 -0800 (PST) X-Google-Smtp-Source: ABdhPJzI0dyGoEy9J1evusz8oHeSJhwwEV7kvy3bVpbOOUT7V8/a7YTKBsLiKLjd58QRUWMAIbeI X-Received: by 2002:a17:906:b297:: with SMTP id q23mr15769221ejz.315.1615217283687; Mon, 08 Mar 2021 07:28:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615217283; cv=none; d=google.com; s=arc-20160816; b=GBAqmbQutSnq2j+wszm6uiC2O2B0fIpZhHP0v9PewPm00rtG4ecqbJhfRb0ouV9bgd SR32YYJNkiD5o530or6yym6ZWXqezYttloMQ7gqeKPdlTYcF12o+n0AlYe9DlbwpPYyn DnpUxEeXMprkNQNLFNDqg7Fj7Jc+IUoo/z0A1Pfo2/sjAQ1gXAY2vhhRMAEhiDBfv51U TsOfMTUrhOubF6HK+L/qWrE6Jqi/g5EomHW+7MvhYjOC9szCgh9wVyq4CYmcKdO3QoJU VLmmvZjj/rvSSKc1Jr8UOrbCIaN/WtlF8tRQuZd6E5hJXZZ4IVcIcCL6VNU/g6KHbnUw jHbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:subject:cc:to:from; bh=yqvjr9islaaDX8cPUFYTXMUWXzojYJh0jFPkyculXLY=; b=PD4IFJCmltACROplI9EChupSxti46x8gJ6riD2iJQWNT27UElsbpJMLQY2MkVhKG/G 2BuNTstJe0mMDm8dZ4iCZ7pb0EFmlD36HFsJFaWSQ8iYBbIguraMZXifXEH1h/tn9zlO K9XoJbwYUkR5f4IOQHW0k+753rEXHBAKwsDwoWFkFY9EARP5oUqcDSwB3MTnFX9msXPJ CylGc9QuHsZj9hX9hvBQx4MGVSCkz+gSh05wtnsramVYIRH6Aij4HnTmAYPuhFoMf6hu n89Pr1mKYyj6UD22K5v6okheF8bwmlf4F2nKr8X2scRUkCPAoWDImqeakBPfUXiT5VpY KSvg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j7si7229158edh.201.2021.03.08.07.27.41; Mon, 08 Mar 2021 07:28:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231426AbhCHP0h (ORCPT + 99 others); Mon, 8 Mar 2021 10:26:37 -0500 Received: from mailgw01.mediatek.com ([210.61.82.183]:40097 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230246AbhCHP0L (ORCPT ); Mon, 8 Mar 2021 10:26:11 -0500 X-UUID: f9f9acf31296440885f04522b3f5b548-20210308 X-UUID: f9f9acf31296440885f04522b3f5b548-20210308 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw01.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.14 Build 0819 with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1398100812; Mon, 08 Mar 2021 23:26:08 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs05n1.mediatek.inc (172.21.101.15) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 8 Mar 2021 23:26:06 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 8 Mar 2021 23:26:06 +0800 From: Mark-PK Tsai To: Marc Zyngier CC: , Mark-PK Tsai , Daniel Palmer , Thomas Gleixner , Matthias Brugger , , , Subject: [PATCH v3] irqchip/irq-mst: Support polarity configuration Date: Mon, 8 Mar 2021 23:26:05 +0800 Message-ID: <20210308152605.26122-1-mark-pk.tsai@mediatek.com> X-Mailer: git-send-email 2.18.0 MIME-Version: 1.0 Content-Type: text/plain X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Support irq polarity configuration and save and restore the config when system suspend and resume. Signed-off-by: Mark-PK Tsai --- drivers/irqchip/irq-mst-intc.c | 92 ++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-mst-intc.c b/drivers/irqchip/irq-mst-intc.c index 143657b0cf28..50f3ef8bc610 100644 --- a/drivers/irqchip/irq-mst-intc.c +++ b/drivers/irqchip/irq-mst-intc.c @@ -13,15 +13,27 @@ #include #include #include +#include -#define INTC_MASK 0x0 -#define INTC_EOI 0x20 +#define MST_INTC_MAX_IRQS 64 + +#define INTC_MASK 0x0 +#define INTC_REV_POLARITY 0x10 +#define INTC_EOI 0x20 + +#ifdef CONFIG_PM_SLEEP +static LIST_HEAD(mst_intc_list); +#endif struct mst_intc_chip_data { raw_spinlock_t lock; unsigned int irq_start, nr_irqs; void __iomem *base; bool no_eoi; +#ifdef CONFIG_PM_SLEEP + struct list_head entry; + u16 saved_polarity_conf[DIV_ROUND_UP(MST_INTC_MAX_IRQS, 16)]; +#endif }; static void mst_set_irq(struct irq_data *d, u32 offset) @@ -78,6 +90,19 @@ static void mst_intc_eoi_irq(struct irq_data *d) irq_chip_eoi_parent(d); } +static int mst_irq_chip_set_type(struct irq_data *data, unsigned int type) +{ + if (type != IRQ_TYPE_LEVEL_LOW && type != IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + + if (type == IRQ_TYPE_LEVEL_LOW) { + mst_set_irq(data, INTC_REV_POLARITY); + type = IRQ_TYPE_LEVEL_HIGH; + } + + return irq_chip_set_type_parent(data, type); +} + static struct irq_chip mst_intc_chip = { .name = "mst-intc", .irq_mask = mst_intc_mask_irq, @@ -87,13 +112,62 @@ static struct irq_chip mst_intc_chip = { .irq_set_irqchip_state = irq_chip_set_parent_state, .irq_set_affinity = irq_chip_set_affinity_parent, .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent, - .irq_set_type = irq_chip_set_type_parent, + .irq_set_type = mst_irq_chip_set_type, .irq_retrigger = irq_chip_retrigger_hierarchy, .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, }; +#ifdef CONFIG_PM_SLEEP +static void mst_intc_polarity_save(struct mst_intc_chip_data *cd) +{ + int i; + void __iomem *addr = cd->base + INTC_REV_POLARITY; + + for (i = 0; i < DIV_ROUND_UP(cd->nr_irqs, 16); i++) + cd->saved_polarity_conf[i] = readw_relaxed(addr + i * 4); +} + +static void mst_intc_polarity_restore(struct mst_intc_chip_data *cd) +{ + int i; + void __iomem *addr = cd->base + INTC_REV_POLARITY; + + for (i = 0; i < DIV_ROUND_UP(cd->nr_irqs, 16); i++) + writew_relaxed(cd->saved_polarity_conf[i], addr + i * 4); +} + +static void mst_irq_resume(void) +{ + struct mst_intc_chip_data *cd; + + list_for_each_entry(cd, &mst_intc_list, entry) + mst_intc_polarity_restore(cd); +} + +static int mst_irq_suspend(void) +{ + struct mst_intc_chip_data *cd; + + list_for_each_entry(cd, &mst_intc_list, entry) + mst_intc_polarity_save(cd); + return 0; +} + +static struct syscore_ops mst_irq_syscore_ops = { + .suspend = mst_irq_suspend, + .resume = mst_irq_resume, +}; + +static int __init mst_irq_pm_init(void) +{ + register_syscore_ops(&mst_irq_syscore_ops); + return 0; +} +late_initcall(mst_irq_pm_init); +#endif + static int mst_intc_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, unsigned long *hwirq, @@ -145,6 +219,14 @@ static int mst_intc_domain_alloc(struct irq_domain *domain, unsigned int virq, parent_fwspec = *fwspec; parent_fwspec.fwnode = domain->parent->fwnode; parent_fwspec.param[1] = cd->irq_start + hwirq; + + /* + * If the irq signal is active low, configure it to active high + * to meet GIC SPI spec in mst_irq_chip_set_type via REV_POLARITY bit + */ + if (fwspec->param[2] == IRQ_TYPE_LEVEL_LOW) + parent_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_fwspec); } @@ -193,6 +275,10 @@ static int __init mst_intc_of_init(struct device_node *dn, return -ENOMEM; } +#ifdef CONFIG_PM_SLEEP + INIT_LIST_HEAD(&cd->entry); + list_add_tail(&cd->entry, &mst_intc_list); +#endif return 0; } -- 2.18.0