From patchwork Tue Aug 2 01:57:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qiang Zhao X-Patchwork-Id: 654473 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3s3KRC5gLfz9sxb for ; Tue, 2 Aug 2016 12:10:15 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3s3KRC4vv7zDrJS for ; Tue, 2 Aug 2016 12:10:15 +1000 (AEST) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from NAM03-CO1-obe.outbound.protection.outlook.com (mail-co1nam03on0054.outbound.protection.outlook.com [104.47.40.54]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3s3KPk1svFzDqcg for ; Tue, 2 Aug 2016 12:08:57 +1000 (AEST) Received: from BN6PR03CA0028.namprd03.prod.outlook.com (10.175.124.14) by DM2PR0301MB0702.namprd03.prod.outlook.com (10.160.96.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.549.15; Tue, 2 Aug 2016 02:08:51 +0000 Received: from BN1BFFO11FD042.protection.gbl (2a01:111:f400:7c10::1:168) by BN6PR03CA0028.outlook.office365.com (2603:10b6:404:10c::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.549.15 via Frontend Transport; Tue, 2 Aug 2016 02:08:51 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) 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; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BN1BFFO11FD042.mail.protection.outlook.com (10.58.144.105) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.549.5 via Frontend Transport; Tue, 2 Aug 2016 02:08:52 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id u7228mLI014918; Mon, 1 Aug 2016 19:08:49 -0700 From: Zhao Qiang To: Subject: [PATCH v5 1/3] irqchip/qeic: move qeic driver from drivers/soc/fsl/qe Date: Tue, 2 Aug 2016 09:57:34 +0800 Message-ID: <1470103056-41711-1-git-send-email-qiang.zhao@nxp.com> X-Mailer: git-send-email 2.1.0.27.g96db324 X-EOPAttributedMessage: 0 X-Matching-Connectors: 131145773324488087; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.158.2; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(1110001)(1109001)(339900001)(199003)(189002)(4326007)(105606002)(11100500001)(69596002)(19580405001)(47776003)(19580395003)(5003940100001)(586003)(2906002)(50986999)(85426001)(104016004)(8666005)(356003)(68736007)(97736004)(77096005)(189998001)(110136002)(50466002)(48376002)(87936001)(50226002)(305945005)(7846002)(86362001)(575784001)(8676002)(81156014)(81166006)(8936002)(2351001)(33646002)(36756003)(229853001)(92566002)(106466001)(7059030)(2004002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR0301MB0702; H:az84smr01.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BN1BFFO11FD042; 1:Hug7v2jFsErkT8BYrJKkOT/lhEYv9k9v+MMZRnUzQJxV3ifAq/l1coUcX6xldbNKbUar8iqSsvwt/6o4L2+iaCG0aci757JwS+DuCqGd/XJe7YdYFcDzEIgcZwm9X2i5fraUQJgqvhnZRV1FR/631Wz6L91nlzLNQjDv6UmDZmcRHlEnfNxqaaNkoGoFy/7glXfxW12ceAWn/7PLVROtFk3JmrGMUFs6I7a+pkcyVodtnD8Y/d2ilA0JAlg5IbU+20xxT9WQgGOIHhAK81XB77KROyAZ+fC7kQOsU0HzdhQxEw8PIdnMMAu2V93Gd+JepR706v6gVxS+1pSSozuLLBvHC1kFPO3PwDQtIe99+BETfpbwzVo96/OALUZ8Wg7AxvSH7aIM2Ly83b0eFCcUBBqSmtNPHrNpFXA5KLIkaazvDBGyIbYbBAo0VZtq6D5xVDhfoTXEV2vVSmsgyYV2/fSWwpjOeeJGFSEiUb7FMCF6yVl5fY++tbSaQtby9IXpnFePe6dql+XHAVmcCP3h1Z7z8ImBQj66dFfE7s+SKhOVdKuVwdt1REQDeoAlj0EumV3OXucMCkAsIG7dFjtuZn6ossBFQObyWz+7afuVz/xWvxGVCTkLsWLPSK3V7CVS9gzGMt8HrrF4tpyM/aCPhz7IBMpNclmIoqM8tKX1+rn9OgFdFL8eoowyGzgEuQoczIuITgdyUG+u1NhbIfgEOP+S0JJqD1dunZ5iaiQYMBY= MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: f0589b69-ba9b-45ba-cd97-08d3ba79f343 X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0702; 2:DIkTih6s38Ys0aS1XZ/AlSQWlHMiX19+TLP0RCzIXYAOFfW2cIdMtB7jDm1dXZaEYi8sc2CUF9XieTWO2DHDiXxw9mVwZv87Nzu7MVQMP4kF8lzIaNjBo+sAq51AmksOYP0YSwMluiV9I/1Vl6niabKyAN09lG+SgCVZT6y/uQkK9PBMrTa4MU8g8DIy7ozh; 3:uE/kpOWlTYT8zS9tFUa3tP9LNicyAPqTGO/aP6W5DTaoHKyEh0eFKf9WiROyFJ3pvg+560xv+5G6qpQag6czmC86j1yYUFZd8W89y2t3jcS2xSBv2eE0UE+AAV28XrW8mNQJEzqAE+selXPDAH9f6PmFHkUeyrq5rYyDcet90TjglpC9r66ruVcinRgbvizWKAxEePJBYKNGL4fI8OTV5M7G/+iB45dYmewlBGuQTpk=; 25:IY5t0jXtPoZymZU8NsMl5TZw4oSAA+8nWACSRD8YoJ6CzrRhUqPMe+ieyRow7ke2tnshcm/xMxgNblkckEy+OH7U9JFVquFsfl/7+/8ZKlJBSH31bWhQ/9BjV1qMgaMsRGzCTbbv/gE7hAF9Ka2wbkchCnETT+sOlDerymfSubPtig0bdw0jw1zf8leaI3Y7qkPOrRaOs14JKTASpUaspVeu4fXDTpX8CeKrucsGtgek9nekjPHoakDw+DA2QuYpokCr9+ws81xzrccRnS5IyAbMhZo1JJ9BdDBcE7ot5Cp4pRIEyhWZ0La/fxwXAWzEcJNAXS9xaITcag5ff8GFxd0BBd9fTj5xFP4mI1K/SZ7+BrOZhXRGCFYLaJwpAQ+Trc7ErjpbI2+3KyeeI5V+iXfHQDj7tSb/wYGIbOqMxo8= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM2PR0301MB0702; X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0702; 31:/qCu72cRkyW6AbzsqKc9cvl3mTjnpUS76v158zMyj8F9HGTYQI3jF+znWairIazF8RVY4bOAgh1FDR/c63kfS7N1zg4Se56wfyNRRBlqwoOwRg0LvFPRkMQyR0ILEboMtVQUE0A8VTEJVcB1DuOe4jLdgEVnTIcXxSk+myoyu7ZPPVbjVdwJRIDjj9tD/jmUUpmLggEENIWNxwrzmqxIgJMaFh5A7NmDhN1PIzHqe9s=; 4:Fr22MC5UGOFYhIkx8lqUx7HNRaw0MT6pKaF/Av14rRAcUhXp9dP78Zs5tnzz9cme1a2kiKTQwySyBQpiWGMs8FnnElx7vzt40G3BlTIryuWt2ndNSNnB9JqiwUlX5QB3L+TyWVkT7cKlkc4yl71tOfVzLtI/d80dkHRQglk5zTyURoO8lOIAjbQQJwp2azyp4jA8jR4fpy9+MUKf3EIFrWKzQD8QtRDwQnte2qihlItf/Le3bTtgr743FRALNVUiS0Vqgo3/NhcllaDGGC10HyIeTtQ7WR+HFFdySafPfkEphjyRdk+FJLMbXd4HpwaKEP2/3jh/GMRrbKLZqI5aZy3V7/cZFoDUVqVtJAHUGaE+nfs1NnOSLDUVvwr1Sq+EKmiv8l6SxpDANr+iZK4UDeeIsWjHAgFNlW5E877zmbK9XWfqVqwlzeCPoK2u2PCCl4TUzcZKN7hgBlY3qyWLeX+HwCPiAtISRV+rUOmRrp21wDydIJwOs19opRzAJouv2JMkfP+4eBk7QTqeX/vghMFnLC1cavY6uX1rXXftPT49SszSOqtMz8sdrxNxK9Aa X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197)(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13024025)(8121501046)(13018025)(13023025)(13017025)(13015025)(5005006)(10201501046)(3002001)(6055026); SRVR:DM2PR0301MB0702; BCL:0; PCL:0; RULEID:(400006); SRVR:DM2PR0301MB0702; X-Forefront-PRVS: 0022134A87 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM2PR0301MB0702; 23:5B+hzcUxXkE+tbuZ02sx7RJ6TAv4NmhHtQGL8ma?= =?us-ascii?Q?2xuqiOgv5+s7rM0AFYbLJUyamoLxN+49EPmlalxx9v+EeCJh6WNNkw2oM95+?= =?us-ascii?Q?xoHyXLMA65Ckvh5CBk3+y2+5PK8wxhCTsaS+D9+GK1rLjEwt3VuXEeCTrSrK?= =?us-ascii?Q?seumjGXziUL50zR2QIFuO/kFRapeRTWZZKmbbknHoT2IuLxoH/kvKdPveDi4?= =?us-ascii?Q?JjjZXm2H3qYj+vQNvSdv7HbUFcNqBd/ZgZ/ZMCDhwwQsAiNqktpoXv887sRF?= =?us-ascii?Q?7ubb9kJ7vBmWNafXryHtqbbNcUAnG8sLbCK0Dq/xeuTJ7p5oRa42FhTjBtug?= =?us-ascii?Q?iLlW0RjKPbCCN93XDD55us49Z6vyMe9IQ1fyI7PlxKKaWJ4mHkgFE3W6EiA7?= =?us-ascii?Q?JBm5SOhF2wBfFATzbuFSheelM2chSOej1wCeP62coENjy18yotODYlbU+U/N?= =?us-ascii?Q?rnbcPja6QsUY5/5S3N0ra0h5e7rqAvOr7JP+finSEXwtBtbTKUMp+m0kzhSt?= =?us-ascii?Q?6fVcDv9k/5L/ZnQAHygH3FIIPQHqXCvTcmvHmsZ+XLd5Li43O2JfYYFgzTWO?= =?us-ascii?Q?bXWprM32B9cVpdecnOuxpmYZ2GknhuB96UHaMC29rFYVpZdVk2u52faAhq03?= =?us-ascii?Q?V/NZRSXn16XNrwkEiBQpVVcu23IL3w4ipmiLmzzM0jKQ7UF1auBfZ0WvRosk?= =?us-ascii?Q?6iAmyYE2UnvHjk06TnK4jQTs9mCeZdDbU1+jDDhPvBhRTcVpC+YqEKd7NNhM?= =?us-ascii?Q?dvAXhPAysPqqkPRgYPQHa7YSWv9zwzivvLAQWhr5ldyJPsIQXtyGlKZGfVJG?= =?us-ascii?Q?y9gBqVHPRfXnQ5EQyoFURgTuyGFw/xTnDEVBUZ9LbWnzYUUJZWO/SUBlyhY8?= =?us-ascii?Q?Kd9/tV6TR9owtZWYpdNetfEfbWTgVp8PUNnyTSz59PoCoNwElsnEVc3Rw8Ad?= =?us-ascii?Q?EFYli+pEhuteF5bYfaCEt6SNwzXobHTDLrqi0ELhwrUhbQMZ9lKHd3V6g26t?= =?us-ascii?Q?kKALRvLL9PgzNFWYEDW4ylltwYELy8ComntqPdC0TQNNIbrkWWZzq3w+SJdm?= =?us-ascii?Q?2WaZ7PsQb38a5FRPDfXZg1u2yeMYnHAG5dH9KcXpGYRPIMuzzFMa6zlw7nK5?= =?us-ascii?Q?dZD4bV9ufXA+qf76GW3D4b8oxfRTF7EE1?= X-Microsoft-Exchange-Diagnostics: 1; DM2PR0301MB0702; 6:sn0aDUfVgDXdfB/DSmu1oPf29Phk3uH04/TWIJBOiB10JDcPuYKOfEmKW9PPnngVQJMab9FAt/p5QMnoAqvTkzooED0bTKA54Dv12p12Su4VE0bfFLIQ+mB//u5zEvDGZ3Xb6XKn1JFpCEOzeRt+a2DVqqhD/qedRRhKiJwx3W9pFR9JyRuHp8VvkylRCjlQMVCd9SDSUg2fIoAHyrE/W6BcRjfynfl4lDjBeXFR8kaspDkJI6Kh4cBG/+W2WvZ4wX2p6hrOkHHWQp/2NXMScHZ+UqWtN7/9ehC7hDwwDkY=; 5:vJXNZwby3Je7P4YBYXHP/MMGe8LYkZPiDIoR8T1TaWlnYZvzJX8OQMQy0rM5+aFVaVBQdxXTsL+JIA3VySf2eRDTs6R5vC3TSh0w378oZILJ24azXBABF/wTX6nlWxQUruVAR9oaxCwye5pJ1To7t9VlMfhPCxVUfDcpQprkA9w=; 24:ydl+4kMWbzTTpvKtELBDNT86mRPFw+ymrK6wOI86Yn7P4ChobvFCmmmIuCWRWHdejyZJ0DrQginwXIXIGvyG0y73UYoR9KOhlWGtpjiBKQ0=; 7:z19GS0wZRTdJb2jcaZ/jq5dueT7TrwkmkE5cEgOuMWFEk3wzKp02iWJjynbbvV62TJCu1QOL4qmpyGZ4++5lQKD/KknTxG3UEIsGKzzi1qy2EldJ7N60KdGP9AfaVI8P7KJ9xL76uAJjvOyGxO6FQo691UiOzjBVseqPZ6MokSioll6LGqrdUw2DjrQC1/Mk6m9rdJjJQmWiAxNlDPrlKSWB+nm2LK08g9Zw9mQLLhCFj9NH/biubZW8SixId5G1 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Aug 2016 02:08:52.1836 (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.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0301MB0702 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: oss@buserror.net, Zhao Qiang , linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, xiaobo.xie@nxp.com Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" move the driver from drivers/soc/fsl/qe to drivers/irqchip, merge qe_ic.h and qe_ic.c into irq-qeic.c. Signed-off-by: Zhao Qiang --- Changes for v2: - modify the subject and commit msg Changes for v3: - merge .h file to .c, rename it with irq-qeic.c Changes for v4: - modify comments Changes for v5: - disable rename detection drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-qeic.c | 601 ++++++++++++++++++++++++++++++++++++++++++++ drivers/soc/fsl/qe/Makefile | 2 +- drivers/soc/fsl/qe/qe_ic.c | 512 ------------------------------------- drivers/soc/fsl/qe/qe_ic.h | 103 -------- 5 files changed, 603 insertions(+), 616 deletions(-) create mode 100644 drivers/irqchip/irq-qeic.c delete mode 100644 drivers/soc/fsl/qe/qe_ic.c delete mode 100644 drivers/soc/fsl/qe/qe_ic.h diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 38853a1..846b34e 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -69,3 +69,4 @@ obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o +obj-$(CONFIG_QUICC_ENGINE) += irq-qeic.o diff --git a/drivers/irqchip/irq-qeic.c b/drivers/irqchip/irq-qeic.c new file mode 100644 index 0000000..48ceded --- /dev/null +++ b/drivers/irqchip/irq-qeic.c @@ -0,0 +1,601 @@ +/* + * drivers/irqchip/irq-qeic.c + * + * Copyright (C) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * Author: Li Yang + * Based on code from Shlomi Gridish + * + * QUICC ENGINE Interrupt Controller + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NR_QE_IC_INTS 64 + +/* QE IC registers offset */ +#define QEIC_CICR 0x00 +#define QEIC_CIVEC 0x04 +#define QEIC_CRIPNR 0x08 +#define QEIC_CIPNR 0x0c +#define QEIC_CIPXCC 0x10 +#define QEIC_CIPYCC 0x14 +#define QEIC_CIPWCC 0x18 +#define QEIC_CIPZCC 0x1c +#define QEIC_CIMR 0x20 +#define QEIC_CRIMR 0x24 +#define QEIC_CICNR 0x28 +#define QEIC_CIPRTA 0x30 +#define QEIC_CIPRTB 0x34 +#define QEIC_CRICR 0x3c +#define QEIC_CHIVEC 0x60 + +/* Interrupt priority registers */ +#define CIPCC_SHIFT_PRI0 29 +#define CIPCC_SHIFT_PRI1 26 +#define CIPCC_SHIFT_PRI2 23 +#define CIPCC_SHIFT_PRI3 20 +#define CIPCC_SHIFT_PRI4 13 +#define CIPCC_SHIFT_PRI5 10 +#define CIPCC_SHIFT_PRI6 7 +#define CIPCC_SHIFT_PRI7 4 + +/* CICR priority modes */ +#define CICR_GWCC 0x00040000 +#define CICR_GXCC 0x00020000 +#define CICR_GYCC 0x00010000 +#define CICR_GZCC 0x00080000 +#define CICR_GRTA 0x00200000 +#define CICR_GRTB 0x00400000 +#define CICR_HPIT_SHIFT 8 +#define CICR_HPIT_MASK 0x00000300 +#define CICR_HP_SHIFT 24 +#define CICR_HP_MASK 0x3f000000 + +/* CICNR */ +#define CICNR_WCC1T_SHIFT 20 +#define CICNR_ZCC1T_SHIFT 28 +#define CICNR_YCC1T_SHIFT 12 +#define CICNR_XCC1T_SHIFT 4 + +/* CRICR */ +#define CRICR_RTA1T_SHIFT 20 +#define CRICR_RTB1T_SHIFT 28 + +/* Signal indicator */ +#define SIGNAL_MASK 3 +#define SIGNAL_HIGH 2 +#define SIGNAL_LOW 0 + +struct qe_ic { + /* Control registers offset */ + volatile u32 __iomem *regs; + + /* The remapper for this QEIC */ + struct irq_domain *irqhost; + + /* The "linux" controller struct */ + struct irq_chip hc_irq; + + /* VIRQ numbers of QE high/low irqs */ + unsigned int virq_high; + unsigned int virq_low; +}; + +/* + * QE interrupt controller internal structure + */ +struct qe_ic_info { + /* location of this source at the QIMR register. */ + u32 mask; + + /* Mask register offset */ + u32 mask_reg; + + /* + * for grouped interrupts sources - the interrupt + * code as appears at the group priority register + */ + u8 pri_code; + + /* Group priority register offset */ + u32 pri_reg; +}; + +static DEFINE_RAW_SPINLOCK(qe_ic_lock); + +static struct qe_ic_info qe_ic_info[] = { + [1] = { + .mask = 0x00008000, + .mask_reg = QEIC_CIMR, + .pri_code = 0, + .pri_reg = QEIC_CIPWCC, + }, + [2] = { + .mask = 0x00004000, + .mask_reg = QEIC_CIMR, + .pri_code = 1, + .pri_reg = QEIC_CIPWCC, + }, + [3] = { + .mask = 0x00002000, + .mask_reg = QEIC_CIMR, + .pri_code = 2, + .pri_reg = QEIC_CIPWCC, + }, + [10] = { + .mask = 0x00000040, + .mask_reg = QEIC_CIMR, + .pri_code = 1, + .pri_reg = QEIC_CIPZCC, + }, + [11] = { + .mask = 0x00000020, + .mask_reg = QEIC_CIMR, + .pri_code = 2, + .pri_reg = QEIC_CIPZCC, + }, + [12] = { + .mask = 0x00000010, + .mask_reg = QEIC_CIMR, + .pri_code = 3, + .pri_reg = QEIC_CIPZCC, + }, + [13] = { + .mask = 0x00000008, + .mask_reg = QEIC_CIMR, + .pri_code = 4, + .pri_reg = QEIC_CIPZCC, + }, + [14] = { + .mask = 0x00000004, + .mask_reg = QEIC_CIMR, + .pri_code = 5, + .pri_reg = QEIC_CIPZCC, + }, + [15] = { + .mask = 0x00000002, + .mask_reg = QEIC_CIMR, + .pri_code = 6, + .pri_reg = QEIC_CIPZCC, + }, + [20] = { + .mask = 0x10000000, + .mask_reg = QEIC_CRIMR, + .pri_code = 3, + .pri_reg = QEIC_CIPRTA, + }, + [25] = { + .mask = 0x00800000, + .mask_reg = QEIC_CRIMR, + .pri_code = 0, + .pri_reg = QEIC_CIPRTB, + }, + [26] = { + .mask = 0x00400000, + .mask_reg = QEIC_CRIMR, + .pri_code = 1, + .pri_reg = QEIC_CIPRTB, + }, + [27] = { + .mask = 0x00200000, + .mask_reg = QEIC_CRIMR, + .pri_code = 2, + .pri_reg = QEIC_CIPRTB, + }, + [28] = { + .mask = 0x00100000, + .mask_reg = QEIC_CRIMR, + .pri_code = 3, + .pri_reg = QEIC_CIPRTB, + }, + [32] = { + .mask = 0x80000000, + .mask_reg = QEIC_CIMR, + .pri_code = 0, + .pri_reg = QEIC_CIPXCC, + }, + [33] = { + .mask = 0x40000000, + .mask_reg = QEIC_CIMR, + .pri_code = 1, + .pri_reg = QEIC_CIPXCC, + }, + [34] = { + .mask = 0x20000000, + .mask_reg = QEIC_CIMR, + .pri_code = 2, + .pri_reg = QEIC_CIPXCC, + }, + [35] = { + .mask = 0x10000000, + .mask_reg = QEIC_CIMR, + .pri_code = 3, + .pri_reg = QEIC_CIPXCC, + }, + [36] = { + .mask = 0x08000000, + .mask_reg = QEIC_CIMR, + .pri_code = 4, + .pri_reg = QEIC_CIPXCC, + }, + [40] = { + .mask = 0x00800000, + .mask_reg = QEIC_CIMR, + .pri_code = 0, + .pri_reg = QEIC_CIPYCC, + }, + [41] = { + .mask = 0x00400000, + .mask_reg = QEIC_CIMR, + .pri_code = 1, + .pri_reg = QEIC_CIPYCC, + }, + [42] = { + .mask = 0x00200000, + .mask_reg = QEIC_CIMR, + .pri_code = 2, + .pri_reg = QEIC_CIPYCC, + }, + [43] = { + .mask = 0x00100000, + .mask_reg = QEIC_CIMR, + .pri_code = 3, + .pri_reg = QEIC_CIPYCC, + }, +}; + +static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg) +{ + return in_be32(base + (reg >> 2)); +} + +static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg, + u32 value) +{ + out_be32(base + (reg >> 2), value); +} + +static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) +{ + return irq_get_chip_data(virq); +} + +static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d) +{ + return irq_data_get_irq_chip_data(d); +} + +static void qe_ic_unmask_irq(struct irq_data *d) +{ + struct qe_ic *qe_ic = qe_ic_from_irq_data(d); + unsigned int src = irqd_to_hwirq(d); + unsigned long flags; + u32 temp; + + raw_spin_lock_irqsave(&qe_ic_lock, flags); + + temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); + qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, + temp | qe_ic_info[src].mask); + + raw_spin_unlock_irqrestore(&qe_ic_lock, flags); +} + +static void qe_ic_mask_irq(struct irq_data *d) +{ + struct qe_ic *qe_ic = qe_ic_from_irq_data(d); + unsigned int src = irqd_to_hwirq(d); + unsigned long flags; + u32 temp; + + raw_spin_lock_irqsave(&qe_ic_lock, flags); + + temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); + qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, + temp & ~qe_ic_info[src].mask); + + /* Flush the above write before enabling interrupts; otherwise, + * spurious interrupts will sometimes happen. To be 100% sure + * that the write has reached the device before interrupts are + * enabled, the mask register would have to be read back; however, + * this is not required for correctness, only to avoid wasting + * time on a large number of spurious interrupts. In testing, + * a sync reduced the observed spurious interrupts to zero. + */ + mb(); + + raw_spin_unlock_irqrestore(&qe_ic_lock, flags); +} + +static struct irq_chip qe_ic_irq_chip = { + .name = "QEIC", + .irq_unmask = qe_ic_unmask_irq, + .irq_mask = qe_ic_mask_irq, + .irq_mask_ack = qe_ic_mask_irq, +}; + +static int qe_ic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) +{ + /* Exact match, unless qe_ic node is NULL */ + struct device_node *of_node = irq_domain_get_of_node(h); + return of_node == NULL || of_node == node; +} + +static int qe_ic_host_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct qe_ic *qe_ic = h->host_data; + struct irq_chip *chip; + + if (hw >= ARRAY_SIZE(qe_ic_info)) { + pr_err("%s: Invalid hw irq number for QEIC\n", __func__); + return -EINVAL; + } + + if (qe_ic_info[hw].mask == 0) { + printk(KERN_ERR "Can't map reserved IRQ\n"); + return -EINVAL; + } + /* Default chip */ + chip = &qe_ic->hc_irq; + + irq_set_chip_data(virq, qe_ic); + irq_set_status_flags(virq, IRQ_LEVEL); + + irq_set_chip_and_handler(virq, chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops qe_ic_host_ops = { + .match = qe_ic_host_match, + .map = qe_ic_host_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) +{ + int irq; + + BUG_ON(qe_ic == NULL); + + /* get the interrupt source vector. */ + irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26; + + if (irq == 0) + return NO_IRQ; + + return irq_linear_revmap(qe_ic->irqhost, irq); +} + +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) +{ + int irq; + + BUG_ON(qe_ic == NULL); + + /* get the interrupt source vector. */ + irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26; + + if (irq == 0) + return NO_IRQ; + + return irq_linear_revmap(qe_ic->irqhost, irq); +} + +void __init qe_ic_init(struct device_node *node, unsigned int flags, + void (*low_handler)(struct irq_desc *desc), + void (*high_handler)(struct irq_desc *desc)) +{ + struct qe_ic *qe_ic; + struct resource res; + u32 temp = 0, ret, high_active = 0; + + ret = of_address_to_resource(node, 0, &res); + if (ret) + return; + + qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL); + if (qe_ic == NULL) + return; + + qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS, + &qe_ic_host_ops, qe_ic); + if (qe_ic->irqhost == NULL) { + kfree(qe_ic); + return; + } + + qe_ic->regs = ioremap(res.start, resource_size(&res)); + + qe_ic->hc_irq = qe_ic_irq_chip; + + qe_ic->virq_high = irq_of_parse_and_map(node, 0); + qe_ic->virq_low = irq_of_parse_and_map(node, 1); + + if (qe_ic->virq_low == NO_IRQ) { + printk(KERN_ERR "Failed to map QE_IC low IRQ\n"); + kfree(qe_ic); + return; + } + + /* default priority scheme is grouped. If spread mode is */ + /* required, configure cicr accordingly. */ + if (flags & QE_IC_SPREADMODE_GRP_W) + temp |= CICR_GWCC; + if (flags & QE_IC_SPREADMODE_GRP_X) + temp |= CICR_GXCC; + if (flags & QE_IC_SPREADMODE_GRP_Y) + temp |= CICR_GYCC; + if (flags & QE_IC_SPREADMODE_GRP_Z) + temp |= CICR_GZCC; + if (flags & QE_IC_SPREADMODE_GRP_RISCA) + temp |= CICR_GRTA; + if (flags & QE_IC_SPREADMODE_GRP_RISCB) + temp |= CICR_GRTB; + + /* choose destination signal for highest priority interrupt */ + if (flags & QE_IC_HIGH_SIGNAL) { + temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT); + high_active = 1; + } + + qe_ic_write(qe_ic->regs, QEIC_CICR, temp); + + irq_set_handler_data(qe_ic->virq_low, qe_ic); + irq_set_chained_handler(qe_ic->virq_low, low_handler); + + if (qe_ic->virq_high != NO_IRQ && + qe_ic->virq_high != qe_ic->virq_low) { + irq_set_handler_data(qe_ic->virq_high, qe_ic); + irq_set_chained_handler(qe_ic->virq_high, high_handler); + } +} + +void qe_ic_set_highest_priority(unsigned int virq, int high) +{ + struct qe_ic *qe_ic = qe_ic_from_irq(virq); + unsigned int src = virq_to_hw(virq); + u32 temp = 0; + + temp = qe_ic_read(qe_ic->regs, QEIC_CICR); + + temp &= ~CICR_HP_MASK; + temp |= src << CICR_HP_SHIFT; + + temp &= ~CICR_HPIT_MASK; + temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT; + + qe_ic_write(qe_ic->regs, QEIC_CICR, temp); +} + +/* Set Priority level within its group, from 1 to 8 */ +int qe_ic_set_priority(unsigned int virq, unsigned int priority) +{ + struct qe_ic *qe_ic = qe_ic_from_irq(virq); + unsigned int src = virq_to_hw(virq); + u32 temp; + + if (priority > 8 || priority == 0) + return -EINVAL; + if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), + "%s: Invalid hw irq number for QEIC\n", __func__)) + return -EINVAL; + if (qe_ic_info[src].pri_reg == 0) + return -EINVAL; + + temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg); + + if (priority < 4) { + temp &= ~(0x7 << (32 - priority * 3)); + temp |= qe_ic_info[src].pri_code << (32 - priority * 3); + } else { + temp &= ~(0x7 << (24 - priority * 3)); + temp |= qe_ic_info[src].pri_code << (24 - priority * 3); + } + + qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp); + + return 0; +} + +/* Set a QE priority to use high irq, only priority 1~2 can use high irq */ +int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high) +{ + struct qe_ic *qe_ic = qe_ic_from_irq(virq); + unsigned int src = virq_to_hw(virq); + u32 temp, control_reg = QEIC_CICNR, shift = 0; + + if (priority > 2 || priority == 0) + return -EINVAL; + if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), + "%s: Invalid hw irq number for QEIC\n", __func__)) + return -EINVAL; + + switch (qe_ic_info[src].pri_reg) { + case QEIC_CIPZCC: + shift = CICNR_ZCC1T_SHIFT; + break; + case QEIC_CIPWCC: + shift = CICNR_WCC1T_SHIFT; + break; + case QEIC_CIPYCC: + shift = CICNR_YCC1T_SHIFT; + break; + case QEIC_CIPXCC: + shift = CICNR_XCC1T_SHIFT; + break; + case QEIC_CIPRTA: + shift = CRICR_RTA1T_SHIFT; + control_reg = QEIC_CRICR; + break; + case QEIC_CIPRTB: + shift = CRICR_RTB1T_SHIFT; + control_reg = QEIC_CRICR; + break; + default: + return -EINVAL; + } + + shift += (2 - priority) * 2; + temp = qe_ic_read(qe_ic->regs, control_reg); + temp &= ~(SIGNAL_MASK << shift); + temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift; + qe_ic_write(qe_ic->regs, control_reg, temp); + + return 0; +} + +static struct bus_type qe_ic_subsys = { + .name = "qe_ic", + .dev_name = "qe_ic", +}; + +static struct device device_qe_ic = { + .id = 0, + .bus = &qe_ic_subsys, +}; + +static int __init init_qe_ic_sysfs(void) +{ + int rc; + + printk(KERN_DEBUG "Registering qe_ic with sysfs...\n"); + + rc = subsys_system_register(&qe_ic_subsys, NULL); + if (rc) { + printk(KERN_ERR "Failed registering qe_ic sys class\n"); + return -ENODEV; + } + rc = device_register(&device_qe_ic); + if (rc) { + printk(KERN_ERR "Failed registering qe_ic sys device\n"); + return -ENODEV; + } + return 0; +} + +subsys_initcall(init_qe_ic_sysfs); diff --git a/drivers/soc/fsl/qe/Makefile b/drivers/soc/fsl/qe/Makefile index 2031d38..51e4726 100644 --- a/drivers/soc/fsl/qe/Makefile +++ b/drivers/soc/fsl/qe/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux ppc-specific parts of QE # -obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o +obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_io.o obj-$(CONFIG_CPM) += qe_common.o obj-$(CONFIG_UCC) += ucc.o obj-$(CONFIG_UCC_SLOW) += ucc_slow.o diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c deleted file mode 100644 index ec2ca86..0000000 --- a/drivers/soc/fsl/qe/qe_ic.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * arch/powerpc/sysdev/qe_lib/qe_ic.c - * - * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Li Yang - * Based on code from Shlomi Gridish - * - * QUICC ENGINE Interrupt Controller - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qe_ic.h" - -static DEFINE_RAW_SPINLOCK(qe_ic_lock); - -static struct qe_ic_info qe_ic_info[] = { - [1] = { - .mask = 0x00008000, - .mask_reg = QEIC_CIMR, - .pri_code = 0, - .pri_reg = QEIC_CIPWCC, - }, - [2] = { - .mask = 0x00004000, - .mask_reg = QEIC_CIMR, - .pri_code = 1, - .pri_reg = QEIC_CIPWCC, - }, - [3] = { - .mask = 0x00002000, - .mask_reg = QEIC_CIMR, - .pri_code = 2, - .pri_reg = QEIC_CIPWCC, - }, - [10] = { - .mask = 0x00000040, - .mask_reg = QEIC_CIMR, - .pri_code = 1, - .pri_reg = QEIC_CIPZCC, - }, - [11] = { - .mask = 0x00000020, - .mask_reg = QEIC_CIMR, - .pri_code = 2, - .pri_reg = QEIC_CIPZCC, - }, - [12] = { - .mask = 0x00000010, - .mask_reg = QEIC_CIMR, - .pri_code = 3, - .pri_reg = QEIC_CIPZCC, - }, - [13] = { - .mask = 0x00000008, - .mask_reg = QEIC_CIMR, - .pri_code = 4, - .pri_reg = QEIC_CIPZCC, - }, - [14] = { - .mask = 0x00000004, - .mask_reg = QEIC_CIMR, - .pri_code = 5, - .pri_reg = QEIC_CIPZCC, - }, - [15] = { - .mask = 0x00000002, - .mask_reg = QEIC_CIMR, - .pri_code = 6, - .pri_reg = QEIC_CIPZCC, - }, - [20] = { - .mask = 0x10000000, - .mask_reg = QEIC_CRIMR, - .pri_code = 3, - .pri_reg = QEIC_CIPRTA, - }, - [25] = { - .mask = 0x00800000, - .mask_reg = QEIC_CRIMR, - .pri_code = 0, - .pri_reg = QEIC_CIPRTB, - }, - [26] = { - .mask = 0x00400000, - .mask_reg = QEIC_CRIMR, - .pri_code = 1, - .pri_reg = QEIC_CIPRTB, - }, - [27] = { - .mask = 0x00200000, - .mask_reg = QEIC_CRIMR, - .pri_code = 2, - .pri_reg = QEIC_CIPRTB, - }, - [28] = { - .mask = 0x00100000, - .mask_reg = QEIC_CRIMR, - .pri_code = 3, - .pri_reg = QEIC_CIPRTB, - }, - [32] = { - .mask = 0x80000000, - .mask_reg = QEIC_CIMR, - .pri_code = 0, - .pri_reg = QEIC_CIPXCC, - }, - [33] = { - .mask = 0x40000000, - .mask_reg = QEIC_CIMR, - .pri_code = 1, - .pri_reg = QEIC_CIPXCC, - }, - [34] = { - .mask = 0x20000000, - .mask_reg = QEIC_CIMR, - .pri_code = 2, - .pri_reg = QEIC_CIPXCC, - }, - [35] = { - .mask = 0x10000000, - .mask_reg = QEIC_CIMR, - .pri_code = 3, - .pri_reg = QEIC_CIPXCC, - }, - [36] = { - .mask = 0x08000000, - .mask_reg = QEIC_CIMR, - .pri_code = 4, - .pri_reg = QEIC_CIPXCC, - }, - [40] = { - .mask = 0x00800000, - .mask_reg = QEIC_CIMR, - .pri_code = 0, - .pri_reg = QEIC_CIPYCC, - }, - [41] = { - .mask = 0x00400000, - .mask_reg = QEIC_CIMR, - .pri_code = 1, - .pri_reg = QEIC_CIPYCC, - }, - [42] = { - .mask = 0x00200000, - .mask_reg = QEIC_CIMR, - .pri_code = 2, - .pri_reg = QEIC_CIPYCC, - }, - [43] = { - .mask = 0x00100000, - .mask_reg = QEIC_CIMR, - .pri_code = 3, - .pri_reg = QEIC_CIPYCC, - }, -}; - -static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg) -{ - return in_be32(base + (reg >> 2)); -} - -static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg, - u32 value) -{ - out_be32(base + (reg >> 2), value); -} - -static inline struct qe_ic *qe_ic_from_irq(unsigned int virq) -{ - return irq_get_chip_data(virq); -} - -static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d) -{ - return irq_data_get_irq_chip_data(d); -} - -static void qe_ic_unmask_irq(struct irq_data *d) -{ - struct qe_ic *qe_ic = qe_ic_from_irq_data(d); - unsigned int src = irqd_to_hwirq(d); - unsigned long flags; - u32 temp; - - raw_spin_lock_irqsave(&qe_ic_lock, flags); - - temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); - qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, - temp | qe_ic_info[src].mask); - - raw_spin_unlock_irqrestore(&qe_ic_lock, flags); -} - -static void qe_ic_mask_irq(struct irq_data *d) -{ - struct qe_ic *qe_ic = qe_ic_from_irq_data(d); - unsigned int src = irqd_to_hwirq(d); - unsigned long flags; - u32 temp; - - raw_spin_lock_irqsave(&qe_ic_lock, flags); - - temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg); - qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg, - temp & ~qe_ic_info[src].mask); - - /* Flush the above write before enabling interrupts; otherwise, - * spurious interrupts will sometimes happen. To be 100% sure - * that the write has reached the device before interrupts are - * enabled, the mask register would have to be read back; however, - * this is not required for correctness, only to avoid wasting - * time on a large number of spurious interrupts. In testing, - * a sync reduced the observed spurious interrupts to zero. - */ - mb(); - - raw_spin_unlock_irqrestore(&qe_ic_lock, flags); -} - -static struct irq_chip qe_ic_irq_chip = { - .name = "QEIC", - .irq_unmask = qe_ic_unmask_irq, - .irq_mask = qe_ic_mask_irq, - .irq_mask_ack = qe_ic_mask_irq, -}; - -static int qe_ic_host_match(struct irq_domain *h, struct device_node *node, - enum irq_domain_bus_token bus_token) -{ - /* Exact match, unless qe_ic node is NULL */ - struct device_node *of_node = irq_domain_get_of_node(h); - return of_node == NULL || of_node == node; -} - -static int qe_ic_host_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct qe_ic *qe_ic = h->host_data; - struct irq_chip *chip; - - if (hw >= ARRAY_SIZE(qe_ic_info)) { - pr_err("%s: Invalid hw irq number for QEIC\n", __func__); - return -EINVAL; - } - - if (qe_ic_info[hw].mask == 0) { - printk(KERN_ERR "Can't map reserved IRQ\n"); - return -EINVAL; - } - /* Default chip */ - chip = &qe_ic->hc_irq; - - irq_set_chip_data(virq, qe_ic); - irq_set_status_flags(virq, IRQ_LEVEL); - - irq_set_chip_and_handler(virq, chip, handle_level_irq); - - return 0; -} - -static const struct irq_domain_ops qe_ic_host_ops = { - .match = qe_ic_host_match, - .map = qe_ic_host_map, - .xlate = irq_domain_xlate_onetwocell, -}; - -/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ -unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic) -{ - int irq; - - BUG_ON(qe_ic == NULL); - - /* get the interrupt source vector. */ - irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26; - - if (irq == 0) - return NO_IRQ; - - return irq_linear_revmap(qe_ic->irqhost, irq); -} - -/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ -unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic) -{ - int irq; - - BUG_ON(qe_ic == NULL); - - /* get the interrupt source vector. */ - irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26; - - if (irq == 0) - return NO_IRQ; - - return irq_linear_revmap(qe_ic->irqhost, irq); -} - -void __init qe_ic_init(struct device_node *node, unsigned int flags, - void (*low_handler)(struct irq_desc *desc), - void (*high_handler)(struct irq_desc *desc)) -{ - struct qe_ic *qe_ic; - struct resource res; - u32 temp = 0, ret, high_active = 0; - - ret = of_address_to_resource(node, 0, &res); - if (ret) - return; - - qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL); - if (qe_ic == NULL) - return; - - qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS, - &qe_ic_host_ops, qe_ic); - if (qe_ic->irqhost == NULL) { - kfree(qe_ic); - return; - } - - qe_ic->regs = ioremap(res.start, resource_size(&res)); - - qe_ic->hc_irq = qe_ic_irq_chip; - - qe_ic->virq_high = irq_of_parse_and_map(node, 0); - qe_ic->virq_low = irq_of_parse_and_map(node, 1); - - if (qe_ic->virq_low == NO_IRQ) { - printk(KERN_ERR "Failed to map QE_IC low IRQ\n"); - kfree(qe_ic); - return; - } - - /* default priority scheme is grouped. If spread mode is */ - /* required, configure cicr accordingly. */ - if (flags & QE_IC_SPREADMODE_GRP_W) - temp |= CICR_GWCC; - if (flags & QE_IC_SPREADMODE_GRP_X) - temp |= CICR_GXCC; - if (flags & QE_IC_SPREADMODE_GRP_Y) - temp |= CICR_GYCC; - if (flags & QE_IC_SPREADMODE_GRP_Z) - temp |= CICR_GZCC; - if (flags & QE_IC_SPREADMODE_GRP_RISCA) - temp |= CICR_GRTA; - if (flags & QE_IC_SPREADMODE_GRP_RISCB) - temp |= CICR_GRTB; - - /* choose destination signal for highest priority interrupt */ - if (flags & QE_IC_HIGH_SIGNAL) { - temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT); - high_active = 1; - } - - qe_ic_write(qe_ic->regs, QEIC_CICR, temp); - - irq_set_handler_data(qe_ic->virq_low, qe_ic); - irq_set_chained_handler(qe_ic->virq_low, low_handler); - - if (qe_ic->virq_high != NO_IRQ && - qe_ic->virq_high != qe_ic->virq_low) { - irq_set_handler_data(qe_ic->virq_high, qe_ic); - irq_set_chained_handler(qe_ic->virq_high, high_handler); - } -} - -void qe_ic_set_highest_priority(unsigned int virq, int high) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp = 0; - - temp = qe_ic_read(qe_ic->regs, QEIC_CICR); - - temp &= ~CICR_HP_MASK; - temp |= src << CICR_HP_SHIFT; - - temp &= ~CICR_HPIT_MASK; - temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT; - - qe_ic_write(qe_ic->regs, QEIC_CICR, temp); -} - -/* Set Priority level within its group, from 1 to 8 */ -int qe_ic_set_priority(unsigned int virq, unsigned int priority) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp; - - if (priority > 8 || priority == 0) - return -EINVAL; - if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), - "%s: Invalid hw irq number for QEIC\n", __func__)) - return -EINVAL; - if (qe_ic_info[src].pri_reg == 0) - return -EINVAL; - - temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg); - - if (priority < 4) { - temp &= ~(0x7 << (32 - priority * 3)); - temp |= qe_ic_info[src].pri_code << (32 - priority * 3); - } else { - temp &= ~(0x7 << (24 - priority * 3)); - temp |= qe_ic_info[src].pri_code << (24 - priority * 3); - } - - qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp); - - return 0; -} - -/* Set a QE priority to use high irq, only priority 1~2 can use high irq */ -int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high) -{ - struct qe_ic *qe_ic = qe_ic_from_irq(virq); - unsigned int src = virq_to_hw(virq); - u32 temp, control_reg = QEIC_CICNR, shift = 0; - - if (priority > 2 || priority == 0) - return -EINVAL; - if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info), - "%s: Invalid hw irq number for QEIC\n", __func__)) - return -EINVAL; - - switch (qe_ic_info[src].pri_reg) { - case QEIC_CIPZCC: - shift = CICNR_ZCC1T_SHIFT; - break; - case QEIC_CIPWCC: - shift = CICNR_WCC1T_SHIFT; - break; - case QEIC_CIPYCC: - shift = CICNR_YCC1T_SHIFT; - break; - case QEIC_CIPXCC: - shift = CICNR_XCC1T_SHIFT; - break; - case QEIC_CIPRTA: - shift = CRICR_RTA1T_SHIFT; - control_reg = QEIC_CRICR; - break; - case QEIC_CIPRTB: - shift = CRICR_RTB1T_SHIFT; - control_reg = QEIC_CRICR; - break; - default: - return -EINVAL; - } - - shift += (2 - priority) * 2; - temp = qe_ic_read(qe_ic->regs, control_reg); - temp &= ~(SIGNAL_MASK << shift); - temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift; - qe_ic_write(qe_ic->regs, control_reg, temp); - - return 0; -} - -static struct bus_type qe_ic_subsys = { - .name = "qe_ic", - .dev_name = "qe_ic", -}; - -static struct device device_qe_ic = { - .id = 0, - .bus = &qe_ic_subsys, -}; - -static int __init init_qe_ic_sysfs(void) -{ - int rc; - - printk(KERN_DEBUG "Registering qe_ic with sysfs...\n"); - - rc = subsys_system_register(&qe_ic_subsys, NULL); - if (rc) { - printk(KERN_ERR "Failed registering qe_ic sys class\n"); - return -ENODEV; - } - rc = device_register(&device_qe_ic); - if (rc) { - printk(KERN_ERR "Failed registering qe_ic sys device\n"); - return -ENODEV; - } - return 0; -} - -subsys_initcall(init_qe_ic_sysfs); diff --git a/drivers/soc/fsl/qe/qe_ic.h b/drivers/soc/fsl/qe/qe_ic.h deleted file mode 100644 index 926a2ed..0000000 --- a/drivers/soc/fsl/qe/qe_ic.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * drivers/soc/fsl/qe/qe_ic.h - * - * QUICC ENGINE Interrupt Controller Header - * - * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Li Yang - * Based on code from Shlomi Gridish - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#ifndef _POWERPC_SYSDEV_QE_IC_H -#define _POWERPC_SYSDEV_QE_IC_H - -#include - -#define NR_QE_IC_INTS 64 - -/* QE IC registers offset */ -#define QEIC_CICR 0x00 -#define QEIC_CIVEC 0x04 -#define QEIC_CRIPNR 0x08 -#define QEIC_CIPNR 0x0c -#define QEIC_CIPXCC 0x10 -#define QEIC_CIPYCC 0x14 -#define QEIC_CIPWCC 0x18 -#define QEIC_CIPZCC 0x1c -#define QEIC_CIMR 0x20 -#define QEIC_CRIMR 0x24 -#define QEIC_CICNR 0x28 -#define QEIC_CIPRTA 0x30 -#define QEIC_CIPRTB 0x34 -#define QEIC_CRICR 0x3c -#define QEIC_CHIVEC 0x60 - -/* Interrupt priority registers */ -#define CIPCC_SHIFT_PRI0 29 -#define CIPCC_SHIFT_PRI1 26 -#define CIPCC_SHIFT_PRI2 23 -#define CIPCC_SHIFT_PRI3 20 -#define CIPCC_SHIFT_PRI4 13 -#define CIPCC_SHIFT_PRI5 10 -#define CIPCC_SHIFT_PRI6 7 -#define CIPCC_SHIFT_PRI7 4 - -/* CICR priority modes */ -#define CICR_GWCC 0x00040000 -#define CICR_GXCC 0x00020000 -#define CICR_GYCC 0x00010000 -#define CICR_GZCC 0x00080000 -#define CICR_GRTA 0x00200000 -#define CICR_GRTB 0x00400000 -#define CICR_HPIT_SHIFT 8 -#define CICR_HPIT_MASK 0x00000300 -#define CICR_HP_SHIFT 24 -#define CICR_HP_MASK 0x3f000000 - -/* CICNR */ -#define CICNR_WCC1T_SHIFT 20 -#define CICNR_ZCC1T_SHIFT 28 -#define CICNR_YCC1T_SHIFT 12 -#define CICNR_XCC1T_SHIFT 4 - -/* CRICR */ -#define CRICR_RTA1T_SHIFT 20 -#define CRICR_RTB1T_SHIFT 28 - -/* Signal indicator */ -#define SIGNAL_MASK 3 -#define SIGNAL_HIGH 2 -#define SIGNAL_LOW 0 - -struct qe_ic { - /* Control registers offset */ - volatile u32 __iomem *regs; - - /* The remapper for this QEIC */ - struct irq_domain *irqhost; - - /* The "linux" controller struct */ - struct irq_chip hc_irq; - - /* VIRQ numbers of QE high/low irqs */ - unsigned int virq_high; - unsigned int virq_low; -}; - -/* - * QE interrupt controller internal structure - */ -struct qe_ic_info { - u32 mask; /* location of this source at the QIMR register. */ - u32 mask_reg; /* Mask register offset */ - u8 pri_code; /* for grouped interrupts sources - the interrupt - code as appears at the group priority register */ - u32 pri_reg; /* Group priority register offset */ -}; - -#endif /* _POWERPC_SYSDEV_QE_IC_H */