From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10EEBC433DB for ; Sat, 30 Jan 2021 00:37:22 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9869C64E00 for ; Sat, 30 Jan 2021 00:37:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9869C64E00 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=calian.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:Content-ID:In-Reply-To:References: Message-ID:Date:Subject:To:From:Reply-To:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ZMiRs/3hsGmgGjnEtLQjPXvo55d9r8wkL5Rb22GvHb4=; b=vAk7ixf+o5Qq0lNbaN4A6p8b6 yxNoZZTJ2NB4Yp5u13m1ubkhTKy+V3QgeHshhJhyvcI9rfZyRVxVpcqDbk732HnEBspeG1V+je/6w Hz/JSZX1/1Rbv4ciUD1kCf1yuAY8D+lNt2hWokxGw9WcGhCp7iUgGVIsdtle3nBhDfmWz7OXRiJPD 2vW3nztI/pI4p8SDnmrt+sik/mD7m4TBRjCTUOD0aaWOkVBEMCudkeyIAxvJwj5g9WWbz5FME7psg wP9FmMqJvlG+rlb2BK5kOoBK+xHeL3e/6dCXPtvVfGSEYUpIjJxckaSO1K2KN2mZRgagbEUQ8LWim FnpAoe23w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1l5eER-00014U-1a; Sat, 30 Jan 2021 00:35:19 +0000 Received: from mx0d-0054df01.pphosted.com ([67.231.150.19]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1l5eEM-00013s-SG for linux-arm-kernel@lists.infradead.org; Sat, 30 Jan 2021 00:35:16 +0000 Received: from pps.filterd (m0209000.ppops.net [127.0.0.1]) by mx0c-0054df01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 10U0Z2tU021692; Fri, 29 Jan 2021 19:35:02 -0500 Received: from can01-qb1-obe.outbound.protection.outlook.com (mail-qb1can01lp2057.outbound.protection.outlook.com [104.47.60.57]) by mx0c-0054df01.pphosted.com with ESMTP id 36b2v31c8t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 Jan 2021 19:35:01 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gr5w8rE7jHA/M6l6tQdkk9zLXWzdC+NqmwRQmTKA2TrMMuu7/LH7jTkyvbi/OnLnD5nMHVND/CDnswsR2Q1fdfHqwNiCveSswG9DRrn5fsLVAFdJU7G/ZuIbN1I6AWwR5/xPrYkmIK8fPCNdk+mt0TmbLls2hM/wvPL8Jp8TZnW0mGuyuXDIQYVTtmxf6oIFBXkqt+FAS77JUl04yIKvk2tgaSV8+tQdLpSZhbuo+iJ3LzgoL9sL6lsAkyvARZ3nLEdlzimybM/sAOBVyVwFa3MCK0Xy84IXTSYbsQU7G6zLC2Y/NaKR9B0d9DZn8nw/n8qXN1XeGslr1DW+B5BByw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=He6aWnJ+7kNsWBXMQ4zxsCEKZiPn2SR/nkg89RPNC/M=; b=fIfYSBumwt1JvjAMLiUsqhKa4KaasNaf7s/9+hTIF8NMw+p8+/I1nFmj3f06HQ9G8COW63y/2IPcZxd55b4reVUnYzQFfKPLA5zil8WuYpmlLukm03qIpuPd4yo3jPYpypPDORrk7w4o3kGULYVEFWb0sYaONzWABAzXau6ciOsRCLVoGRkVo9I/1uISiB46nUj6mq4uqjtaHeC8Fc39GzCTKp2P1RoLnS0YfjtJGR7KQnZ4MhoJD6sKyHRLC7zTmGKoOhtFYP2uLr7YKXoaHzmPAlhvsV4344DOvfvZtYOoiF5gkTlpHj7VBl9YUfxJ1wLtfdx6FpoTqB5dzR2q1w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=calian.com; dmarc=pass action=none header.from=calian.com; dkim=pass header.d=calian.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=calian.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=He6aWnJ+7kNsWBXMQ4zxsCEKZiPn2SR/nkg89RPNC/M=; b=sVFKD5+n+fCCrei0BZL8Uu7J4Hu2SPTw7LFVBiASdsAoLtkEkbbjFtcnksRCiE1fmEoe0qsVS/4MlTxN6M1mXWmrN9OlvWCSewMXsnAX/fCALM4Vach5CUeA751cPoqg1QvgHDcYlvYmP4/kMrlZG8hvOLV2BHXlOrMZqeObxwQ= Received: from YT1PR01MB3546.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:b01:f::20) by YT1PR01MB4412.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:b01:2b::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3805.19; Sat, 30 Jan 2021 00:34:58 +0000 Received: from YT1PR01MB3546.CANPRD01.PROD.OUTLOOK.COM ([fe80::3172:da27:cec8:e96]) by YT1PR01MB3546.CANPRD01.PROD.OUTLOOK.COM ([fe80::3172:da27:cec8:e96%7]) with mapi id 15.20.3805.019; Sat, 30 Jan 2021 00:34:58 +0000 From: Robert Hancock To: "vilhelm.gray@gmail.com" , "srinivas.neeli@xilinx.com" , "linus.walleij@linaro.org" , "michal.simek@xilinx.com" , "sgoud@xilinx.com" , "shubhrajyoti.datta@xilinx.com" , "syednwaris@gmail.com" , "bgolaszewski@baylibre.com" Subject: Re: [PATCH V5 3/5] gpio: gpio-xilinx: Add interrupt support Thread-Topic: [PATCH V5 3/5] gpio: gpio-xilinx: Add interrupt support Thread-Index: AQHW9krsX0ht7Dqrv0WII0NrBdLiOqo/UuKA Date: Sat, 30 Jan 2021 00:34:57 +0000 Message-ID: <1cdf7c3db96e9efadc3a492f2ed27caa330d052c.camel@calian.com> References: <1611930410-25747-1-git-send-email-srinivas.neeli@xilinx.com> <1611930410-25747-4-git-send-email-srinivas.neeli@xilinx.com> In-Reply-To: <1611930410-25747-4-git-send-email-srinivas.neeli@xilinx.com> Accept-Language: en-CA, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: Evolution 3.28.5 (3.28.5-16.el8) authentication-results: gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=none action=none header.from=calian.com; x-originating-ip: [204.83.154.189] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: b8b61ecd-a4c3-4909-5903-08d8c4b6df2f x-ms-traffictypediagnostic: YT1PR01MB4412: x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:8882; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: wA1u2HW/OBH5lIso4ebMdFgkxzcAPd9am+06t7hXIFZcm6noRrXElVzx8LJvwQVAhRoCQQubGe/PvRQByWI6LK5I/TIccZ5bkTcm8T1SyI6AWKPZkS7gnmu7hglft9G8vce/4DW6jdjGHo99MSWXVOQiZAmHFrKoETf0IEkJzQWcsV/DCF2WoVEnXL/OtfhL7hZDbEI4obLdwYjS/T3MzGdTq9+wF3MwF2F9Q/eG+QaO/kDgm58BHKmwn1U9z1FwP9MCJMkWH7lpVJOgAPpWBf2Ipdbqk6EmfDQf+FcmLuTdHyVZ+WTgT8wQErYJ/JKTn59v3JO7PvRmV6pg3D0Nxsmm+cM861HEy1IpMU4KWJI0Zx7Cl1znb9AdxqdPFpIYcjs/mmHa7zQperc8OkpV6WgSt4S+H0roeSLiA9ClgIAHThDLlUXMJk+LUL6EQWOXWOdAIejMmVJYyvJgxum/D29cekVVY3A/koY7nqa34IaSr3gtfels2AmIZE/sktnHBE/VRu4titzseimCpSAkbyJPH/PeorsknhoNfuI4SyD2uY5Bel+eclVSD9/m/tBPiPENlvq7mBGiYeM3Em334GeY/fk9XiGXoiORAoDgPLFY00FFCeJSew0NFDnmsCPE5AOXHXs+Bo/MKQOry4lrERJyp0sn+k8/ts/gsJwOumzc9Eczokfh8kfj8tP96Joa x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:YT1PR01MB3546.CANPRD01.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(4636009)(346002)(39850400004)(376002)(396003)(366004)(136003)(30864003)(5660300002)(7416002)(8936002)(83380400001)(71200400001)(6512007)(6486002)(2616005)(478600001)(15974865002)(66446008)(44832011)(66556008)(66476007)(186003)(6506007)(54906003)(110136005)(76116006)(26005)(66946007)(86362001)(4326008)(316002)(36756003)(64756008)(8676002)(2906002)(99106002)(18886075002); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata: =?utf-8?B?Mkd0VjlaMGVqeEhncis2RnFKbWRFMmg2SnpDM0cra0x3anUzc2xiMjdUbEpZ?= =?utf-8?B?bU1YZGFrN09MU215c0pGZlNQaFhNYXJXNTdLVUhYTmU4T0hYKzllcEJLcmRL?= =?utf-8?B?UGcxRWZJV0ZOc3FHbjRJMzIzRUxSUXczdVV6dHBXdnR5VUgwWFZJbi94dE94?= =?utf-8?B?TmtBOHRNOWNtNTFod24rQ25aZHJzc3VtMjNsMjJxL0Jmd01Yc29ybmpKVWEw?= =?utf-8?B?cEdZd1RDOTI4dnprM0puNFl4RERhZUUwVmN1MGRhaUkxNjBDTk1LeDRtaFRy?= =?utf-8?B?NG9zcGtrYm55dktVWEVpT3F3UkRwaTU2WExJNVFyaEpHQnYzWVpkcmlzRDBv?= =?utf-8?B?Rk1LcTRtRWZITWpyMEpqYUJTRlErUW5TWlg0WUdXWHFrUyszM1pIVlE2dHNw?= =?utf-8?B?Rzl6Q1U2cXAzSUIyV2xmcHkyM1JsVnBqNVcxcUdsVzFuM1AyV3JKKy9nT2FS?= =?utf-8?B?eFYyczhDbmZqTHliK1huVmtEV1RCYUZKcU1vUGVuS0ZmSU0zbkZHTUc2WUkz?= =?utf-8?B?UFV4Q0JVbVlJVkNvNzFjOTZUZVFmMFh3Z1lsSGZ4N1dMSVhiM25oVkZjZmtq?= =?utf-8?B?MVVQb0tBcWs2UnNodDFSY0lncUt0RTZmMFN2S1BpMXh5eUhPL013Nk1kOWIw?= =?utf-8?B?SFJwdnBuWHo1RVZwK2RsalpnQlFtWUhsL2ZoN1lZbUZCL0hCT0xEZmw2U0hr?= =?utf-8?B?a0xrNHVtMEV3OVdjMElsVW43dVgxWnZaT1ZkS1ZYYXpUYnJ4Q0FLOTN2NTB6?= =?utf-8?B?MFExZVNEQlI4Z2pVK05NcmV0WHR5L0wvWkdJcVVWcld4L3RndVlITElST2FB?= =?utf-8?B?ZHR1bFhKSWRWQ1lBVk44eXkrOUUyWnd0diszMDBoOEYzVjJvaVhKc1ppaTVC?= =?utf-8?B?NlQyR0tIeENic3c0L0JhVHZlV2ZuZkwyZkZlSjY1K2dmWHJGYVZsMHpRNVFK?= =?utf-8?B?RkI0Y09nNjBMZzN2MVYvR0t5T0xsS1pCUWdBL3MrOXRiT1hUamtKOTByaHRy?= =?utf-8?B?QzZHWm1NUXd6K3prV2ZKMXNCZy9LUHZwajZsRTBJdzZpVEdmaUQ0bVl2MWVW?= =?utf-8?B?cjdneGNZMDE5MCs2THE3NW9aMUExRU5idng0V0lTVHdjb1hneWRWWnpGTitP?= =?utf-8?B?WmtpUU9XbkpEd2NVTnhHcC9JbzExQjZIYVhXNGs3YlNqdFlVcXdSTXJ1VEho?= =?utf-8?B?RXRidmR2RC9sclFNTDlvblJ5TXU1S3RkVnIrWWZSL1Z2cmU2azdRMmVZUGJl?= =?utf-8?B?a1NpODIxUWl6cVlrbVhFTW1Vam9pOXdDemE4SkM4Zzc2RWVwVHRjUFdZMG5S?= =?utf-8?B?WDFyRW9qV01FbEZXb2xhMG0wSlByNUp5Y3hKTnhoczMxdnZ1N2ZaMS9EU1VB?= =?utf-8?B?a2tKV1pXUktUdktXdFNpM24yS2xjZFI0S3pQUnRzZkVCTkwxcmtmL2lKVHMr?= =?utf-8?B?bkdyZXZVSFVZbFhOU1lpUW5BZUZBSzlPcFhyTTJRPT0=?= x-ms-exchange-transport-forked: True Content-ID: <33D859849043F249BC75EBDB67DA4D4B@CANPRD01.PROD.OUTLOOK.COM> MIME-Version: 1.0 X-OriginatorOrg: calian.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: YT1PR01MB3546.CANPRD01.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-Network-Message-Id: b8b61ecd-a4c3-4909-5903-08d8c4b6df2f X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Jan 2021 00:34:57.8880 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 23b57807-562f-49ad-92c4-3bb0f07a1fdf X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: XlXdiZGSFbFeL5tFe6EF/4pXJ2j/3z6YxUwaxXGlkyuwldxfTX4CzHnLkXiqbJGy3YEQqVtJMV7figsobya4L3l9sJ38Tq4hEh2rFBYP7D8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: YT1PR01MB4412 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369, 18.0.737 definitions=2021-01-29_12:2021-01-29, 2021-01-29 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 lowpriorityscore=0 clxscore=1011 phishscore=0 mlxscore=0 spamscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2101300000 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210129_193515_143961_1F24727C X-CRM114-Status: GOOD ( 31.20 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "hancock@sedsystems.ca" , "linux-gpio@vger.kernel.org" , "linux-kernel@vger.kernel.org" , "linux-arm-kernel@lists.infradead.org" , "git@xilinx.com" Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Noticed one issue, see below: On Fri, 2021-01-29 at 19:56 +0530, Srinivas Neeli wrote: > Adds interrupt support to the Xilinx GPIO driver so that rising and > falling edge line events can be supported. Since interrupt support is > an optional feature in the Xilinx IP, the driver continues to support > devices which have no interrupt provided. > Depends on OF_GPIO framework for of_xlate function to translate > gpiospec to the GPIO number and flags. > > Signed-off-by: Robert Hancock > Signed-off-by: Shubhrajyoti Datta > Signed-off-by: Srinivas Neeli > --- > Changes in V5: > -Removed IRQ_DOMAIN_HIERARCHY from Kconfig and > #include from includes. > -Fixed "detected irqchip that is shared with multiple > gpiochips: please fix the driver"error message. > -Added check for #gpio-cells and error message in failure case. > Changes in V4: > -Added more commit description. > Changes in V3: > -Created separate patch for Clock changes and runtime resume > and suspend. > -Updated minor review comments. > > Changes in V2: > -Added check for return value of platform_get_irq() API. > -Updated code to support rising edge and falling edge. > -Added xgpio_xlate() API to support switch. > -Added MAINTAINERS fragment. > --- > drivers/gpio/Kconfig | 2 + > drivers/gpio/gpio-xilinx.c | 246 > ++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 244 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index c70f46e80a3b..2ee57797d908 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -690,6 +690,8 @@ config GPIO_XGENE_SB > > config GPIO_XILINX > tristate "Xilinx GPIO support" > + select GPIOLIB_IRQCHIP > + depends on OF_GPIO > help > Say yes here to support the Xilinx FPGA GPIO device > > diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c > index f88db56543c2..62deb755f910 100644 > --- a/drivers/gpio/gpio-xilinx.c > +++ b/drivers/gpio/gpio-xilinx.c > @@ -10,7 +10,9 @@ > #include > #include > #include > +#include > #include > +#include > #include > #include > #include > @@ -22,6 +24,11 @@ > > #define XGPIO_CHANNEL_OFFSET 0x8 > > +#define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */ > +#define XGPIO_GIER_IE BIT(31) > +#define XGPIO_IPISR_OFFSET 0x120 /* IP Interrupt Status */ > +#define XGPIO_IPIER_OFFSET 0x128 /* IP Interrupt Enable */ > + > /* Read/Write access to the GPIO registers */ > #if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86) > # define xgpio_readreg(offset) readl(offset) > @@ -36,9 +43,15 @@ > * @gc: GPIO chip > * @regs: register block > * @gpio_width: GPIO width for every channel > - * @gpio_state: GPIO state shadow register > + * @gpio_state: GPIO write state shadow register > + * @gpio_last_irq_read: GPIO read state register from last interrupt > * @gpio_dir: GPIO direction shadow register > * @gpio_lock: Lock used for synchronization > + * @irq: IRQ used by GPIO device > + * @irqchip: IRQ chip > + * @irq_enable: GPIO IRQ enable/disable bitfield > + * @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield > + * @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield > * @clk: clock resource for this driver > */ > struct xgpio_instance { > @@ -46,8 +59,14 @@ struct xgpio_instance { > void __iomem *regs; > unsigned int gpio_width[2]; > u32 gpio_state[2]; > + u32 gpio_last_irq_read[2]; > u32 gpio_dir[2]; > spinlock_t gpio_lock; /* For serializing operations */ > + int irq; > + struct irq_chip irqchip; > + u32 irq_enable[2]; > + u32 irq_rising_edge[2]; > + u32 irq_falling_edge[2]; > struct clk *clk; > }; > > @@ -277,6 +296,175 @@ static int xgpio_remove(struct platform_device *pdev) > } > > /** > + * xgpio_irq_ack - Acknowledge a child GPIO interrupt. > + * @irq_data: per IRQ and chip data passed down to chip functions > + * This currently does nothing, but irq_ack is unconditionally called by > + * handle_edge_irq and therefore must be defined. > + */ > +static void xgpio_irq_ack(struct irq_data *irq_data) > +{ > +} > + > +/** > + * xgpio_irq_mask - Write the specified signal of the GPIO device. > + * @irq_data: per IRQ and chip data passed down to chip functions > + */ > +static void xgpio_irq_mask(struct irq_data *irq_data) > +{ > + unsigned long flags; > + struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); > + int irq_offset = irqd_to_hwirq(irq_data); > + int index = xgpio_index(chip, irq_offset); > + int offset = xgpio_offset(chip, irq_offset); > + > + spin_lock_irqsave(&chip->gpio_lock, flags); > + > + chip->irq_enable[index] &= ~BIT(offset); > + > + if (!chip->irq_enable[index]) { > + /* Disable per channel interrupt */ > + u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); > + > + temp &= ~BIT(index); > + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); > + } > + spin_unlock_irqrestore(&chip->gpio_lock, flags); > +} > + > +/** > + * xgpio_irq_unmask - Write the specified signal of the GPIO device. > + * @irq_data: per IRQ and chip data passed down to chip functions > + */ > +static void xgpio_irq_unmask(struct irq_data *irq_data) > +{ > + unsigned long flags; > + struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); > + int irq_offset = irqd_to_hwirq(irq_data); > + int index = xgpio_index(chip, irq_offset); > + int offset = xgpio_offset(chip, irq_offset); > + u32 old_enable = chip->irq_enable[index]; > + > + spin_lock_irqsave(&chip->gpio_lock, flags); > + > + chip->irq_enable[index] |= BIT(offset); > + > + if (!old_enable) { > + /* Clear any existing per-channel interrupts */ > + u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) & > + BIT(index); > + > + if (val) > + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); > + > + /* Update GPIO IRQ read data before enabling interrupt*/ > + val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + > + index * XGPIO_CHANNEL_OFFSET); > + chip->gpio_last_irq_read[index] = val; > + > + /* Enable per channel interrupt */ > + val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); > + val |= BIT(index); > + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); > + } > + > + spin_unlock_irqrestore(&chip->gpio_lock, flags); > +} > + > +/** > + * xgpio_set_irq_type - Write the specified signal of the GPIO device. > + * @irq_data: Per IRQ and chip data passed down to chip functions > + * @type: Interrupt type that is to be set for the gpio pin > + * > + * Return: > + * 0 if interrupt type is supported otherwise -EINVAL > + */ > +static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) > +{ > + struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); > + int irq_offset = irqd_to_hwirq(irq_data); > + int index = xgpio_index(chip, irq_offset); > + int offset = xgpio_offset(chip, irq_offset); > + > + /* > + * The Xilinx GPIO hardware provides a single interrupt status > + * indication for any state change in a given GPIO channel (bank). > + * Therefore, only rising edge or falling edge triggers are > + * supported. > + */ > + switch (type & IRQ_TYPE_SENSE_MASK) { > + case IRQ_TYPE_EDGE_BOTH: > + chip->irq_rising_edge[index] |= BIT(offset); > + chip->irq_falling_edge[index] |= BIT(offset); > + break; > + case IRQ_TYPE_EDGE_RISING: > + chip->irq_rising_edge[index] |= BIT(offset); > + chip->irq_falling_edge[index] &= ~BIT(offset); > + break; > + case IRQ_TYPE_EDGE_FALLING: > + chip->irq_rising_edge[index] &= ~BIT(offset); > + chip->irq_falling_edge[index] |= BIT(offset); > + break; > + default: > + return -EINVAL; > + } > + > + irq_set_handler_locked(irq_data, handle_edge_irq); > + return 0; > +} > + > +/** > + * xgpio_irqhandler - Gpio interrupt service routine > + * @desc: Pointer to interrupt description > + */ > +static void xgpio_irqhandler(struct irq_desc *desc) > +{ > + struct xgpio_instance *chip = irq_desc_get_handler_data(desc); > + struct irq_chip *irqchip = irq_desc_get_chip(desc); > + u32 num_channels = chip->gpio_width[1] ? 2 : 1; > + u32 offset = 0, index; > + u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); > + > + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); > + > + chained_irq_enter(irqchip, desc); > + for (index = 0; index < num_channels; index++) { > + if ((status & BIT(index))) { > + unsigned long rising_events, falling_events, > all_events; > + unsigned long flags; > + u32 data, bit; > + unsigned int irq; > + > + spin_lock_irqsave(&chip->gpio_lock, flags); > + data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + > + index * XGPIO_CHANNEL_OFFSET); > + rising_events = data & > + ~chip->gpio_last_irq_read[index] & > + chip->irq_enable[index] & > + chip->irq_rising_edge[index]; > + falling_events = ~data & > + chip->gpio_last_irq_read[index] & > + chip->irq_enable[index] & > + chip->irq_falling_edge[index]; > + dev_dbg(chip->gc.parent, > + "IRQ chan %u rising 0x%lx falling 0x%lx\n", > + index, rising_events, falling_events); > + all_events = rising_events | falling_events; > + chip->gpio_last_irq_read[index] = data; > + spin_unlock_irqrestore(&chip->gpio_lock, flags); > + > + for_each_set_bit(bit, &all_events, 32) { > + irq = irq_find_mapping(chip->gc.irq.domain, > + offset + bit); > + generic_handle_irq(irq); > + } > + } > + offset += chip->gpio_width[index]; > + } > + > + chained_irq_exit(irqchip, desc); > +} > + > +/** > * xgpio_of_probe - Probe method for the GPIO device. > * @pdev: pointer to the platform device > * > @@ -289,7 +477,10 @@ static int xgpio_probe(struct platform_device *pdev) > struct xgpio_instance *chip; > int status = 0; > struct device_node *np = pdev->dev.of_node; > - u32 is_dual; > + u32 is_dual = 0; > + u32 cells = 2; > + struct gpio_irq_chip *girq; > + u32 temp; > > chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); > if (!chip) > @@ -305,6 +496,15 @@ static int xgpio_probe(struct platform_device *pdev) > if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) > chip->gpio_dir[0] = 0xFFFFFFFF; > > + /* Update cells with gpio-cells value */ > + if (of_property_read_u32(np, "#gpio-cells", &cells)) > + dev_dbg(&pdev->dev, "Missing gpio-cells property\n"); > + > + if (cells != 2) { > + dev_err(&pdev->dev, "#gpio-cells mismatch\n"); > + return -EINVAL; > + } > + > /* > * Check device node and parent device node for device width > * and assume default width of 32 > @@ -343,6 +543,7 @@ static int xgpio_probe(struct platform_device *pdev) > chip->gc.parent = &pdev->dev; > chip->gc.direction_input = xgpio_dir_in; > chip->gc.direction_output = xgpio_dir_out; > + chip->gc.of_gpio_n_cells = cells; > chip->gc.get = xgpio_get; > chip->gc.set = xgpio_set; > chip->gc.set_multiple = xgpio_set_multiple; > @@ -367,14 +568,51 @@ static int xgpio_probe(struct platform_device *pdev) > > xgpio_save_regs(chip); > > + chip->irq = platform_get_irq_optional(pdev, 0); > + if (chip->irq <= 0) > + goto skip_irq; > + > + chip->irqchip.name = "gpio-xilinx"; > + chip->irqchip.irq_ack = xgpio_irq_ack; > + chip->irqchip.irq_mask = xgpio_irq_mask; > + chip->irqchip.irq_unmask = xgpio_irq_unmask; > + chip->irqchip.irq_set_type = xgpio_set_irq_type; > + > + /* Disable per-channel interrupts */ > + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, 0); > + /* Clear any existing per-channel interrupts */ > + temp = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); > + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, temp); > + /* Enable global interrupts */ > + xgpio_writereg(chip->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE); > + > + girq = &chip->gc.irq; > + girq->chip = &chip->irqchip; > + girq->parent_handler = xgpio_irqhandler; I think you want to also set "girq->parent_handler_data = chip;" here. The original version of this patch did that, but this may have gotten lost when it was changed to a per-instance irqchip. It appears that if parent_handler_data is not set, gpiochip_add_irqchip uses the gpio_chip pointer as the data when calling the parent IRQ handler. xgpio_irqhandler then converts this pointer to xgpio_instance* when it is called. Since the gpio_chip is currently the first member of the xgpio_instance structure, the pointers end up the same and this would currently work. However, it may be unwise to depend on this, as changing the order of members in xgpio_instance would unexpectedly break the code. > + girq->num_parents = 1; > + girq->parents = devm_kcalloc(&pdev->dev, 1, > + sizeof(*girq->parents), > + GFP_KERNEL); > + if (!girq->parents) { > + status = -ENOMEM; > + goto err_unprepare_clk; > + } > + girq->parents[0] = chip->irq; > + girq->default_type = IRQ_TYPE_NONE; > + girq->handler = handle_bad_irq; > + > +skip_irq: > status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); > if (status) { > dev_err(&pdev->dev, "failed to add GPIO chip\n"); > - clk_disable_unprepare(chip->clk); > - return status; > + goto err_unprepare_clk; > } > > return 0; > + > +err_unprepare_clk: > + clk_disable_unprepare(chip->clk); > + return status; > } > > static const struct of_device_id xgpio_of_match[] = { -- Robert Hancock Senior Hardware Designer, Calian Advanced Technologies www.calian.com _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel