From patchwork Thu Sep 28 07:06:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 145910 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp3196098vqu; Thu, 28 Sep 2023 03:04:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGeUDbe6MhM/PZMdbIj02IkMA2tiiIpjYdjVCd7A6kB79QUfiyT5Rf4IoSpyX2UVR4IJm8j X-Received: by 2002:a05:6830:22c4:b0:6b9:b600:536 with SMTP id q4-20020a05683022c400b006b9b6000536mr778624otc.27.1695895453034; Thu, 28 Sep 2023 03:04:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695895453; cv=none; d=google.com; s=arc-20160816; b=t7gkMfD2zR/k8Lh229poaDpUedFJNkSYywBa08zDR1aO4tJ2K77sAHaccwlJn3lpiH qBqwqMg4vP2OKGYBo0Chh1pEorB520ffcZNaIziiL6HlGhX7ST7oo23ouhUtxZzrKHwx abbnyEcLWU3oUofDtqN4Lwk26zSzpheH3A8YIXU7wiv0fInQSIrZiAv54Kw7FZOVYngV RptlacNu1DoOsFxxDgMu5V7kIBjzdBhUYj0ZT7bqIXxH6oubXt6gPvfSmJ/2lR+KJt91 LFm1/240BqkhtGlhB64nU9UjTuZD9r/1ZHNnv2qO2IHwl5+sCmAYoQAvNv8XFQztu5y7 Oiag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=/DwitjZhCHlnkz7qkrXG3uyfct/SPxtzv9MZMSwF7Vo=; fh=8Kc64rxAF0/ep7JtUzveSO6N9QMBWtHyiJ9nqNn2Uww=; b=ebmGBt9gZuZqlYp1lr5MF+0cxM2AuMHqfVp0bHAe7LMkNAehZzutFN7LiHpnuEj/wU oetFwi65QEvzsmm/WFCfYFHTFfhE/LQ08lILhiFZp1Ric57TcVzQ/V+mwfcb0oKhdMiV rbtE+nsI83K2D8b8pBu7BpkRj75ZPPUQR7D7IhfzFQNJNL7yhd+O+tOpKNaml8pz2upa c85nVYAYI4HFjAM/ekpEkmc/Kf48Dj3zw8hSTOkphULlx2P6m6H8WhZF9JdDdBi9eilT K2Al1Qld+P6TS58r8FBVtOfYoGFV4nianyA323SP4uH4jN3S3pWZJyvwNPw6TSjojWBc I6Hw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=Wif74VE1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from morse.vger.email (morse.vger.email. [23.128.96.31]) by mx.google.com with ESMTPS id t22-20020a056a0021d600b00690bf904bb6si18998925pfj.307.2023.09.28.03.04.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 03:04:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) client-ip=23.128.96.31; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=Wif74VE1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.31 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 40B658031AF3; Thu, 28 Sep 2023 00:22:43 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230358AbjI1HWW (ORCPT + 20 others); Thu, 28 Sep 2023 03:22:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231664AbjI1HWH (ORCPT ); Thu, 28 Sep 2023 03:22:07 -0400 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED11A3AA6; Thu, 28 Sep 2023 00:08:47 -0700 (PDT) Received: by mail.gandi.net (Postfix) with ESMTPA id C142820012; Thu, 28 Sep 2023 07:08:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1695884922; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/DwitjZhCHlnkz7qkrXG3uyfct/SPxtzv9MZMSwF7Vo=; b=Wif74VE1U41A3/k2AdtGwrXBPWaE5y4ZIOuGUi66eaKTwT704/DNKcdKXGXn1wPNHq8CRg B7+1QN+oXjOtKD23C2GII31VvoMKPM/Rh4TsplF1XH5wy98N5stvQkq1HVzs/IbslThPCv 8ZNhRQO/5UkwIp6igDb8BKU5U4oZXCKb0DI9bL9i8AfE/UT2uXMeZCeA5O4ZHyspXqRXFz LhE/Ioazn/M4unfTL3AfR0UK406cpa9scyIOdUgIoZPUxHZ4keZ78DEW3eXW8o/pctkwGH gNyc9LVRp/LeQHX9PETRGdp0v7QQZGR/IlRY4aB872/LtcybVvevGh0V9LX5pA== From: Herve Codina To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Linus Walleij , Qiang Zhao , Li Yang , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , Shengjiu Wang , Xiubo Li , Fabio Estevam , Nicolin Chen , Christophe Leroy , Randy Dunlap Cc: netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, alsa-devel@alsa-project.org, Simon Horman , Christophe JAILLET , Thomas Petazzoni Subject: [PATCH v7 27/30] pinctrl: Add support for the Lantic PEF2256 pinmux Date: Thu, 28 Sep 2023 09:06:45 +0200 Message-ID: <20230928070652.330429-28-herve.codina@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230928070652.330429-1-herve.codina@bootlin.com> References: <20230928070652.330429-1-herve.codina@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (morse.vger.email [0.0.0.0]); Thu, 28 Sep 2023 00:22:43 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778275270627321731 X-GMAIL-MSGID: 1778275270627321731 The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. This kind of component can be found in old telecommunication system. It was used to digital transmission of many simultaneous telephone calls by time-division multiplexing. Also using HDLC protocol, WAN networks can be reached through the framer. This pinmux support handles the pin muxing part (pins RP(A..D) and pins XP(A..D)) of the PEF2256. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Reviewed-by: Linus Walleij --- drivers/pinctrl/Kconfig | 15 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pef2256.c | 358 ++++++++++++++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pef2256.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7dfb7190580e..32728d73e0d1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -366,6 +366,21 @@ config PINCTRL_PALMAS open drain configuration for the Palmas series devices like TPS65913, TPS80036 etc. +config PINCTRL_PEF2256 + tristate "Lantiq PEF2256 (FALC56) pin controller driver" + depends on OF && FRAMER_PEF2256 + select PINMUX + select PINCONF + select GENERIC_PINCONF + help + This option enables the pin controller support for the Lantiq PEF2256 + framer, also known as FALC56. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pinctrl-pef2256. + config PINCTRL_PIC32 bool "Microchip PIC32 pin controller driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index dd6cda270294..800c4219fcc1 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO) += pinctrl-microchip-sgpio.o obj-$(CONFIG_PINCTRL_MLXBF3) += pinctrl-mlxbf3.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o +obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o diff --git a/drivers/pinctrl/pinctrl-pef2256.c b/drivers/pinctrl/pinctrl-pef2256.c new file mode 100644 index 000000000000..868ea33bec3c --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PEF2256 also known as FALC56 driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port Configuration 1..4 */ +#define PEF2256_PC1 0x80 +#define PEF2256_PC2 0x81 +#define PEF2256_PC3 0x82 +#define PEF2256_PC4 0x83 +#define PEF2256_12_PC_RPC_MASK GENMASK(6, 4) +#define PEF2256_12_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x0) +#define PEF2256_12_PC_RPC_RFM FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x1) +#define PEF2256_12_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x2) +#define PEF2256_12_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x3) +#define PEF2256_12_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x4) +#define PEF2256_12_PC_RPC_DLR FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x5) +#define PEF2256_12_PC_RPC_FREEZE FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x6) +#define PEF2256_12_PC_RPC_RFSP FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_MASK GENMASK(4, 0) +#define PEF2256_12_PC_XPC_SYPX FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x0) +#define PEF2256_12_PC_XPC_XFMS FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x1) +#define PEF2256_12_PC_XPC_XSIG FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x2) +#define PEF2256_12_PC_XPC_TCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x3) +#define PEF2256_12_PC_XPC_XMFB FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x4) +#define PEF2256_12_PC_XPC_XSIGM FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x5) +#define PEF2256_12_PC_XPC_DLX FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x6) +#define PEF2256_12_PC_XPC_XCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_XLT FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x8) +#define PEF2256_2X_PC_RPC_MASK GENMASK(7, 4) +#define PEF2256_2X_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x0) +#define PEF2256_2X_PC_RPC_RFM FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x1) +#define PEF2256_2X_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x2) +#define PEF2256_2X_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x3) +#define PEF2256_2X_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x4) +#define PEF2256_2X_PC_RPC_DLR FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x5) +#define PEF2256_2X_PC_RPC_FREEZE FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x6) +#define PEF2256_2X_PC_RPC_RFSP FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x7) +#define PEF2256_2X_PC_RPC_GPI FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x9) +#define PEF2256_2X_PC_RPC_GPOH FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xa) +#define PEF2256_2X_PC_RPC_GPOL FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xb) +#define PEF2256_2X_PC_RPC_LOS FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0xc) +#define PEF2256_2X_PC_XPC_MASK GENMASK(3, 0) +#define PEF2256_2X_PC_XPC_SYPX FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x0) +#define PEF2256_2X_PC_XPC_XFMS FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x1) +#define PEF2256_2X_PC_XPC_XSIG FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x2) +#define PEF2256_2X_PC_XPC_TCLK FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x3) +#define PEF2256_2X_PC_XPC_XMFB FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x4) +#define PEF2256_2X_PC_XPC_XSIGM FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x5) +#define PEF2256_2X_PC_XPC_DLX FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x6) +#define PEF2256_2X_PC_XPC_XCLK FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x7) +#define PEF2256_2X_PC_XPC_XLT FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x8) +#define PEF2256_2X_PC_XPC_GPI FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0x9) +#define PEF2256_2X_PC_XPC_GPOH FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0xa) +#define PEF2256_2X_PC_XPC_GPOL FIELD_PREP_CONST(PEF2256_2X_PC_XPC_MASK, 0xb) + +struct pef2256_pinreg_desc { + int offset; + u8 mask; +}; + +struct pef2256_function_desc { + const char *name; + const char * const*groups; + unsigned int ngroups; + u8 func_val; +}; + +struct pef2256_pinctrl { + struct device *dev; + struct regmap *regmap; + enum pef2256_version version; + struct pinctrl_desc pctrl_desc; + const struct pef2256_function_desc *functions; + unsigned int nfunctions; +}; + +static int pef2256_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + return pef2256->pctrl_desc.npins; +} + +static const char *pef2256_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + return pef2256->pctrl_desc.pins[selector].name; +} + +static int pef2256_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + /* We map 1 group <-> 1 pin */ + *pins = &pef2256->pctrl_desc.pins[selector].number; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops pef2256_pctlops = { + .get_groups_count = pef2256_get_groups_count, + .get_group_name = pef2256_get_group_name, + .get_group_pins = pef2256_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static int pef2256_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + return pef2256->nfunctions; +} + +static const char *pef2256_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + return pef2256->functions[selector].name; +} + +static int pef2256_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + + *groups = pef2256->functions[selector].groups; + *num_groups = pef2256->functions[selector].ngroups; + return 0; +} + +static int pef2256_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, + unsigned int group_selector) +{ + struct pef2256_pinctrl *pef2256 = pinctrl_dev_get_drvdata(pctldev); + const struct pef2256_pinreg_desc *pinreg_desc; + u8 func_val; + + /* We map 1 group <-> 1 pin */ + pinreg_desc = pef2256->pctrl_desc.pins[group_selector].drv_data; + func_val = pef2256->functions[func_selector].func_val; + + return regmap_update_bits(pef2256->regmap, pinreg_desc->offset, + pinreg_desc->mask, func_val); +} + +static const struct pinmux_ops pef2256_pmxops = { + .get_functions_count = pef2256_get_functions_count, + .get_function_name = pef2256_get_function_name, + .get_function_groups = pef2256_get_function_groups, + .set_mux = pef2256_set_mux, +}; + +#define PEF2256_PINCTRL_PIN(_number, _name, _offset, _mask) { \ + .number = _number, \ + .name = _name, \ + .drv_data = &(struct pef2256_pinreg_desc) { \ + .offset = _offset, \ + .mask = _mask, \ + }, \ +} + +static const struct pinctrl_pin_desc pef2256_v12_pins[] = { + PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_12_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_12_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_12_PC_XPC_MASK), +}; + +static const struct pinctrl_pin_desc pef2256_v2x_pins[] = { + PEF2256_PINCTRL_PIN(0, "RPA", PEF2256_PC1, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(1, "RPB", PEF2256_PC2, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(2, "RPC", PEF2256_PC3, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(3, "RPD", PEF2256_PC4, PEF2256_2X_PC_RPC_MASK), + PEF2256_PINCTRL_PIN(4, "XPA", PEF2256_PC1, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(5, "XPB", PEF2256_PC2, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(6, "XPC", PEF2256_PC3, PEF2256_2X_PC_XPC_MASK), + PEF2256_PINCTRL_PIN(7, "XPD", PEF2256_PC4, PEF2256_2X_PC_XPC_MASK), +}; + +static const char *const pef2256_rp_groups[] = { "RPA", "RPB", "RPC", "RPD" }; +static const char *const pef2256_xp_groups[] = { "XPA", "XPB", "XPC", "XPD" }; +static const char *const pef2256_all_groups[] = { "RPA", "RPB", "RPC", "RPD", + "XPA", "XPB", "XPC", "XPD" }; + +#define PEF2256_FUNCTION(_name, _func_val, _groups) { \ + .name = _name, \ + .groups = _groups, \ + .ngroups = ARRAY_SIZE(_groups), \ + .func_val = _func_val, \ +} + +static const struct pef2256_function_desc pef2256_v2x_functions[] = { + PEF2256_FUNCTION("SYPR", PEF2256_2X_PC_RPC_SYPR, pef2256_rp_groups), + PEF2256_FUNCTION("RFM", PEF2256_2X_PC_RPC_RFM, pef2256_rp_groups), + PEF2256_FUNCTION("RFMB", PEF2256_2X_PC_RPC_RFMB, pef2256_rp_groups), + PEF2256_FUNCTION("RSIGM", PEF2256_2X_PC_RPC_RSIGM, pef2256_rp_groups), + PEF2256_FUNCTION("RSIG", PEF2256_2X_PC_RPC_RSIG, pef2256_rp_groups), + PEF2256_FUNCTION("DLR", PEF2256_2X_PC_RPC_DLR, pef2256_rp_groups), + PEF2256_FUNCTION("FREEZE", PEF2256_2X_PC_RPC_FREEZE, pef2256_rp_groups), + PEF2256_FUNCTION("RFSP", PEF2256_2X_PC_RPC_RFSP, pef2256_rp_groups), + PEF2256_FUNCTION("LOS", PEF2256_2X_PC_RPC_LOS, pef2256_rp_groups), + + PEF2256_FUNCTION("SYPX", PEF2256_2X_PC_XPC_SYPX, pef2256_xp_groups), + PEF2256_FUNCTION("XFMS", PEF2256_2X_PC_XPC_XFMS, pef2256_xp_groups), + PEF2256_FUNCTION("XSIG", PEF2256_2X_PC_XPC_XSIG, pef2256_xp_groups), + PEF2256_FUNCTION("TCLK", PEF2256_2X_PC_XPC_TCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XMFB", PEF2256_2X_PC_XPC_XMFB, pef2256_xp_groups), + PEF2256_FUNCTION("XSIGM", PEF2256_2X_PC_XPC_XSIGM, pef2256_xp_groups), + PEF2256_FUNCTION("DLX", PEF2256_2X_PC_XPC_DLX, pef2256_xp_groups), + PEF2256_FUNCTION("XCLK", PEF2256_2X_PC_XPC_XCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XLT", PEF2256_2X_PC_XPC_XLT, pef2256_xp_groups), + + PEF2256_FUNCTION("GPI", PEF2256_2X_PC_RPC_GPI | PEF2256_2X_PC_XPC_GPI, + pef2256_all_groups), + PEF2256_FUNCTION("GPOH", PEF2256_2X_PC_RPC_GPOH | PEF2256_2X_PC_XPC_GPOH, + pef2256_all_groups), + PEF2256_FUNCTION("GPOL", PEF2256_2X_PC_RPC_GPOL | PEF2256_2X_PC_XPC_GPOL, + pef2256_all_groups), +}; + +static const struct pef2256_function_desc pef2256_v12_functions[] = { + PEF2256_FUNCTION("SYPR", PEF2256_12_PC_RPC_SYPR, pef2256_rp_groups), + PEF2256_FUNCTION("RFM", PEF2256_12_PC_RPC_RFM, pef2256_rp_groups), + PEF2256_FUNCTION("RFMB", PEF2256_12_PC_RPC_RFMB, pef2256_rp_groups), + PEF2256_FUNCTION("RSIGM", PEF2256_12_PC_RPC_RSIGM, pef2256_rp_groups), + PEF2256_FUNCTION("RSIG", PEF2256_12_PC_RPC_RSIG, pef2256_rp_groups), + PEF2256_FUNCTION("DLR", PEF2256_12_PC_RPC_DLR, pef2256_rp_groups), + PEF2256_FUNCTION("FREEZE", PEF2256_12_PC_RPC_FREEZE, pef2256_rp_groups), + PEF2256_FUNCTION("RFSP", PEF2256_12_PC_RPC_RFSP, pef2256_rp_groups), + + PEF2256_FUNCTION("SYPX", PEF2256_12_PC_XPC_SYPX, pef2256_xp_groups), + PEF2256_FUNCTION("XFMS", PEF2256_12_PC_XPC_XFMS, pef2256_xp_groups), + PEF2256_FUNCTION("XSIG", PEF2256_12_PC_XPC_XSIG, pef2256_xp_groups), + PEF2256_FUNCTION("TCLK", PEF2256_12_PC_XPC_TCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XMFB", PEF2256_12_PC_XPC_XMFB, pef2256_xp_groups), + PEF2256_FUNCTION("XSIGM", PEF2256_12_PC_XPC_XSIGM, pef2256_xp_groups), + PEF2256_FUNCTION("DLX", PEF2256_12_PC_XPC_DLX, pef2256_xp_groups), + PEF2256_FUNCTION("XCLK", PEF2256_12_PC_XPC_XCLK, pef2256_xp_groups), + PEF2256_FUNCTION("XLT", PEF2256_12_PC_XPC_XLT, pef2256_xp_groups), +}; + +static int pef2256_register_pinctrl(struct pef2256_pinctrl *pef2256) +{ + struct pinctrl_dev *pctrl; + + pef2256->pctrl_desc.name = dev_name(pef2256->dev); + pef2256->pctrl_desc.owner = THIS_MODULE; + pef2256->pctrl_desc.pctlops = &pef2256_pctlops; + pef2256->pctrl_desc.pmxops = &pef2256_pmxops; + if (pef2256->version == PEF2256_VERSION_1_2) { + pef2256->pctrl_desc.pins = pef2256_v12_pins; + pef2256->pctrl_desc.npins = ARRAY_SIZE(pef2256_v12_pins); + pef2256->functions = pef2256_v12_functions; + pef2256->nfunctions = ARRAY_SIZE(pef2256_v12_functions); + } else { + pef2256->pctrl_desc.pins = pef2256_v2x_pins; + pef2256->pctrl_desc.npins = ARRAY_SIZE(pef2256_v2x_pins); + pef2256->functions = pef2256_v2x_functions; + pef2256->nfunctions = ARRAY_SIZE(pef2256_v2x_functions); + } + + pctrl = devm_pinctrl_register(pef2256->dev, &pef2256->pctrl_desc, pef2256); + if (IS_ERR(pctrl)) + return dev_err_probe(pef2256->dev, PTR_ERR(pctrl), + "pinctrl driver registration failed\n"); + + return 0; +} + +static void pef2256_reset_pinmux(struct pef2256_pinctrl *pef2256) +{ + u8 val; + /* + * Reset values cannot be used. + * They define the SYPR/SYPX pin mux for all the RPx and XPx pins and + * Only one pin can be muxed to SYPR and one pin can be muxed to SYPX. + * Choose here an other reset value. + */ + if (pef2256->version == PEF2256_VERSION_1_2) + val = PEF2256_12_PC_XPC_XCLK | PEF2256_12_PC_RPC_RFSP; + else + val = PEF2256_2X_PC_XPC_GPI | PEF2256_2X_PC_RPC_GPI; + + regmap_write(pef2256->regmap, PEF2256_PC1, val); + regmap_write(pef2256->regmap, PEF2256_PC2, val); + regmap_write(pef2256->regmap, PEF2256_PC3, val); + regmap_write(pef2256->regmap, PEF2256_PC4, val); +} + +static int pef2256_pinctrl_probe(struct platform_device *pdev) +{ + struct pef2256_pinctrl *pef2256_pinctrl; + struct pef2256 *pef2256; + int ret; + + pef2256_pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pef2256_pinctrl), GFP_KERNEL); + if (!pef2256_pinctrl) + return -ENOMEM; + + device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent)); + + pef2256 = dev_get_drvdata(pdev->dev.parent); + + pef2256_pinctrl->dev = &pdev->dev; + pef2256_pinctrl->regmap = pef2256_get_regmap(pef2256); + pef2256_pinctrl->version = pef2256_get_version(pef2256); + + platform_set_drvdata(pdev, pef2256_pinctrl); + + pef2256_reset_pinmux(pef2256_pinctrl); + ret = pef2256_register_pinctrl(pef2256_pinctrl); + if (ret) + return ret; + + return 0; +} + +static struct platform_driver pef2256_pinctrl_driver = { + .driver = { + .name = "lantiq-pef2256-pinctrl", + }, + .probe = pef2256_pinctrl_probe, +}; +module_platform_driver(pef2256_pinctrl_driver); + +MODULE_AUTHOR("Herve Codina "); +MODULE_DESCRIPTION("PEF2256 pin controller driver"); +MODULE_LICENSE("GPL");