From patchwork Tue Oct 20 12:10:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "majun \(F\)" X-Patchwork-Id: 55306 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lf0-f72.google.com (mail-lf0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id 9A33622EA2 for ; Tue, 20 Oct 2015 12:24:01 +0000 (UTC) Received: by lffv3 with SMTP id v3sf4266305lff.1 for ; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id :in-reply-to:references:mime-version:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :content-type:content-transfer-encoding:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list; bh=h3Mn1Jp2vrCjgat+s718IdLRimq0mAj7U4CK4Y8f8tI=; b=TrjfS2lekDr/1mf6MKTqkOMNeIsY4ev7Bsfvxk5NaBCwpOidggECqZ65OBjbrbGh0q /YADV/wVG3q32XJz6EJtb35mffLG+R48fdYi8GlZkeEflgpG8ULgez1pSfEM+/rqG8qZ 6pWthJakb6ie8WaTYHkd7fQXn/1zCP9Dg2XzHx6+2eSY5rt6dz5uqWidkqZQa4T5a7c1 yFpCDwlokrBHqhtKvP2kvyUHiJcVyL6fjeyOvU+JeeQj7rB9NExcYsi7o0TC9d9nLJtC M5pkEAxmi1bwazp9/TwhSpSlkGrUJnjJP32CmKgjHAO2clclD+fAoaEsn4Y9CqmF4bPd jfrQ== X-Gm-Message-State: ALoCoQkfRp8cqFAoVfYdVfrmnu3/rXJPQj9cGPDx764YtaB0GyvLaHlniqnAuajqbqA3FOAt9C4Z X-Received: by 10.195.18.100 with SMTP id gl4mr578863wjd.4.1445343840536; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.207.70 with SMTP id f67ls60495lfg.78.gmail; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) X-Received: by 10.25.22.38 with SMTP id m38mr1086552lfi.10.1445343840383; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) Received: from mail-lf0-f52.google.com (mail-lf0-f52.google.com. [209.85.215.52]) by mx.google.com with ESMTPS id r134si2081766lfd.0.2015.10.20.05.24.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Oct 2015 05:24:00 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) client-ip=209.85.215.52; Received: by lffv3 with SMTP id v3so4644916lff.0 for ; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) X-Received: by 10.25.207.82 with SMTP id f79mr1115372lfg.73.1445343840162; Tue, 20 Oct 2015 05:24:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp2050083lbq; Tue, 20 Oct 2015 05:23:58 -0700 (PDT) X-Received: by 10.68.245.33 with SMTP id xl1mr3755556pbc.39.1445343838393; Tue, 20 Oct 2015 05:23:58 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id ni10si4872742pbc.213.2015.10.20.05.23.57 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Oct 2015 05:23:58 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZoVwK-0006TM-7x; Tue, 20 Oct 2015 12:22:52 +0000 Received: from szxga01-in.huawei.com ([58.251.152.64]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZoVwD-0006IK-SK for linux-arm-kernel@lists.infradead.org; Tue, 20 Oct 2015 12:22:48 +0000 Received: from 172.24.1.48 (EHLO SZXEML429-HUB.china.huawei.com) ([172.24.1.48]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CXE95740; Tue, 20 Oct 2015 20:10:43 +0800 (CST) Received: from localhost (10.177.235.245) by SZXEML429-HUB.china.huawei.com (10.82.67.184) with Microsoft SMTP Server id 14.3.235.1; Tue, 20 Oct 2015 20:10:35 +0800 From: MaJun To: , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH RESEND v6 3/4] irqchip:create irq domain for each mbigen device Date: Tue, 20 Oct 2015 20:10:31 +0800 Message-ID: <1445343032-8032-4-git-send-email-majun258@huawei.com> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1445343032-8032-1-git-send-email-majun258@huawei.com> References: <1445343032-8032-1-git-send-email-majun258@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.177.235.245] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151020_052247_590754_46E5608D X-CRM114-Status: GOOD ( 17.62 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [58.251.152.64 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [58.251.152.64 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: majun258@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 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.c | 165 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 165 insertions(+), 0 deletions(-) diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index f18132f..3a20b25 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -16,27 +16,177 @@ * along with this program. If not, see . */ +#include +#include #include +#include #include #include #include #include #include +/* Interrupt numbers per mbigen node supported */ +#define IRQS_PER_MBIGEN_NODE 128 + +/* 16 irqs (Pin0-pin15) are reserved for each mbigen chip */ +#define RESERVED_IRQ_PER_MBIGEN_CHIP 16 + +/** + * In mbigen vector register + * bit[21:12]: event id value + * bit[11:0]: device id + */ +#define IRQ_EVENT_ID_SHIFT 12 +#define IRQ_EVENT_ID_MASK 0x3ff + +/* register range of each mbigen node */ +#define MBIGEN_NODE_OFFSET 0x1000 + +/* offset of vector register in mbigen node */ +#define REG_MBIGEN_VEC_OFFSET 0x200 + /** * struct mbigen_device - holds the information of mbigen device. * * @pdev: pointer to the platform device structure of mbigen chip. * @base: mapped address of this mbigen chip. + * @domain: pointer to the irq domain */ struct mbigen_device { struct platform_device *pdev; void __iomem *base; + struct irq_domain *domain; +}; + +/** + * struct mbigen_irq_data - private data of each irq + * + * @base: mapped address of mbigen chip + * @reg_vec: addr offset of interrupt vector register. + */ +struct mbigen_irq_data { + void __iomem *base; + unsigned int reg_vec; +}; + +static inline int get_mbigen_vec_reg(u32 nid, u32 offset) +{ + return (offset * 4) + nid * MBIGEN_NODE_OFFSET + + REG_MBIGEN_VEC_OFFSET; +} + + +static struct irq_chip mbigen_irq_chip = { + .name = "mbigen-v2", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = mbigen_eoi_irq, + .irq_set_type = mbigen_set_type, + .irq_set_affinity = irq_chip_set_affinity_parent, +}; + +static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg) +{ + struct mbigen_irq_data *mgn_irq_data = irq_get_chip_data(desc->irq); + u32 val; + + val = readl_relaxed(mgn_irq_data->reg_vec + mgn_irq_data->base); + + val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT); + val |= (msg->data << IRQ_EVENT_ID_SHIFT); + + writel_relaxed(val, mgn_irq_data->reg_vec + mgn_irq_data->base); +} + +static struct mbigen_irq_data *set_mbigen_irq_data(int hwirq) +{ + struct mbigen_irq_data *datap; + unsigned int nid, pin_offset; + + datap = kzalloc(sizeof(*datap), GFP_KERNEL); + if (!datap) + return NULL; + + /* get the mbigen node number */ + nid = (hwirq - RESERVED_IRQ_PER_MBIGEN_CHIP) / IRQS_PER_MBIGEN_NODE + 1; + + pin_offset = (hwirq - RESERVED_IRQ_PER_MBIGEN_CHIP) + % IRQS_PER_MBIGEN_NODE; + + datap->reg_vec = get_mbigen_vec_reg(nid, pin_offset); + + return datap; +} + +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; + + *hwirq = fwspec->param[0]; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + + 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 = fwspec->param[0]; + struct mbigen_device *mgn_chip; + struct mbigen_irq_data *mgn_irq_data; + int i, err; + + err = platform_msi_domain_alloc(domain, virq, nr_irqs); + if (err) + return err; + + /* set related information of this irq */ + mgn_irq_data = set_mbigen_irq_data(hwirq); + if (!mgn_irq_data) + return err; + + mgn_chip = platform_msi_get_host_data(domain); + mgn_irq_data->base = mgn_chip->base; + + for (i = 0; i < nr_irqs; i++) + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, + &mbigen_irq_chip, mgn_irq_data); + + return 0; +} + +static void mbigen_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) +{ + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + struct mbigen_irq_data *mgn_irq_data = irq_data_get_irq_chip_data(d); + + kfree(mgn_irq_data); + irq_domain_free_irqs_common(domain, virq, nr_irqs); +} + +static struct irq_domain_ops mbigen_domain_ops = { + .translate = mbigen_domain_translate, + .alloc = mbigen_irq_domain_alloc, + .free = mbigen_domain_free, }; static int mbigen_device_probe(struct platform_device *pdev) { struct mbigen_device *mgn_chip; + struct irq_domain *domain; + u32 num_msis; mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); if (!mgn_chip) @@ -45,6 +195,20 @@ static int mbigen_device_probe(struct platform_device *pdev) mgn_chip->pdev = pdev; mgn_chip->base = of_iomap(pdev->dev.of_node, 0); + /* If there is no "num-msi" property, assume 64... */ + if (of_property_read_u32(pdev->dev.of_node, "num-msis", &num_msis) < 0) + num_msis = 64; + + domain = platform_msi_create_device_domain(&pdev->dev, num_msis, + mbigen_write_msg, + &mbigen_domain_ops, + mgn_chip); + + if (!domain) + return -ENOMEM; + + mgn_chip->domain = domain; + platform_set_drvdata(pdev, mgn_chip); return 0; @@ -54,6 +218,7 @@ static int mbigen_device_remove(struct platform_device *pdev) { struct mbigen_device *mgn_chip = platform_get_drvdata(pdev); + irq_domain_remove(mgn_chip->domain); iounmap(mgn_chip->base); return 0;