From patchwork Tue Feb 16 06:37:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "majun \(F\)" X-Patchwork-Id: 61979 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp1482599lbl; Mon, 15 Feb 2016 22:38:44 -0800 (PST) X-Received: by 10.98.14.79 with SMTP id w76mr29007074pfi.1.1455604724546; Mon, 15 Feb 2016 22:38:44 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ln6si48935969pab.182.2016.02.15.22.38.44; Mon, 15 Feb 2016 22:38:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754100AbcBPGik (ORCPT + 30 others); Tue, 16 Feb 2016 01:38:40 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:7170 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753560AbcBPGih (ORCPT ); Tue, 16 Feb 2016 01:38:37 -0500 Received: from 172.24.1.50 (EHLO szxeml427-hub.china.huawei.com) ([172.24.1.50]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BWB82468; Tue, 16 Feb 2016 14:38:19 +0800 (CST) Received: from localhost (10.177.235.245) by szxeml427-hub.china.huawei.com (10.82.67.182) with Microsoft SMTP Server id 14.3.235.1; Tue, 16 Feb 2016 14:37:40 +0800 From: MaJun To: , , , , , , , , , , , , , , Subject: [PATCH v2 4/5] irqchip:create irq domain for each mbigen device Date: Tue, 16 Feb 2016 14:37:27 +0800 Message-ID: <1455604648-20668-5-git-send-email-majun258@huawei.com> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1455604648-20668-1-git-send-email-majun258@huawei.com> References: <1455604648-20668-1-git-send-email-majun258@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.177.235.245] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020203.56C2C3DD.000C, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: f256cfa9feab7f52a474a0a61d4f7367 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ma Jun For peripheral devices which connect to mbigen,mbigen is a interrupt controller. So, we create irq domain for each mbigen device and add mbigen irq domain into irq hierarchy structure. Signed-off-by: Ma Jun --- drivers/irqchip/irq-mbigen-v1.c | 136 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 136 insertions(+), 0 deletions(-) -- 1.7.1 diff --git a/drivers/irqchip/irq-mbigen-v1.c b/drivers/irqchip/irq-mbigen-v1.c index 9445658..61e7ad0 100644 --- a/drivers/irqchip/irq-mbigen-v1.c +++ b/drivers/irqchip/irq-mbigen-v1.c @@ -16,11 +16,30 @@ * along with this program. If not, see . */ +#include +#include #include +#include +#include +#include #include #include #include +/* The maximum IRQ pin number of mbigen chip(start from 0) */ +#define MAXIMUM_IRQ_PIN_NUM 640 + +/** + * In mbigen vector register + * bit[31:16]: device id + * bit[15:0]: event id value + */ +#define IRQ_EVENT_ID_MASK 0xffff + +/* offset of vector register in mbigen node */ +#define REG_MBIGEN_VEC_OFFSET 0x300 +#define REG_MBIGEN_EXT_VEC_OFFSET 0x320 + /** * struct mbigen_device - holds the information of mbigen device. * @@ -32,10 +51,112 @@ struct mbigen_device { void __iomem *base; }; +static int get_mbigen_nid(unsigned int offset) +{ + int nid = 0; + + if (offset < 256) + nid = offset / 64; + else if (offset < 384) + nid = 4; + else if (offset < 640) + nid = 5; + + return nid; +} + +static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) +{ + unsigned int nid; + + nid = get_mbigen_nid(hwirq); + + if (nid < 4) + return (nid * 4) + REG_MBIGEN_VEC_OFFSET; + else + return (nid - 4) * 4 + REG_MBIGEN_EXT_VEC_OFFSET; +} + +static struct irq_chip mbigen_irq_chip = { + .name = "mbigen-v1", +}; + +static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg) +{ + /* The address of doorbell is encoded in mbigen register by default + * So,we don't need to program the doorbell address at here + * Besides, the event ID is decided by the hardware pin number, + * we can't change it in software.So, we don't need to encode the + * event ID in mbigen register. + */ +} + +static int mbigen_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (is_of_node(fwspec->fwnode)) { + if (fwspec->param_count != 2) + return -EINVAL; + + if (fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) + return -EINVAL; + + *hwirq = fwspec->param[0]; + + /* If there is no valid irq type, just use the default type */ + if ((fwspec->param[1] == IRQ_TYPE_EDGE_RISING) || + (fwspec->param[1] == IRQ_TYPE_LEVEL_HIGH)) + *type = fwspec->param[1]; + else + return -EINVAL; + + return 0; + } + return -EINVAL; +} + +static int mbigen_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, + void *args) +{ + struct irq_fwspec *fwspec = args; + irq_hw_number_t hwirq; + unsigned int type; + struct mbigen_device *mgn_chip; + int i, err; + + err = mbigen_domain_translate(domain, fwspec, &hwirq, &type); + if (err) + return err; + + err = platform_msi_domain_alloc(domain, virq, nr_irqs); + if (err) + return err; + + mgn_chip = platform_msi_get_host_data(domain); + + for (i = 0; i < nr_irqs; i++) + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, + &mbigen_irq_chip, mgn_chip->base); + + return 0; +} + +static struct irq_domain_ops mbigen_domain_ops = { + .translate = mbigen_domain_translate, + .alloc = mbigen_irq_domain_alloc, + .free = irq_domain_free_irqs_common, +}; + static int mbigen_device_probe(struct platform_device *pdev) { struct mbigen_device *mgn_chip; struct resource *res; + struct irq_domain *domain; + u32 num_pins; mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); if (!mgn_chip) @@ -48,8 +169,23 @@ static int mbigen_device_probe(struct platform_device *pdev) if (IS_ERR(mgn_chip->base)) return PTR_ERR(mgn_chip->base); + if (of_property_read_u32(pdev->dev.of_node, "num-pins", &num_pins) < 0) { + dev_err(&pdev->dev, "No num-pins property\n"); + return -EINVAL; + } + + domain = platform_msi_create_device_domain(&pdev->dev, num_pins, + mbigen_write_msg, + &mbigen_domain_ops, + mgn_chip); + + if (!domain) + return -ENOMEM; + platform_set_drvdata(pdev, mgn_chip); + dev_info(&pdev->dev, "Allocated %d MSIs\n", num_pins); + return 0; }