From patchwork Mon Aug 27 20:15:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 145216 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp358425ljw; Mon, 27 Aug 2018 13:15:51 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZ8bICRUksjgc/pIbVC0gvCW6bmMfuo6hc4MmcJfaTiXb5z6eOrnDDP60/KND8AQZ3FRNhf X-Received: by 2002:a62:778c:: with SMTP id s134-v6mr15824655pfc.189.1535400951166; Mon, 27 Aug 2018 13:15:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535400951; cv=none; d=google.com; s=arc-20160816; b=P3d35bPJoSbn0vGAqKk43S4CRDx+1iDsRSWLutB5XKsthO3UjOPk+kZKGLYXcNwYOU plKfGhCGHCClWoSB10Ot0ccXcnzVEoSLCKMCc0JfMuzGuVmD6n9h423ItUDSuvD4oOm6 vq6gHxcNTESqLQo6smsEuxv44bFBBstWXKEUwsfjSbvMa3efx3q2t+ZmK2vTpxHoX6hj UQKue7Nrnh92lSdyMQgkdIcjCoddvmgum1+sAgfrIW76hYWwtCdbb5wSGhxhM1L4TVka rTqHTCYBnKj6msDiWvswqJn4LXsrnAX3eomUoVccWcbrvyPRz5tNDqRwMR/gabZmjywz pFdQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=2P9M83mYP1F5F5pmFu+t2Kn5d2KbyGHemoeuc57Ewzs=; b=dObyDzqwHdDdSr6FBosIGCNzuSLOd/3F9x5arLBPpy/U1X2mcXOjWBIoBFhm7fPSjy mQIO+ETeZL1ouWx8pycuTa2kMxdv8EKkkeYWOpOwfX141FhCpVHcE9NTXHYzE+KuC8x4 fFcq0G39lyBvpewgQpBTFs8HZ/YSO1j5IMpAH5adAopMV58I7sAPcZRQhlp9O8p8p6jZ wX0GpDnA57wBt3d7rYM3KzzLusW4KQ9228qjkp04hUQ9HsuaTmLJ0cPA7zajT8lCUxco H5P0jIVW+aWt3HEf7dGye2NW/Swq7lJeq1w5CssZB9MzORK7hhWm0deLWZCAV2WZLneD pI6w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=hQPCeFuF; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-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 f5-v6si155040plf.411.2018.08.27.13.15.50; Mon, 27 Aug 2018 13:15:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-gpio-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=hQPCeFuF; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-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 S1727128AbeH1AD5 (ORCPT + 5 others); Mon, 27 Aug 2018 20:03:57 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:44962 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727013AbeH1AD5 (ORCPT ); Mon, 27 Aug 2018 20:03:57 -0400 Received: by mail-lf1-f67.google.com with SMTP id g6-v6so169497lfb.11 for ; Mon, 27 Aug 2018 13:15:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=2P9M83mYP1F5F5pmFu+t2Kn5d2KbyGHemoeuc57Ewzs=; b=hQPCeFuFZmVge0oAoQVb6j9RXzXpqmuyDGiGhuap8TEMezwGAommkVDc5WwIK1QY12 NP4AZpp3H54G0h9DkjU523FNu1gfyy1gHySHW5QSEweY/puR8AhS8S/WVMKcPvNWccOZ OlhU9SseR5S7lbg8oGssZx9Oco8EU88IgP0Gw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=2P9M83mYP1F5F5pmFu+t2Kn5d2KbyGHemoeuc57Ewzs=; b=c+Sd1Q148OplWDEcbSBhCtHvurNmWZraSDXfz7EKykF6WJnLjTqzDEq3CrQjyb3RkJ KmA/5C+8K3TgZR0KZQwwM+s1DjGgfaGFaay64dMABqrBiJHHENZdCeIUxTvb3mJJyAZO PE0qE4zRFMnGQc/j9eE60psX48P0G2KqT43ItFyOsX0miCFtbo2feB0gAej7+cHYCLFe Ie275XZnK/oE5Z05oDsgk30gqkgW/LsnjY03GENWVBrWIXtpuFtDDvMjXBTAt+ceBkd1 u3A5H5RYufacmSVxCPEyjnhKFjQden4fGw1PH5PzWeRZCp9UMyDFU4cmXK7h+cxNz1P9 uiaw== X-Gm-Message-State: APzg51DtN59o/rrwnrPTUe9LOaQQ/rLrNEBjaWfPZbZogbUryFAmaoqe rQT3aReoy7JtiCZ6PgvajewAIQ== X-Received: by 2002:a19:6388:: with SMTP id v8-v6mr9598926lfi.95.1535400947617; Mon, 27 Aug 2018 13:15:47 -0700 (PDT) Received: from localhost.bredbandsbolaget (c-ae7b71d5.014-348-6c756e10.bbcust.telenor.se. [213.113.123.174]) by smtp.gmail.com with ESMTPSA id y23-v6sm27131ljk.28.2018.08.27.13.15.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 27 Aug 2018 13:15:45 -0700 (PDT) From: Linus Walleij To: Hans Ulli Kroll , Florian Fainelli , Jonas Jensen Cc: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, Linus Walleij Subject: [PATCH 1/2 v2] gpio: ftgpio: Support optional silicon clock Date: Mon, 27 Aug 2018 22:15:40 +0200 Message-Id: <20180827201540.15957-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.1 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The GPIO silicon is clocked with a PCLK (peripheral clock) on all systems, however not all platforms model it and include it in e.g. the device tree, so add clock handling but make it optional so we bail out safely if it is e.g. always on. Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Bail out properly for -EPROBE_DEFER from the clock. --- drivers/gpio/gpio-ftgpio010.c | 41 +++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) -- 2.17.1 Reviewed-by: Andrew Lunn diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 868bf8501560..f548bc92e1d1 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -15,6 +15,7 @@ #include #include #include +#include /* GPIO registers definition */ #define GPIO_DATA_OUT 0x00 @@ -40,11 +41,14 @@ * struct ftgpio_gpio - Gemini GPIO state container * @dev: containing device for this instance * @gc: gpiochip for this instance + * @base: remapped I/O-memory base + * @clk: silicon clock */ struct ftgpio_gpio { struct device *dev; struct gpio_chip gc; void __iomem *base; + struct clk *clk; }; static void ftgpio_gpio_ack_irq(struct irq_data *d) @@ -180,6 +184,19 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) if (irq <= 0) return irq ? irq : -EINVAL; + g->clk = devm_clk_get(dev, NULL); + if (!IS_ERR(g->clk)) { + ret = clk_prepare_enable(g->clk); + if (ret) + return ret; + } else if (PTR_ERR(g->clk) == -EPROBE_DEFER) { + /* + * Percolate deferrals, for anything else, + * just live without the clocking. + */ + return PTR_ERR(g->clk); + } + ret = bgpio_init(&g->gc, dev, 4, g->base + GPIO_DATA_IN, g->base + GPIO_DATA_SET, @@ -189,7 +206,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) 0); if (ret) { dev_err(dev, "unable to init generic GPIO\n"); - return ret; + goto dis_clk; } g->gc.label = "FTGPIO010"; g->gc.base = -1; @@ -199,7 +216,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) ret = devm_gpiochip_add_data(dev, &g->gc, g); if (ret) - return ret; + goto dis_clk; /* Disable, unmask and clear all interrupts */ writel(0x0, g->base + GPIO_INT_EN); @@ -211,14 +228,29 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) IRQ_TYPE_NONE); if (ret) { dev_info(dev, "could not add irqchip\n"); - return ret; + goto dis_clk; } gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip, irq, ftgpio_gpio_irq_handler); + platform_set_drvdata(pdev, g); dev_info(dev, "FTGPIO010 @%p registered\n", g->base); return 0; + +dis_clk: + if (!IS_ERR(g->clk)) + clk_disable_unprepare(g->clk); + return ret; +} + +static int ftgpio_gpio_remove(struct platform_device *pdev) +{ + struct ftgpio_gpio *g = platform_get_drvdata(pdev); + + if (!IS_ERR(g->clk)) + clk_disable_unprepare(g->clk); + return 0; } static const struct of_device_id ftgpio_gpio_of_match[] = { @@ -239,6 +271,7 @@ static struct platform_driver ftgpio_gpio_driver = { .name = "ftgpio010-gpio", .of_match_table = of_match_ptr(ftgpio_gpio_of_match), }, - .probe = ftgpio_gpio_probe, + .probe = ftgpio_gpio_probe, + .remove = ftgpio_gpio_remove, }; builtin_platform_driver(ftgpio_gpio_driver); From patchwork Mon Aug 27 20:15:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 145217 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp358556ljw; Mon, 27 Aug 2018 13:15:58 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZc5XRfNmUUybZomNkd/ExSpVUdUuWhje6In9YQv/fR/xikExgvCHrlZ6+axpmdKNFKSYVE X-Received: by 2002:a63:c807:: with SMTP id z7-v6mr13198402pgg.77.1535400958677; Mon, 27 Aug 2018 13:15:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535400958; cv=none; d=google.com; s=arc-20160816; b=Tey80XxIpApfbNeDEZLnyVVwp/LfFN+8JXJLGP4rywBCxy/JOQIrckF2W/6UknqtHN 7tHUWSsjmzKqv1H1k8KpJ3Whh+7+BL5XsTtfQ3g9OlNhFB4XKacfuo+BP6W6IlKN+HP4 AYPQzQqmbDdR6SsblBfCwmuCy3qKJQRZaYQCsio4L6+5G11gSeQeVSVtx74TVBh2DUv1 hyBd3pqh4viRY047I7bNmYLfbTLdYacVo0oVotqEd+KuMS/5ZjBmN+kX+MK8n1I5FQvC fhNAWRbPgnk1w5VSiGUSu7V8mR5K7aBoM2ics4wYnLduqQEeCbbOHSC2q3uZ8ZtwCv4r jpLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=XMcJhHnMLBCOWw/8y/MR/AExu5eyWDChkwXCqnMwgsE=; b=tfrePJ9os6hzJmIaI1TMKjoqdOG7sn3Tq44Bk8vF6zTYz5LD8taQGLQ86gE3aWA3j8 KBcbjg4YLyr93ET5aQmm3Ou9fDkjmBhzHxnRg1+AmjNEFdTxgCB58neReGsuN2iFVnGi tg7SNoBLcOCYT8xz25tcfsdaxtd+Z+ppLWGd34UYLVjRzxJJdMq6TLmCo1SQNn27jBJL OtAOFkrUUHkn5UJmJIdMu+sQgy1iy3dhhL1P+4L+gs3Jn3nCpdI4kspFEmsjGEowArfM Aaf68M0abJbKiReSoVyHS5dbdJbgWV939lb6zG+GBOuofNv2iB08yA4EILoGL5z3qpov 9Xjg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=S+48Pr5D; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-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 f5-v6si155040plf.411.2018.08.27.13.15.58; Mon, 27 Aug 2018 13:15:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-gpio-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=S+48Pr5D; spf=pass (google.com: best guess record for domain of linux-gpio-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-gpio-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 S1727172AbeH1AEF (ORCPT + 5 others); Mon, 27 Aug 2018 20:04:05 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:37640 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727013AbeH1AEF (ORCPT ); Mon, 27 Aug 2018 20:04:05 -0400 Received: by mail-lf1-f67.google.com with SMTP id j8-v6so203124lfb.4 for ; Mon, 27 Aug 2018 13:15:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=XMcJhHnMLBCOWw/8y/MR/AExu5eyWDChkwXCqnMwgsE=; b=S+48Pr5DKMOPXYhPpNi6nyOVqWfgMXCnWPaJdIOfLXnNYTO84oyk6+c78pw1VTk0t1 yxBZI57EHFpbZrH3g/wzFDqvNbhk299QByBz0dyDEgcyaEAUv3NJ0azVg9cEZy/Q/VQJ oHywi1vYAWrA5/SWhylSl984k+QyPaCidP0dU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=XMcJhHnMLBCOWw/8y/MR/AExu5eyWDChkwXCqnMwgsE=; b=Al9v3Opju8eAGrDU2VssDL9tC3G55p5TFCyqzI9zHoLfSXlq6CAaU/SI64yjjZu4XZ 9LUHz1KMZH3pCCgExLn4IC5v0LmU5WzalcqVpF+ezruxZWJj8nukiDLc3ZvtOnz9qL1T DTOvf8zjhPjJplEBj5ocmiyh5qWP2hFX9IG8WYBusUY+1645rkDEYZbwYhnMCVkERU2S V27geW3qlEP0i395KEek9PK4tz9CcWGR/dOxvLBuhuOYHOWnF/0Bs8AsyU2146OzASRX VtBmbnDK+vsDrKEzy/5DVrRDCtdapj4KU9QWl97wSQ1Yw98XL8NV85uQAtA04U0Ln0Wn r3dQ== X-Gm-Message-State: APzg51AKhXKopvVQ5kJkuc4FS7WKNjy0NVaIbTuCbNTniFZHupWSN2ii vzw3KmXwHhn2WBbQto7s1tV28A== X-Received: by 2002:a19:1591:: with SMTP id 17-v6mr8999982lfv.141.1535400955822; Mon, 27 Aug 2018 13:15:55 -0700 (PDT) Received: from localhost.bredbandsbolaget (c-ae7b71d5.014-348-6c756e10.bbcust.telenor.se. [213.113.123.174]) by smtp.gmail.com with ESMTPSA id x8-v6sm24818lji.53.2018.08.27.13.15.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 27 Aug 2018 13:15:54 -0700 (PDT) From: Linus Walleij To: Hans Ulli Kroll , Florian Fainelli , Jonas Jensen Cc: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, Linus Walleij Subject: [PATCH 2/2 v2] gpio: ftgpio: Support debounce timer Date: Mon, 27 Aug 2018 22:15:51 +0200 Message-Id: <20180827201551.16012-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.1 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The FTGPIO010 has a debounce timer or rather prescaler that will affect interrupts fireing off the block. We can support this to get proper debounce on e.g. keypresses. Since the same prescaler is used across all GPIO lines of the silicon block, we need to bail out if the prescaler is already set and in use by another line. If the prescaler is already set to what we need, fine, we reuse it. This happens more often than not when the same debounce time is set for several GPIO keys, so we support that usecase easily with this code. Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Fix up a unchecked line in writing default zero to debounce enable. --- drivers/gpio/gpio-ftgpio010.c | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) -- 2.17.1 diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index f548bc92e1d1..95f578804b0e 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -161,6 +161,73 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } +static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + enum pin_config_param param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + unsigned long pclk_freq; + u32 deb_div; + u32 val; + + if (param != PIN_CONFIG_INPUT_DEBOUNCE) + return -ENOTSUPP; + + /* + * Debounce only works if interrupts are enabled. The manual + * states that if PCLK is 66 MHz, and this is set to 0x7D0, then + * PCLK is divided down to 33 kHz for the debounce timer. 0x7D0 is + * 2000 decimal, so what they mean is simply that the PCLK is + * divided by this value. + * + * As we get a debounce setting in microseconds, we calculate the + * desired period time and see if we can get a suitable debounce + * time. + */ + pclk_freq = clk_get_rate(g->clk); + deb_div = DIV_ROUND_CLOSEST(pclk_freq, arg); + + /* This register is only 24 bits wide */ + if (deb_div > (1 << 24)) + return -ENOTSUPP; + + dev_dbg(g->dev, "prescale divisor: %08x, resulting frequency %lu Hz\n", + deb_div, (pclk_freq/deb_div)); + + val = readl(g->base + GPIO_DEBOUNCE_PRESCALE); + if (val == deb_div) { + /* + * The debounce timer happens to already be set to the + * desireable value, what a coincidence! We can just enable + * debounce on this GPIO line and return. This happens more + * often than you think, for example when all GPIO keys + * on a system are requesting the same debounce interval. + */ + val = readl(g->base + GPIO_DEBOUNCE_EN); + val |= BIT(offset); + writel(val, g->base + GPIO_DEBOUNCE_EN); + return 0; + } + + val = readl(g->base + GPIO_DEBOUNCE_EN); + if (val) { + /* + * Oh no! Someone is already using the debounce with + * another setting than what we need. Bummer. + */ + return -ENOTSUPP; + } + + /* First come, first serve */ + writel(deb_div, g->base + GPIO_DEBOUNCE_PRESCALE); + /* Enable debounce */ + val |= BIT(offset); + writel(val, g->base + GPIO_DEBOUNCE_EN); + + return 0; +} + static int ftgpio_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -214,6 +281,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) g->gc.owner = THIS_MODULE; /* ngpio is set by bgpio_init() */ + /* We need a silicon clock to do debounce */ + if (!IS_ERR(g->clk)) + g->gc.set_config = ftgpio_gpio_set_config; + ret = devm_gpiochip_add_data(dev, &g->gc, g); if (ret) goto dis_clk; @@ -223,6 +294,9 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) writel(0x0, g->base + GPIO_INT_MASK); writel(~0x0, g->base + GPIO_INT_CLR); + /* Clear any use of debounce */ + writel(0x0, g->base + GPIO_DEBOUNCE_EN); + ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip, 0, handle_bad_irq, IRQ_TYPE_NONE);