From patchwork Sun Mar 19 15:26:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mars Cheng X-Patchwork-Id: 9632613 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0E9AA602D6 for ; Sun, 19 Mar 2017 15:27:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 012C7283E0 for ; Sun, 19 Mar 2017 15:27:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9E69284D5; Sun, 19 Mar 2017 15:27:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 86C1E283E0 for ; Sun, 19 Mar 2017 15:27:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=d2WPXpGmodRwgsTwnj8mh43chrfNU9iT3Q5beuOrc9I=; b=thjgPfaCeO1ANt nWNv+2wUB+UWK5TRf01okPmDFFDf/kYmpomhuEk53SOvpzo8/0MPQd2PwhYXnBywzVc+gGvgxeeGI k8CYnjjc9PBe2VR3GsNeGVevGOcA3jLWIyQO+R4cXnjU/0J2V5zg2y/5x376xctb6O8//IBkvi6ma 7hZ96HdHStcEs3MAcQghAPgCaiS7ZNorumU1bTD8K5x7piQVJjIpmcNfCFb0rpNLO7c1+R++4G0Kt Xv5i5iY7C935zfs29W+lIJFC4jswnCWCTukynqV85Nld6yAnAUymTuaU3IwqKp1w9IhTQ0TqOL/lh 8GGYzLOe6ikCYxlc11zQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cpck6-0007vW-OL; Sun, 19 Mar 2017 15:27:38 +0000 Received: from [210.61.82.184] (helo=mailgw02.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cpcjz-0007mL-If for linux-mediatek@lists.infradead.org; Sun, 19 Mar 2017 15:27:33 +0000 Received: from mtkhts07.mediatek.inc [(172.21.101.69)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 62515862; Sun, 19 Mar 2017 23:26:55 +0800 Received: from mtkswgap22.mediatek.inc (172.21.77.33) by mtkhts07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 14.3.266.1; Sun, 19 Mar 2017 23:26:53 +0800 From: Mars Cheng To: Matthias Brugger , Rob Herring , Marc Zyngier , Michael Turquette , Stephen Boyd Subject: [PATCH v3 02/12] irqchip: mtk-sysirq: extend intpol base to arbitrary number Date: Sun, 19 Mar 2017 23:26:23 +0800 Message-ID: <1489937193-2953-3-git-send-email-mars.cheng@mediatek.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1489937193-2953-1-git-send-email-mars.cheng@mediatek.com> References: <1489937193-2953-1-git-send-email-mars.cheng@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170319_082731_783987_2E193244 X-CRM114-Status: GOOD ( 18.56 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, CC Hwang , wsd_upstream@mediatek.com, Mars Cheng , Loda Chou , linux-kernel@vger.kernel.org, Jades Shih , Miles Chen , linux-mediatek@lists.infradead.org, My Chuang , Yingjoe Chen , linux-clk@vger.kernel.org Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Originally driver only supports one base. However, MT6797 has more than one bases to configure interrupt polarity. To support possible design change, here comes a solution to use arbitrary number of bases. Signed-off-by: Mars Cheng Acked-by: Marc Zyngier --- drivers/irqchip/irq-mtk-sysirq.c | 116 +++++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c index 63ac73b..9ba969c 100644 --- a/drivers/irqchip/irq-mtk-sysirq.c +++ b/drivers/irqchip/irq-mtk-sysirq.c @@ -24,22 +24,29 @@ struct mtk_sysirq_chip_data { spinlock_t lock; - void __iomem *intpol_base; + u32 nr_intpol_bases; + void __iomem **intpol_bases; + u32 *intpol_words; + u8 *intpol_idx; + u16 *which_word; }; static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) { irq_hw_number_t hwirq = data->hwirq; struct mtk_sysirq_chip_data *chip_data = data->chip_data; + u8 intpol_idx = chip_data->intpol_idx[hwirq]; + void __iomem *base; u32 offset, reg_index, value; unsigned long flags; int ret; + base = chip_data->intpol_bases[intpol_idx]; + reg_index = chip_data->which_word[hwirq]; offset = hwirq & 0x1f; - reg_index = hwirq >> 5; spin_lock_irqsave(&chip_data->lock, flags); - value = readl_relaxed(chip_data->intpol_base + reg_index * 4); + value = readl_relaxed(base + reg_index * 4); if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) { if (type == IRQ_TYPE_LEVEL_LOW) type = IRQ_TYPE_LEVEL_HIGH; @@ -49,7 +56,8 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) } else { value &= ~(1 << offset); } - writel(value, chip_data->intpol_base + reg_index * 4); + + writel(value, base + reg_index * 4); data = data->parent_data; ret = data->chip->irq_set_type(data, type); @@ -124,8 +132,7 @@ static int __init mtk_sysirq_of_init(struct device_node *node, { struct irq_domain *domain, *domain_parent; struct mtk_sysirq_chip_data *chip_data; - int ret, size, intpol_num; - struct resource res; + int ret, size, intpol_num = 0, nr_intpol_bases = 0, i = 0; domain_parent = irq_find_host(parent); if (!domain_parent) { @@ -133,36 +140,103 @@ static int __init mtk_sysirq_of_init(struct device_node *node, return -EINVAL; } - ret = of_address_to_resource(node, 0, &res); - if (ret) - return ret; - chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); if (!chip_data) return -ENOMEM; - size = resource_size(&res); - intpol_num = size * 8; - chip_data->intpol_base = ioremap(res.start, size); - if (!chip_data->intpol_base) { - pr_err("mtk_sysirq: unable to map sysirq register\n"); - ret = -ENXIO; - goto out_free; + while (of_get_address(node, i++, NULL, NULL)) + nr_intpol_bases++; + + if (nr_intpol_bases == 0) { + pr_err("mtk_sysirq: base address not specified\n"); + ret = -EINVAL; + goto out_free_chip; + } + + chip_data->intpol_words = kcalloc(nr_intpol_bases, + sizeof(*chip_data->intpol_words), + GFP_KERNEL); + if (!chip_data->intpol_words) { + ret = -ENOMEM; + goto out_free_chip; + } + + chip_data->intpol_bases = kcalloc(nr_intpol_bases, + sizeof(*chip_data->intpol_bases), + GFP_KERNEL); + if (!chip_data->intpol_bases) { + ret = -ENOMEM; + goto out_free_intpol_words; + } + + for (i = 0; i < nr_intpol_bases; i++) { + struct resource res; + + ret = of_address_to_resource(node, i, &res); + size = resource_size(&res); + intpol_num += size * 8; + chip_data->intpol_words[i] = size / 4; + chip_data->intpol_bases[i] = of_iomap(node, i); + if (ret || !chip_data->intpol_bases[i]) { + pr_err("%s: couldn't map region %d\n", + node->full_name, i); + ret = -ENODEV; + goto out_free_intpol; + } + } + + chip_data->intpol_idx = kcalloc(intpol_num, + sizeof(*chip_data->intpol_idx), + GFP_KERNEL); + if (!chip_data->intpol_idx) { + ret = -ENOMEM; + goto out_free_intpol; + } + + chip_data->which_word = kcalloc(intpol_num, + sizeof(*chip_data->which_word), + GFP_KERNEL); + if (!chip_data->which_word) { + ret = -ENOMEM; + goto out_free_intpol_idx; + } + + /* + * assign an index of the intpol_bases for each irq + * to set it fast later + */ + for (i = 0; i < intpol_num ; i++) { + u32 word = i / 32, j; + + for (j = 0; word >= chip_data->intpol_words[j] ; j++) + word -= chip_data->intpol_words[j]; + + chip_data->intpol_idx[i] = j; + chip_data->which_word[i] = word; } domain = irq_domain_add_hierarchy(domain_parent, 0, intpol_num, node, &sysirq_domain_ops, chip_data); if (!domain) { ret = -ENOMEM; - goto out_unmap; + goto out_free_which_word; } spin_lock_init(&chip_data->lock); return 0; -out_unmap: - iounmap(chip_data->intpol_base); -out_free: +out_free_which_word: + kfree(chip_data->which_word); +out_free_intpol_idx: + kfree(chip_data->intpol_idx); +out_free_intpol: + for (i = 0; i < nr_intpol_bases; i++) + if (chip_data->intpol_bases[i]) + iounmap(chip_data->intpol_bases[i]); + kfree(chip_data->intpol_bases); +out_free_intpol_words: + kfree(chip_data->intpol_words); +out_free_chip: kfree(chip_data); return ret; }