From patchwork Wed Oct 11 18:48:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Griffin X-Patchwork-Id: 13417820 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3F778CDB475 for ; Wed, 11 Oct 2023 18:49:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 0D387C116AB; Wed, 11 Oct 2023 18:49:46 +0000 (UTC) Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp.kernel.org (Postfix) with ESMTPS id 1B483C43140 for ; Wed, 11 Oct 2023 18:49:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 smtp.kernel.org 1B483C43140 Authentication-Results: smtp.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.kernel.org; spf=pass smtp.mailfrom=linaro.org Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-40666aa674fso2363235e9.0 for ; Wed, 11 Oct 2023 11:49:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1697050170; x=1697654970; darn=kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gdKtCyKn1s/CVBRJ7oxdlFfABpP1ozzTtDEFGXap/B8=; b=PNYJiDlLOWlkJ0b2NH82wQAlbzo3JKr32LQnx7qZuHNUFN5uYolb1bYhPAHAm9H8Av KGJvximBGWDdP/LgvQVF2L746lZkEbo3TyDBDzADHGnkDgv1Gtl/UUxFKzAUEyono4I8 DrB8RCv+fJ7GGrqwzZNgoiSTY9gKL9x8CaysjABVYMxtW0VlEwY+PeqtOt5vkGkoGW0Q S8tgR+vnjpsHlM/EChy2lV3WxUXj+XITu8IflecaiSURTXdK3CmC/eCQ1JM+hg6uLI2N QBE/7aAyiRl62iaUB51LuOnol2DtxJiDI0r7DFIgMWj0nCR/nxLhk30fZVy5HB/zKfLF GHlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697050170; x=1697654970; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gdKtCyKn1s/CVBRJ7oxdlFfABpP1ozzTtDEFGXap/B8=; b=pCQm57hAydFOMcAJrAiXpLGq1z2+4pMj/wk2jz4+zoTtVisChGJY9uQx/c4U8qXq1p XLsDs+E2Td1ZB0/WD8KW7ZL/UGX1hVsFIzBJX0NkAEG+diHWZiXLDiNKfzdLoQSzIX/C 96GJaVcbklr23Q19/8I5fu6+AbfnLUmCy4pnt0SduvyC199yS4o0tuSFoKEHP0fmIj0v vJ+Qozte9GpqoLWxg+a2bhQqUNKuNV4+ZlANimwxs/+AqXXrx35Xk7td8+7YwL/9iWqx v079PHBR0hy273CNgHF3sUUaHvtB+0slxBdBdfiXJGRfJmBKkAP8Frpm1h2CTF7VQjxK LP0Q== X-Gm-Message-State: AOJu0Yx34J0RMVEQMCFaG6aF0eDN13EVJnjzdnQEuuRAD6vrlPr56Qqx 6MB18qele2BF0/VKb45HL/gU6g== X-Google-Smtp-Source: AGHT+IFwIISwTvqyINc1pDhhhHjOkgwmgnDNwkryVq0B2wX1K+vhsGm7+kSAf271rRuFPgqH3YuruQ== X-Received: by 2002:a5d:4fd2:0:b0:314:15a8:7879 with SMTP id h18-20020a5d4fd2000000b0031415a87879mr17936381wrw.34.1697050170290; Wed, 11 Oct 2023 11:49:30 -0700 (PDT) Received: from gpeter-l.lan (host-92-12-225-146.as13285.net. [92.12.225.146]) by smtp.gmail.com with ESMTPSA id v6-20020adff686000000b0031980294e9fsm16003875wrp.116.2023.10.11.11.49.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Oct 2023 11:49:29 -0700 (PDT) From: Peter Griffin To: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, mturquette@baylibre.com, conor+dt@kernel.org, sboyd@kernel.org, tomasz.figa@gmail.com, s.nawrocki@samsung.com, linus.walleij@linaro.org, wim@linux-watchdog.org, linux@roeck-us.net, catalin.marinas@arm.com, will@kernel.org, arnd@arndb.de, olof@lixom.net, gregkh@linuxfoundation.org, cw00.choi@samsung.com List-Id: Cc: peter.griffin@linaro.org, tudor.ambarus@linaro.org, andre.draszik@linaro.org, semen.protsenko@linaro.org, saravanak@google.com, willmcvicker@google.com, soc@kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-watchdog@vger.kernel.org, kernel-team@android.com, linux-serial@vger.kernel.org Subject: [PATCH v3 13/20] pinctrl: samsung: Add filter selection support for alive banks Date: Wed, 11 Oct 2023 19:48:16 +0100 Message-ID: <20231011184823.443959-14-peter.griffin@linaro.org> X-Mailer: git-send-email 2.42.0.655.g421f12c284-goog In-Reply-To: <20231011184823.443959-1-peter.griffin@linaro.org> References: <20231011184823.443959-1-peter.griffin@linaro.org> MIME-Version: 1.0 Newer Exynos SoCs have a filter selection register on alive bank pins. This allows the selection of a digital or delay filter for each pin. If the filter selection register is not available then the default filter (digital) is applied. On suspend we apply the analog filter to all pins in the bank, and on resume the digital filter is reapplied to all pins in the bank. Signed-off-by: Peter Griffin Tested-by: Will McVicker --- drivers/pinctrl/samsung/pinctrl-exynos.c | 82 ++++++++++++++++++++++- drivers/pinctrl/samsung/pinctrl-exynos.h | 7 ++ drivers/pinctrl/samsung/pinctrl-samsung.c | 2 + drivers/pinctrl/samsung/pinctrl-samsung.h | 23 +++++++ 4 files changed, 113 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index a8212fc126bf..800831aa8357 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -269,6 +269,68 @@ struct exynos_eint_gpio_save { u32 eint_mask; }; +static void exynos_eint_flt_config(struct samsung_pinctrl_drv_data *d, + struct samsung_pin_bank *bank, int filter) +{ + unsigned int flt_reg, flt_con = 0; + unsigned int val, shift; + int i; + int loop_cnt; + + /* + * This function sets the desired filter (digital or delay) to + * every pin in the bank. Note the filter selection bitfield is + * only found on alive banks. The FLTCON register has the + * following layout + * + * BitfieldName[PinNum][Bit:Bit] + * + * FLT_EN[3][31] FLT_SEL[3][30] FLT_WIDTH[3][29:24] + * FLT_EN[2][23] FLT_SEL[2][22] FLT_WIDTH[2][21:16] + * FLT_EN[1][15] FLT_SEL[1][14] FLT_WIDTH[1][13:8] + * FLT_EN[0][7] FLT_SEL[0][6] FLT_WIDTH[0][5:0] + */ + + flt_con |= EXYNOS9_FLTCON_EN; + + if (filter) + flt_con |= EXYNOS9_FLTCON_SEL_DIGITAL; + + flt_reg = EXYNOS_GPIO_EFLTCON_OFFSET + bank->fltcon_offset; + + if (bank->nr_pins > EXYNOS9_FLTCON_NR_PIN) + /* + * if nr_pins > 4, we should set FLTCON0 register fully. + * (pin0 ~ 3). So loop 4 times in case of FLTCON0. + */ + loop_cnt = EXYNOS9_FLTCON_NR_PIN; + else + loop_cnt = bank->nr_pins; + + val = readl(d->virt_base + flt_reg); + + for (i = 0; i < loop_cnt; i++) { + shift = i * EXYNOS9_FLTCON_LEN; + val &= ~(EXYNOS9_FLTCON_MASK << shift); + val |= (flt_con << shift); + } + + writel(val, d->virt_base + flt_reg); + + /* loop for FLTCON1 pin 4 ~ 7 */ + if (bank->nr_pins > EXYNOS9_FLTCON_NR_PIN) { + val = readl(d->virt_base + flt_reg + 0x4); + loop_cnt = (bank->nr_pins - EXYNOS9_FLTCON_NR_PIN); + + for (i = 0; i < loop_cnt; i++) { + shift = i * EXYNOS9_FLTCON_LEN; + val &= ~(EXYNOS9_FLTCON_MASK << shift); + val |= (flt_con << shift); + } + writel(val, d->virt_base + flt_reg + 0x4); + } +} + /* * exynos_eint_gpio_init() - setup handling of external gpio interrupts. * @d: driver data of samsung pinctrl driver. @@ -321,6 +383,9 @@ __init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) goto err_domains; } + /* Set Delay Analog Filter */ + if (bank->fltcon_type != FLT_DEFAULT) + exynos_eint_flt_config(d, bank, EXYNOS9_FLTCON_SEL_DELAY); } return 0; @@ -555,6 +620,10 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) if (bank->eint_type != EINT_TYPE_WKUP) continue; + /* Set Digital Filter */ + if (bank->fltcon_type != FLT_DEFAULT) + exynos_eint_flt_config(d, bank, EXYNOS9_FLTCON_SEL_DIGITAL); + bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip), GFP_KERNEL); if (!bank->irq_chip) { @@ -658,6 +727,7 @@ static void exynos_pinctrl_suspend_bank( void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) { struct samsung_pin_bank *bank = drvdata->pin_banks; + struct samsung_pinctrl_drv_data *d = bank->drvdata; struct exynos_irq_chip *irq_chip = NULL; int i; @@ -665,6 +735,9 @@ void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) if (bank->eint_type == EINT_TYPE_GPIO) exynos_pinctrl_suspend_bank(drvdata, bank); else if (bank->eint_type == EINT_TYPE_WKUP) { + /* Setting Delay (Analog) Filter */ + if (bank->fltcon_type != FLT_DEFAULT) + exynos_eint_flt_config(d, bank, EXYNOS9_FLTCON_SEL_DELAY); if (!irq_chip) { irq_chip = bank->irq_chip; irq_chip->set_eint_wakeup_mask(drvdata, @@ -707,11 +780,18 @@ static void exynos_pinctrl_resume_bank( void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata) { struct samsung_pin_bank *bank = drvdata->pin_banks; + struct samsung_pinctrl_drv_data *d = bank->drvdata; int i; for (i = 0; i < drvdata->nr_banks; ++i, ++bank) - if (bank->eint_type == EINT_TYPE_GPIO) + if (bank->eint_type == EINT_TYPE_GPIO) { exynos_pinctrl_resume_bank(drvdata, bank); + } else if (bank->eint_type == EINT_TYPE_WKUP || + bank->eint_type == EINT_TYPE_WKUP_MUX) { + /* Set Digital Filter */ + if (bank->fltcon_type != FLT_DEFAULT) + exynos_eint_flt_config(d, bank, EXYNOS9_FLTCON_SEL_DIGITAL); + } } static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h index 7bd6d82c9f36..63b2426ad5d6 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.h +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h @@ -50,6 +50,13 @@ #define EXYNOS_EINT_MAX_PER_BANK 8 #define EXYNOS_EINT_NR_WKUP_EINT +/* EINT filter configuration */ +#define EXYNOS9_FLTCON_EN BIT(7) +#define EXYNOS9_FLTCON_SEL_DIGITAL BIT(6) +#define EXYNOS9_FLTCON_SEL_DELAY 0 +#define EXYNOS9_FLTCON_MASK 0xff +#define EXYNOS9_FLTCON_LEN 8 +#define EXYNOS9_FLTCON_NR_PIN 4 #define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \ { \ diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index e54847040b4a..449f8109d8b5 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1104,6 +1104,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, bank->eint_func = bdata->eint_func; bank->eint_type = bdata->eint_type; bank->eint_mask = bdata->eint_mask; + bank->fltcon_type = bdata->fltcon_type; + bank->fltcon_offset = bdata->fltcon_offset; bank->eint_offset = bdata->eint_offset; bank->name = bdata->name; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 9af93e3d8d9f..de2ca8e8b378 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -82,6 +82,21 @@ enum eint_type { EINT_TYPE_WKUP_MUX, }; +/** + * enum fltcon_type - filter selection + * @FLT_DEFAULT: filter not selectable, default digital filter + * @FLT_SELECT: filter selectable (digital or delay) + * + * Some banks on some SoCs (gs101 and possibly others) have a selectable + * filter on alive banks of 'delay/analog' or 'digital'. If the filter + * selection is not available then the default filter is used (digital). + */ + +enum fltcon_type { + FLT_DEFAULT, + FLT_SELECTABLE, +}; + /* maximum length of a pin in pin descriptor (example: "gpa0-0") */ #define PIN_NAME_LENGTH 10 @@ -122,6 +137,8 @@ struct samsung_pin_bank_type { * @eint_type: type of the external interrupt supported by the bank. * @eint_mask: bit mask of pins which support EINT function. * @eint_offset: SoC-specific EINT register or interrupt offset of bank. + * @fltcon_type: whether the filter (delay/digital) is selectable + * @fltcon_offset: SoC-specific EINT filter control register offset of bank. * @name: name to be prefixed for each pin in this pin bank. */ struct samsung_pin_bank_data { @@ -133,6 +150,8 @@ struct samsung_pin_bank_data { enum eint_type eint_type; u32 eint_mask; u32 eint_offset; + enum fltcon_type fltcon_type; + u32 fltcon_offset; const char *name; }; @@ -147,6 +166,8 @@ struct samsung_pin_bank_data { * @eint_type: type of the external interrupt supported by the bank. * @eint_mask: bit mask of pins which support EINT function. * @eint_offset: SoC-specific EINT register or interrupt offset of bank. + * @fltcon_type: whether the filter (delay/digital) is selectable + * @fltcon_offset: SoC-specific EINT filter control register offset of bank. * @name: name to be prefixed for each pin in this pin bank. * @pin_base: starting pin number of the bank. * @soc_priv: per-bank private data for SoC-specific code. @@ -169,6 +190,8 @@ struct samsung_pin_bank { enum eint_type eint_type; u32 eint_mask; u32 eint_offset; + enum fltcon_type fltcon_type; + u32 fltcon_offset; const char *name; u32 pin_base;