Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753623AbcL0JqN (ORCPT ); Tue, 27 Dec 2016 04:46:13 -0500 Received: from mail-cys01nam02on0088.outbound.protection.outlook.com ([104.47.37.88]:42081 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751256AbcL0JqE (ORCPT ); Tue, 27 Dec 2016 04:46:04 -0500 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com;nxp.com; dkim=none (message not signed) header.d=none; From: Minghuan Lian To: , , CC: Marc Zyngier , Rob Herring , Jason Cooper , Roy Zang , Mingkai Hu , Stuart Yoder , Yang-Leo Li , Scott Wood , Minghuan Lian Subject: [PATCH 7/9] irqchip/ls-scfg-msi: add LS1046a MSI support Date: Tue, 27 Dec 2016 17:13:03 +0800 Message-ID: <1482829985-24421-7-git-send-email-Minghuan.Lian@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1482829985-24421-1-git-send-email-Minghuan.Lian@nxp.com> References: <1482829985-24421-1-git-send-email-Minghuan.Lian@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131273034724433379;(91ab9b29-cfa4-454e-5278-08d120cd25b8);() X-Forefront-Antispam-Report: CIP:192.88.168.50;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(336005)(7916002)(39450400003)(39840400002)(39860400002)(39410400002)(39850400002)(39400400002)(39380400002)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(36756003)(68736007)(5001770100001)(356003)(97736004)(626004)(50226002)(47776003)(5660300001)(6666003)(2950100002)(189998001)(8656002)(104016004)(105606002)(7416002)(48376002)(38730400001)(77096006)(230783001)(92566002)(50466002)(305945005)(76176999)(50986999)(2201001)(4326007)(5003940100001)(106466001)(81156014)(81166006)(8936002)(8676002)(85426001)(2906002)(86362001)(7059030)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:MWHPR03MB2480;H:tx30smr01.am.freescale.net;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD010;1:dziiX5mcWyCaLCrDBh4enu829fUkGEljrl8RQ109HP3IOL6c0FOLgf0dyMy4acLz8gJ9Je7Bj4I24bAKq5stbDDH8EhmdmX7ioJDUor2Ya+8QD7NR8xE8QtpOPthON4jsXkKuKVm1RKmA5GvfaO2YDc98wZqhaMqz1bhNk2S4eqPjdVyztuY/lCKfUkem5vCH+Slj6FHuHTUTyDPNtJ7UWkKOUvG2nxWTMcse4LJzG5KS4rc+bNWixpNJXR+sgAvFDbTWoL8NfK7N2e6RkJbYgqVeAofnR1vJw0ssc1bjkdfk2oWW1yfSTNnIvr7OdNu4rjWJPQy9Pk1nWZDq+uHJVqw2hRxcexN+sUsNjxl/C2GOQwQf9HwWDWpibdF5/XxzuazoNiIUYZkng51TaEAQ7+e5Xm0qFQlKVEXzTBDv1RlxUWk2esA/MiBr9WTPGRlomlclOXpGGJ6ImlbFTOMeVnyrYCZRxmSyLq9e8Sv3xf7Pu//3DZFdU25F6egZDehnhpmKKSe6qej/++7YajzQTO7NT5aljKPVoAda3UhH5EKI1md85BuMTQmkzdYaY59FkPSB3i9VCBYNCbDUYCDCZjU6/7rq1vFmgR3St8YGBKSwoUm4KVKIs0W1PWT/WPLfdMQ1pFfWFOx8lKFem959G9HkZNfaKf+Lv+Gm5y/4sXvJnYHhdxNq27favJdUjWHtOYBOYNUu9URYLWX9MncjnIgK9piT4fqvgK/pdBZtLbiXBPaITXnG7s4efa4Yt3+ MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 2a2a1308-5f98-4a8b-52eb-08d42e384dba X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:MWHPR03MB2480; X-Microsoft-Exchange-Diagnostics: 1;MWHPR03MB2480;3:95mGeUt0apH0xphJc6WQWgAa6w99QDDRy+giwfhH5ZOtWuzItc0WM1H+Vy+Zp81Qfp3GmwothAZJSrbmyiupUq1omvXb0/994VKr44lGsAXTVXfKKtFX/NBYv5qGB9Hfcj+tHCjd/i0YkW9RKtnDi3cuZcB38Tr6F96Hs1e6U8SPijHl/uGDquk1zXAiRc41L4wuvqDkF55D3qar3XoKRzD2qxAfSxiUNI93ZPaloN6ytJ1eXokXIYWWj2Q+GyJtz+facykXG2uh1Uw0vOAh/H1v07BTnbmSmA7T0xeA6fyF99SB8i1OmkY/qGnsvgwn6CIYXayvMWMC55XM7uMeeMeER/hO9zmkq/LyOIrKPxpwzbsbKamiyhXUGxJ8fJ/C;25:ZTCnj3lbgWk/vHq7/cC363Qk1Sj9sFo8pUyFkfPtvI/Fg1RvI6M5/iLhGnmNyEULuKXnyM5XBJgGk+fXWqPuRTenbKqx/o+mciiaf12unPlh+FW8vrF67krrewSsT9m7wrNcpfjgQYfU2kqPhH1vJFvVQXaZxGZLoOwONDJ7E59GU1Ky5mf/+eMucsMw3oUF9uRzjfxTNBe17M34o6EibnEZshJJ/mAp930QKl9N8UfS2leZ44fll1QTRALUuZDCnKF7VQPeXl0D0Tq4yvCnl8F04G+1MxGNTppcF9vLqXE69/qTbnrB3y8wwcRgnTjARSutcXOvfOJhWAx/bQ101WvI0y1u6ZfZ1Bb7gujUUfljCIEY9XrqEzEetaIYmoyTOL/4W/lOOitM6E2ELPEE+pstI7SBTHt3wtHKT4GOdb5ZIz4kjz8/C0V08D9mGmE+ebTHd0gUnhKuHou4BBrR9g== X-Microsoft-Exchange-Diagnostics: 1;MWHPR03MB2480;31:J0jPslt1WHGgNUqpCbVPDzGmtPhCNJtY0GOfOTzypHwdkxJ3255EqUUA1KhBtN1yCYc1G3nGwzeoLBqpu6yjuvXGPBigyza5wdJS+6d2JlBy/A3RoMSagvYDdGHJtCgrpErAgbFmR9EMpKz/G5T1eOwqPQvZNsoFt2lzEkwxQ56zMlmRvkPO7usuFJoPs9nIaIpT8BikhZ89zYNvVP+Aqp9Nn5w1K/Dwi13RoqDtiSHhD/gBp/wNTiC0QrjOOh2nHLelVYvg5a8o4uEJgsZrvMtdVD6gOzDuvXv9lE+/mmE= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6095060)(601004)(2401047)(13024025)(13023025)(13015025)(13017025)(13018025)(8121501046)(5005006)(3002001)(10201501046)(6055026)(6096035)(20161123561025)(20161123559025)(20161123556025)(20161123565025)(20161123563025);SRVR:MWHPR03MB2480;BCL:0;PCL:0;RULEID:(400006);SRVR:MWHPR03MB2480; X-Microsoft-Exchange-Diagnostics: 1;MWHPR03MB2480;4:Hu1Uuq/a9onpZ0V3jbC7na9DVCAIZUrtYDDv/vXpTMugZ8qdRajIAoKuJIIOOSPKAAPc48huvjBXre9ZgNp4ccdHmI3qR2aDDaMCv/FMdaeAhzHOe+ClDLe2EB+0cHPICpBe8N0XC1OdCsPi9o4FCNXMdoS6x4D0Uo+3mYQ2goqiWtpvaAuxcCHP259UsR2g9y+/rmepxex/XBF8Td3TFEE021OIR7qnDUGLpvNlGocG2MX5OA1tU2PQFxbIt42e3tY1ryVITqkl4ukFY4J1PsUilvgmVpoEeadhk7loafRwch9hARTNPV5oTfY0dlJPJxw5GO7mpEKk8NHSGcZqcM9Au/VYQ/3LxVlIw/EYWaqg1/zK+JDV06dOhZbPIdRfI71WRbn/bHg97ClJ0ysj0QmPJsNe4Kuo6qEXClCwceiFxkzbK7/PBXC+Jdk8C/8DnGe3VuV+nlPZ0s0r5NJD4M7p0Uy8YmGUi2KK6i7JBSyisXGjmVYQVATOIe5gCILoiuvyjsbvIzfaxgcr9HMVzb672RZ3PYnI9jKGXOwqW9IIxblOZsPQW7KtE77H4Kkp9lBzNqJcAn5m+/07FpJBNUApSdEk3lCNQpw/4boSPzk8Em6cOrR+EHSfmpp6IjNdU5LkHddJCghcCqXA/Dxuisy5Cq16O82t8zzv7TGsNdjBofxaeUrGVn0wRuqud8Uiw0/iiUbj0ZsJ0DLS16phZq2hWMcSEMkah/iW7Glf+Mi92QOhLX3kIAGHpne24Bb1 X-Forefront-PRVS: 0169092318 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;MWHPR03MB2480;23:nYh35iWu1NEkSiMZDScKYnqg/g1W1Ui8jwqUkx6bg?= =?us-ascii?Q?a4XJDYRWUT1dq6AIjk5qToEj2v7aEpNZaEGm+Eug/39AdFfKbURq6MYkiHBL?= =?us-ascii?Q?b+mq5giOX/mUSFB8qzcdU/oi8ubqCTKQrBTkWXm97xanL5MQbTeVa00cZ0gz?= =?us-ascii?Q?CN5gQ1kg8LfYW9GlfAAB0LMU/Jpuxq0lJxNHfNeWUPeIb2wNkaGtk346sVi9?= =?us-ascii?Q?jdIdCqdGVuB57PMXjI4Bk+1XIZlvf0aLUcQnkvt09ssGa6m5BgDLVZHSXZ5Y?= =?us-ascii?Q?9otZaNMkH3gDrAC2EpvrjSRaZ7q8ht0f/sJyrTLGgEBCavPk+UTcsNU1Cmka?= =?us-ascii?Q?WQ2g+xL3OnCviPwDR6TVt2qkWKEOX2L19PnjMT8Y0qWh1sB7W9y1IYYZ3GK7?= =?us-ascii?Q?dISmWK4bKNJFQo5AiJdEtCdz1soHnDsNYyWJojpT8Ccbaml/BO/q2F8KXjOC?= =?us-ascii?Q?eVlwuz13/QGa9dut6ukbdH6UAfRWg1Fhiq/gqaKw9CVqIlDaWR7QEf+JCc1B?= =?us-ascii?Q?y+bYJWBb4bZiGlnhKcQKvUPsQzvazAWVhvB5cCYGcuocHTwNmorz7lXuSUng?= =?us-ascii?Q?WV9SW5HOjL7Js2nGfiUIQlXE0rOS2nbSU9l7y9F4rmWVKSxw8W4A6XMtBl3w?= =?us-ascii?Q?rt+beR3BT9Q7J49IqmC/MgJflqN3Izvu656L1Ms8Wz3LCXmlNvQO9Ti0Wzk6?= =?us-ascii?Q?tNSVnUPMp33BrHJ5nqfPomNkSSEV/fM54BI5gMfhtvgUPRlWdl0FwArCGDuE?= =?us-ascii?Q?craFI+6vkMsNC1N7kqFmK7bwAq1vzOEd/l9k1PFFE/VLCyPsPzaeg4YAxd5N?= =?us-ascii?Q?WWvxo8gpuIaCz3hvKd2EBWeywF9HhkrlVf0FpRmbbcgQnRMo/BhUSXR3iAL1?= =?us-ascii?Q?2/ca/lYlLuAZW2Ge9XYvFV8yPpJWcNgFsUPrlhRtj0kJQtZpLJnqS5IZkgWI?= =?us-ascii?Q?rou8wQ2ixGFgB2I/M4iGHWHLBWR5u+4Cv2uUKrWoIohvadT1THYKQrC/1eGu?= =?us-ascii?Q?a7WrdVG/a9vxP6/ALstLPIg2onQIq9xp1f63lA8CfMHEH6gSMdWaELHFTaXg?= =?us-ascii?Q?wV13xgqP8wm7C5TRJSQEYh7sH75ZhlR2NToB2Be2qQG4Leri+3mlS3hylufr?= =?us-ascii?Q?bBQZyOjwNoAp9wIisawSyprVVf6erqjJblxsuTfXBYReq0Y/ctmXXreU9Bgt?= =?us-ascii?Q?m3qDAfOFtg+p854igknSFn8kzWtj4PSMYQY8OMjXb5JKafvAvN0XoFFRAWlq?= =?us-ascii?Q?cXk9VP8MvwlEmx2DO9rlGvcfnYqjLWvzOWfYsb4om6jsKSZlOe1eQ8DNtWf6?= =?us-ascii?Q?mrQJU8ADZqL8/f0yeT3QIM=3D?= X-Microsoft-Exchange-Diagnostics: 1;MWHPR03MB2480;6:Hop9iGiYWMXflZHyp8J1yGYc/PGc8Jy8Uqu6JKCy7hj6pQRbA9qMn8745bM2YipcHLDWWD2XlJvfcAMZYv8pnCorcBXoo+edjRIbthhY+CgBDqtSLpa3r9Oj/FpMF9LNypTrK20f0aOtiNiLQ+xxk/q/saRbr36jub8HLwPTi2GZm0y1qzo1XTM0agmQvje2IfLnpo3rdrO0GU3fZlDPVSia71/j0dInxJ8Gnt0rMcseNGankDntU3XlfAV3oh6Rr3pDvISWb8un/f8YCmVJ9CgdO67RMEfWPGLZs+OuZLfsHZpFNqxqowQwMxbLvsARj7AL7JSKgXHA45sDgBpWn7D0LWKxgYsys9zhDHe/G/dzpMSNQ2/rh+aB2tiXIkrhs9oYiueeiZfK5limr5PxyOfOVQeGoL7Xt5f6bh3Ugku/USdUDrD/D+Eaf5PxiLJ2;5:+PzEW1V0kEE9gXcDvqNIA9tvW1lLKgLY2s6qtzIBCq9qDl5bMNugnz/s+PzjwTzU8OeqJBSB/v1TGClrzgBs5COTtW5ALzlCvU05nQD4Mqb6AcVyV35IzijHGiETCcMbNJx3ljL+vibCRgoixazL3RRjkTqfwn1Y/S6TuLUnPw1mEFvUg7YUJqsheo7fTTuD;24:KW0+LYm4Hm5TMCujm4cTpN1iWHXc3CNFrpqicO7GHLkWqqFTtl1p6t0YwXb1UWmCKxWxZpDpMidjzYuHGo9UNnFiH4iQj16Zsm1PQxGDrps= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;MWHPR03MB2480;7:DKRa/wnkBRsRKq+QVHH6D3nXX59B2j4ZQvUWjh27wj2moWGH2n2eHd42axMQVfP/a1s3j5Xg4fsZ3U7On6Dbyi6+CU5eWX9bUzHe7Bbl7dOROlnANUlLKAFJv7OPovvNMsjUgSEuChdaCnMgBXsJSGr8fP8cGmp3pi0ZXY/eNG44kjD8vxXR5E/VEKgVoSbHDBJAOBwi8GmJpQq06SevdXmAbcPdANvaP+FmN+11OUGooiymDB34VbjJ3OqXnxMHiKvNWaB2jOYpXWg/nIYL+rTILBIFPA4mC6CS75El1SZHggq8Uy1SpGow4DEDl1uDEeYeV2jKFfLc0wePoiaGVI8hAvXfhbfnpiJ2UTRC9MEZH6N9MPZz9aRC+SwocV3+5raunuwfLoi7PmRxw/sDenEGSNE8h2qrigq/bS1AUOzTJ+KeMQXi4jzWNlAhUJLkBgklPiN2jI2oK8GI/DRGjA== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Dec 2016 09:11:12.0377 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR03MB2480 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9192 Lines: 296 LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC SPI interrupt and provides 32 MSI interrupts. Compared to previous MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and total MSI interrupt number is changed to 128. The patch adds structure 'ls_scfg_msir' to describe MSIR setting and 'ibs_shift' to store the different value between the SoCs. Signed-off-by: Minghuan Lian --- .../interrupt-controller/fsl,ls-scfg-msi.txt | 2 +- drivers/irqchip/irq-ls-scfg-msi.c | 161 ++++++++++++++++----- 2 files changed, 127 insertions(+), 36 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt index 54597b0..dde4552 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt @@ -6,7 +6,7 @@ Required properties: Layerscape PCIe MSI controller block such as: "fsl,ls1021a-msi" "fsl,ls1043a-msi" - "fsl,ls1046a-msi" + "fsl,ls1046a-msi" - msi-controller: indicates that this is a PCIe MSI controller node - reg: physical base address of the controller and length of memory mapped. - interrupts: an interrupt to the parent interrupt controller. diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index cef67cc..67547bd 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c @@ -17,13 +17,24 @@ #include #include #include +#include #include #include #include -#define MSI_MAX_IRQS 32 -#define MSI_IBS_SHIFT 3 -#define MSIR 4 +#define MSI_IRQS_PER_MSIR 32 +#define MSI_MSIR_OFFSET 4 + +struct ls_scfg_msi_cfg { + u32 ibs_shift; /* Shift of interrupt bit select */ +}; + +struct ls_scfg_msir { + struct ls_scfg_msi *msi_data; + unsigned int index; + unsigned int gic_irq; + void __iomem *reg; +}; struct ls_scfg_msi { spinlock_t lock; @@ -32,8 +43,11 @@ struct ls_scfg_msi { struct irq_domain *msi_domain; void __iomem *regs; phys_addr_t msiir_addr; - int irq; - DECLARE_BITMAP(used, MSI_MAX_IRQS); + struct ls_scfg_msi_cfg *cfg; + u32 msir_num; + struct ls_scfg_msir *msir; + u32 irqs_num; + unsigned long *used; }; static struct irq_chip ls_scfg_msi_irq_chip = { @@ -55,7 +69,7 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) msg->address_hi = upper_32_bits(msi_data->msiir_addr); msg->address_lo = lower_32_bits(msi_data->msiir_addr); - msg->data = data->hwirq << MSI_IBS_SHIFT; + msg->data = data->hwirq; } static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, @@ -81,8 +95,8 @@ static int ls_scfg_msi_domain_irq_alloc(struct irq_domain *domain, WARN_ON(nr_irqs != 1); spin_lock(&msi_data->lock); - pos = find_first_zero_bit(msi_data->used, MSI_MAX_IRQS); - if (pos < MSI_MAX_IRQS) + pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num); + if (pos < msi_data->irqs_num) __set_bit(pos, msi_data->used); else err = -ENOSPC; @@ -106,7 +120,7 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain, int pos; pos = d->hwirq; - if (pos < 0 || pos >= MSI_MAX_IRQS) { + if (pos < 0 || pos >= msi_data->irqs_num) { pr_err("failed to teardown msi. Invalid hwirq %d\n", pos); return; } @@ -123,15 +137,17 @@ static void ls_scfg_msi_domain_irq_free(struct irq_domain *domain, static void ls_scfg_msi_irq_handler(struct irq_desc *desc) { - struct ls_scfg_msi *msi_data = irq_desc_get_handler_data(desc); + struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc); + struct ls_scfg_msi *msi_data = msir->msi_data; unsigned long val; - int pos, virq; + int pos, virq, hwirq; chained_irq_enter(irq_desc_get_chip(desc), desc); - val = ioread32be(msi_data->regs + MSIR); - for_each_set_bit(pos, &val, MSI_MAX_IRQS) { - virq = irq_find_mapping(msi_data->parent, (31 - pos)); + val = ioread32be(msir->reg); + for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) { + hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index; + virq = irq_find_mapping(msi_data->parent, hwirq); if (virq) generic_handle_irq(virq); } @@ -143,7 +159,7 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data) { /* Initialize MSI domain parent */ msi_data->parent = irq_domain_add_linear(NULL, - MSI_MAX_IRQS, + msi_data->irqs_num, &ls_scfg_msi_domain_ops, msi_data); if (!msi_data->parent) { @@ -164,16 +180,83 @@ static int ls_scfg_msi_domains_init(struct ls_scfg_msi *msi_data) return 0; } +static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index) +{ + struct ls_scfg_msir *msir; + int virq, i, hwirq; + + virq = platform_get_irq(msi_data->pdev, index); + if (virq <= 0) + return -ENODEV; + + msir = &msi_data->msir[index]; + msir->index = index; + msir->msi_data = msi_data; + msir->gic_irq = virq; + msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index; + + irq_set_chained_handler_and_data(msir->gic_irq, + ls_scfg_msi_irq_handler, + msir); + + /* Release the hwirqs corresponding to this MSIR */ + for (i = 0; i < MSI_IRQS_PER_MSIR; i++) { + hwirq = i << msi_data->cfg->ibs_shift | msir->index; + bitmap_clear(msi_data->used, hwirq, 1); + } + + return 0; +} + +static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir) +{ + struct ls_scfg_msi *msi_data = msir->msi_data; + int i, hwirq; + + if (msir->gic_irq > 0) + irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL); + + for (i = 0; i < MSI_IRQS_PER_MSIR; i++) { + hwirq = i << msi_data->cfg->ibs_shift | msir->index; + bitmap_set(msi_data->used, hwirq, 1); + } + + return 0; +} + +static struct ls_scfg_msi_cfg ls1021_msi_cfg = { + .ibs_shift = 3, +}; + +static struct ls_scfg_msi_cfg ls1046_msi_cfg = { + .ibs_shift = 2, +}; + +static const struct of_device_id ls_scfg_msi_id[] = { + { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg }, + { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg }, + { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg }, + {}, +}; +MODULE_DEVICE_TABLE(of, ls_scfg_msi_id); + static int ls_scfg_msi_probe(struct platform_device *pdev) { + const struct of_device_id *match; struct ls_scfg_msi *msi_data; struct resource *res; - int ret; + int i, ret; + + match = of_match_device(ls_scfg_msi_id, &pdev->dev); + if (!match) + return -ENODEV; msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); if (!msi_data) return -ENOMEM; + msi_data->cfg = (struct ls_scfg_msi_cfg *) match->data; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); msi_data->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(msi_data->regs)) { @@ -182,23 +265,37 @@ static int ls_scfg_msi_probe(struct platform_device *pdev) } msi_data->msiir_addr = res->start; - msi_data->irq = platform_get_irq(pdev, 0); - if (msi_data->irq <= 0) { - dev_err(&pdev->dev, "failed to get MSI irq\n"); - return -ENODEV; - } - msi_data->pdev = pdev; spin_lock_init(&msi_data->lock); + msi_data->irqs_num = MSI_IRQS_PER_MSIR * + (1 << msi_data->cfg->ibs_shift); + msi_data->used = devm_kcalloc(&pdev->dev, + BITS_TO_LONGS(msi_data->irqs_num), + sizeof(*msi_data->used), + GFP_KERNEL); + if (!msi_data->used) + return -ENOMEM; + /* + * Reserve all the hwirqs + * The available hwirqs will be released in ls1_msi_setup_hwirq() + */ + bitmap_set(msi_data->used, 0, msi_data->irqs_num); + + msi_data->msir_num = of_irq_count(pdev->dev.of_node); + msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num, + sizeof(*msi_data->msir), + GFP_KERNEL); + if (!msi_data->msir) + return -ENOMEM; + + for (i = 0; i < msi_data->msir_num; i++) + ls_scfg_msi_setup_hwirq(msi_data, i); + ret = ls_scfg_msi_domains_init(msi_data); if (ret) return ret; - irq_set_chained_handler_and_data(msi_data->irq, - ls_scfg_msi_irq_handler, - msi_data); - platform_set_drvdata(pdev, msi_data); return 0; @@ -207,8 +304,10 @@ static int ls_scfg_msi_probe(struct platform_device *pdev) static int ls_scfg_msi_remove(struct platform_device *pdev) { struct ls_scfg_msi *msi_data = platform_get_drvdata(pdev); + int i; - irq_set_chained_handler_and_data(msi_data->irq, NULL, NULL); + for (i = 0; i < msi_data->msir_num; i++) + ls_scfg_msi_teardown_hwirq(&msi_data->msir[i]); irq_domain_remove(msi_data->msi_domain); irq_domain_remove(msi_data->parent); @@ -218,14 +317,6 @@ static int ls_scfg_msi_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ls_scfg_msi_id[] = { - { .compatible = "fsl,1s1021a-msi", }, /* a typo */ - { .compatible = "fsl,1s1043a-msi", }, /* a typo */ - { .compatible = "fsl,ls1021a-msi", }, - { .compatible = "fsl,ls1043a-msi", }, - {}, -}; - static struct platform_driver ls_scfg_msi_driver = { .driver = { .name = "ls-scfg-msi", -- 1.9.1