Received: by 10.223.185.116 with SMTP id b49csp3297866wrg; Tue, 13 Feb 2018 00:15:15 -0800 (PST) X-Google-Smtp-Source: AH8x225MsdTJTnjThjfPOrWpZ/sOlfK3Z65DlVe8aR/l6aFUf5vt1H8Kapds7pluFJMG8LvZaQUP X-Received: by 10.101.101.200 with SMTP id y8mr348927pgv.356.1518509715066; Tue, 13 Feb 2018 00:15:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518509715; cv=none; d=google.com; s=arc-20160816; b=sgQQUEpf3AiKqdbuJY0yTKm9KIFiTQ/pI0HZl/BdqAlwl2D48kjxG3skQ8TeBGF8bG KOIS44k3G0IpLQQIJAhA0AlKeAjBNQXaxvZ+E49nN7q+GAfcmOG0x/rFrTbh+aFBFqcn DLFFTY9Zp5RC+crrGoWy/wWntPeSFkUayKtkR4bvzLsr6HLBz7E/CC28VDt0VCDpRT1P Uq++wk/cZqZsJo8rsNWyLAB3jiOjjotlPYBhKtjNdcjVC+zKUz/nsbiskkSNF9gxBUDM WyJYUancQ5Zlzt0B+W+eD+zSWpaOeC8UzcwKgZszyMP3ddgmi6K8VPSOfAJ9spvqo/fq vCww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=9nNJisHl6JOU4OgIl6pFZyZYWzSyA5bvhiYY5u0pdD8=; b=A8u9KHgfAvm6F2oP+bB7yTWb1MbKQjwsyDR3hlrKFGtCaD9M0rVgSw0YcDyTz4I84x zq95/vM0PpMhJ6rx5LDlVqTL7Bo9AqwJkEc7Wc2dRnj9TNMaqwom3dBp+9A42SScDQF3 UdyO4+OsAaCLj5WKzlfnMalMkSzVFua9K0yemiuO6dusKllPHFe58nmCszyRW14KxzGK ZYNNvbnbxU0sQGaMP07WzAVJ+QNwPaXbdTRO4xKPmhvnQdqUieRKXC5peuCptESd+THy iLDY3rG8EG3KAzUQosGk1pmD9kBqNdSXQlVwuchHEx1J0mJ8JwKBYEoJ9wsd16M/ekoX GNSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=SkJ4fJc5; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d6-v6si1044830plo.489.2018.02.13.00.15.00; Tue, 13 Feb 2018 00:15:15 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=SkJ4fJc5; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933703AbeBMINg (ORCPT + 99 others); Tue, 13 Feb 2018 03:13:36 -0500 Received: from mail-it0-f68.google.com ([209.85.214.68]:37429 "EHLO mail-it0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933689AbeBMINe (ORCPT ); Tue, 13 Feb 2018 03:13:34 -0500 Received: by mail-it0-f68.google.com with SMTP id d10so3932864itj.2 for ; Tue, 13 Feb 2018 00:13:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=9nNJisHl6JOU4OgIl6pFZyZYWzSyA5bvhiYY5u0pdD8=; b=SkJ4fJc5qdX9fQgWUxsrNKuGjh426V49BnBW0XRHfj8uz+gXe/e20thJGK4bVAcKSW OmuSGvt6XbTN6EDkn3Y2dJQBSXQ3RVpCW0jiCtIGY5gKydG7H4ptlcCxbamtMhgUWzrk n+vOaGEMcJzur9eW9lxRbcY0ZdLhOKdU9F5OU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=9nNJisHl6JOU4OgIl6pFZyZYWzSyA5bvhiYY5u0pdD8=; b=e9dQ93zcB3NI+srEXmHB+P17YeYMXdQlu3m6f9qPQE81eTefdD2vhFZB+zGt2Wyqzr +kQxermLpR7cD/OKKe9q1TuyRr4NNA3sLOqXHZk1zS2R+OMXRA0/6J/O3k18vig3/Fj5 mPpDcjtnolRVxQsoflpivb1WR3IazYc5dKdM5HknB5k4T3jJN9sGCFaTsOAScBgCqd1D 2d8Es2yXYDvxM533/0BcluYJHSWjat5/czOqVbbQjkM1US12L0LYtVRGvcSm7kbF2MdE VNCxuX3YsHYIYNHpRaqhhE9BG8ds9tmh4UqrAKprKTuKEnNjNDIZuEk0J7vIj0Vd/0gv rRzg== X-Gm-Message-State: APf1xPAphP4xEGt0VNYkQ+QR4u/qZsVJJmX8YEbITzYze1nnqBJpjBUR sE4DP0vozgf27pUgPuRD/RNpLgKuvVWjlTc8dg4GPg== X-Received: by 10.36.207.67 with SMTP id y64mr630221itf.39.1518509613153; Tue, 13 Feb 2018 00:13:33 -0800 (PST) MIME-Version: 1.0 Received: by 10.79.102.131 with HTTP; Tue, 13 Feb 2018 00:13:32 -0800 (PST) In-Reply-To: References: <2834309f69a1ec37b84a33f153a3d0b90336bcc6.1517795460.git.baolin.wang@linaro.org> From: Linus Walleij Date: Tue, 13 Feb 2018 09:13:32 +0100 Message-ID: Subject: Re: [PATCH v3 2/2] gpio: Add GPIO driver for Spreadtrum SC9860 platform To: Baolin Wang Cc: Rob Herring , Mark Rutland , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , "linux-kernel@vger.kernel.org" , linux-gpio@vger.kernel.org, Mark Brown , Andy Shevchenko Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Feb 5, 2018 at 2:55 AM, Baolin Wang wrote: > The Spreadtrum SC9860 platform GPIO controller contains 16 groups and > each group contains 16 GPIOs. Each GPIO can set input/output and has > the interrupt capability. > > Signed-off-by: Baolin Wang > Reviewed-by: Andy Shevchenko > --- > Changes since v2: Hi Baolin, sorry for taking so long to review :( I think you need to add depends on OF_GPIO to the dependencies. Else the build will break on compile test on things like Usermode Linux that doesn't have IOMEM. > +/* GPIO registers definition */ > +#define SPRD_GPIO_DATA 0x0 > +#define SPRD_GPIO_DMSK 0x4 > +#define SPRD_GPIO_DIR 0x8 > +#define SPRD_GPIO_IS 0xc > +#define SPRD_GPIO_IBE 0x10 > +#define SPRD_GPIO_IEV 0x14 > +#define SPRD_GPIO_IE 0x18 > +#define SPRD_GPIO_RIS 0x1c > +#define SPRD_GPIO_MIS 0x20 > +#define SPRD_GPIO_IC 0x24 > +#define SPRD_GPIO_INEN 0x28 So this is very simple. And the only reason we cannot use GPIO_GENERIC is that we have these groups inside the controller and a shared interrupt line :/ Hm yeah I cannot think of anything better anyway. Have you contemplated just putting them into the device tree like this: ap_gpio0: gpio@40280000 { compatible = "sprd,sc9860-gpio"; reg = <0 0x40280000 0 0x80>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = ; }; ap_gpio1: gpio@40280080 { compatible = "sprd,sc9860-gpio"; reg = <0 0x40280080 0 0x80>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = ; }; ap_gpio2: gpio@40280100 { compatible = "sprd,sc9860-gpio"; reg = <0 0x40280100 0 0x80>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = ; }; (...) ? It is fine to have 16 driver instances if you grab the interrupt with IRQF_SHARED and really just handle the IRQ if it is for "your" instance. The upside is that you could then use GPIO_GENERIC and get a very small and simple driver. I understand that the current approach is also appealing though and I see why. I'm not gonna say no to it, so if you strongly prefer this approach we can go for it. Just wanted to point out alternatives. > +/* We have 16 groups GPIOs and each group contain 16 GPIOs */ > +#define SPRD_GPIO_GROUP_NR 16 > +#define SPRD_GPIO_NR 256 > +#define SPRD_GPIO_GROUP_SIZE 0x80 > +#define SPRD_GPIO_GROUP_MASK GENMASK(15, 0) > +#define SPRD_GPIO_BIT(x) ((x) & (SPRD_GPIO_GROUP_NR - 1)) Please rename this from "groups" to "banks" because in the GPIO subsystem everyone talks about "banks" not "groups". This last thing many drivers do like this: bit = x % 15; but it is up to you, either way works (and probably result in the same assembly). > +static inline void __iomem *sprd_gpio_group_base(struct sprd_gpio *sprd_gpio, > + unsigned int group) > +{ > + return sprd_gpio->base + SPRD_GPIO_GROUP_SIZE * group; > +} Since you're always using this like this: void __iomem *base = sprd_gpio_group_base(sprd_gpio, offset / SPRD_GPIO_GROUP_NR); Why not simply have the offset as parameter to the function instead of group number and do the division inside this static inline? > +static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset, > + unsigned int reg, unsigned int val) I would use u16 reg. > +{ > + struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); > + void __iomem *base = sprd_gpio_group_base(sprd_gpio, > + offset / SPRD_GPIO_GROUP_NR); > + u32 shift = SPRD_GPIO_BIT(offset); > + unsigned long flags; > + u32 orig, tmp; > + > + spin_lock_irqsave(&sprd_gpio->lock, flags); > + orig = readl_relaxed(base + reg); > + > + tmp = (orig & ~BIT(shift)) | (val << shift); > + writel_relaxed(tmp, base + reg); > + spin_unlock_irqrestore(&sprd_gpio->lock, flags); > +} You don't need shift, orig and tmp variables here, I think it gets hard to read. I would do it like this: u32 tmp; tmp = readl_relaxed(base + reg); if (val) tmp |= BIT(SPRD_GPIO_BIT(offset)); else tmp &= ~BIT(SPRD_GPIO_BIT(offset)); writel_relaxed(tmp, base + reg); I don't know if the macros really help much. Maybe just inline it: tmp = readl_relaxed(base + reg); if (val) tmp |= BIT(offset % 15); else tmp &= ~BIT(offset % 15); writel_relaxed(tmp, base + reg); It depends on taste. Just consider my options. (I'll go with what you feel is easiest to read.) > +static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, > + unsigned int reg) > +{ > + struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); > + void __iomem *base = sprd_gpio_group_base(sprd_gpio, > + offset / SPRD_GPIO_GROUP_NR); > + u32 value = readl_relaxed(base + reg) & SPRD_GPIO_GROUP_MASK; > + u32 shift = SPRD_GPIO_BIT(offset); > + > + return !!(value & BIT(shift)); I would just return !!(readl_relaxed(base + reg) & BIT(offset % 15)): But again it is a matter of taste. (the rest looks fine!) Yours, Linus Walleij