From patchwork Wed Aug 9 13:27:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 133295 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c44e:0:b0:3f2:4152:657d with SMTP id w14csp2865855vqr; Wed, 9 Aug 2023 08:12:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHgTnhwGocNaDGSl9sxE11NjfcJ6iRs1HrQhC+MYVg4X9mrHOeBVU+FgjIv56cp7X9ryu01 X-Received: by 2002:a05:6a00:23d6:b0:686:9385:4642 with SMTP id g22-20020a056a0023d600b0068693854642mr3060139pfc.6.1691593948518; Wed, 09 Aug 2023 08:12:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691593948; cv=none; d=google.com; s=arc-20160816; b=vd3L2ahjDjexlDeS48Sf0kIejyNqBgMa/rolvJz+qxCM4MALLxZqxidDtJKF85srCE 7VDn6qGy+R2nAN6ALYp9Mpo8p4fxCLbCF/3i4UbAtEZG1lhv3V3vOUPLw8GI6bxeyq4L b2tfn83jWGHt2ImmSmOt3Y4nU3ON+YcHy7Qsv6YeK21/PvK7BpLoejLI3OZyrqlJK0zW h1pR9RGYs4Owk1+XeSHAfLJNuV8Sv0gCYGWPOy9ROzL3qhHpSDhS9EFWxGJ//KvlgNmy zx0lktekcEAPH0TuTTlJMwwznNzcZ1nj3MSX4Iyk7+bzqEsR6HVHUFeh1tyQ2XTzvmh4 5Q1A== 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=rS2zWooHhgb+vyQgWTMsrAfLSIShj/3Jf6uxaMRe1HU=; fh=OtJVFpZ5Y8/ND7g8QcUIbRSFhG4LznwcYYtG4zWKevM=; b=JhWSW6YHqpKomvTTPlktpNCQBSkm4WpwDjv7fr90S5mRyP7dit5WYB8EpbxirnbNYq 12ke4EpMCxBCbLQGQJsWAdMLGV6KB+GrZOJLyvgfkORI9PtnUBwdtmvUqORLEoxqCY1A 5skSYzuph9YmA8CGmPpS1z3ed6COWSOwR9jXj3Ehqbihkk3sKLnalk9Ft+HPJG3bNUIA v/XW6xBsbtfN1G9i3+vPUoaEWq1EKCKk/La2vMwF1b4LnP8RRh5ITCDbhqn8AGZ909yO xz3dDEO3utoNElKE0GqrSaXKaPbQAl4BeT3Vr6dAY1p98FUp7sw5vl/zK0P/0GQEznTG 21vA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=OD0tVPI4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bq26-20020a056a000e1a00b006872089fa3fsi7361500pfb.283.2023.08.09.08.12.15; Wed, 09 Aug 2023 08:12:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=OD0tVPI4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233106AbjHINat (ORCPT + 99 others); Wed, 9 Aug 2023 09:30:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53780 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233194AbjHINaF (ORCPT ); Wed, 9 Aug 2023 09:30:05 -0400 Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::222]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C5FF35AA; Wed, 9 Aug 2023 06:29:08 -0700 (PDT) Received: by mail.gandi.net (Postfix) with ESMTPA id 16EF940005; Wed, 9 Aug 2023 13:28:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1691587740; 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=rS2zWooHhgb+vyQgWTMsrAfLSIShj/3Jf6uxaMRe1HU=; b=OD0tVPI4its3xoCQwR2kuSjyJdL1f9tD7WhzU4k9oQzWYN4PEj1D0a2CQhD79fEeVl9mcT YnwUWbOwDR4gxoFj8ts4Z6v6m5ENiWRkDOMgkpxSSPLO0l0imlEp9Pxt4fs2kpR3gDk2YH 4pvVTEzQlSf8kkly4VWwvuVG/7FAPz+aEXUfd2FbTZTFDfptmTO5jZ6hqEJtJT3bvXw19Y EZyJmv1n1W+P6YKbwkJs+jqtymZbTDYlWCVO+I3tdY1srcFiWRYuHdttkXk1Axi7VirXWX SiHniltAIAQP2Doskw7unc/tyvp8T+HeZUqInL3fijfcQM1c8V07bPgka+hxDg== From: Herve Codina To: Herve Codina , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Lee Jones , 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, Thomas Petazzoni Subject: [PATCH v3 25/28] pinctrl: Add support for the Lantic PEF2256 pinmux Date: Wed, 9 Aug 2023 15:27:52 +0200 Message-ID: <20230809132757.2470544-26-herve.codina@bootlin.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230809132757.2470544-1-herve.codina@bootlin.com> References: <20230809132757.2470544-1-herve.codina@bootlin.com> MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773764815884267729 X-GMAIL-MSGID: 1773764815884267729 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 --- drivers/pinctrl/Kconfig | 14 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pef2256-regs.h | 65 ++++++ drivers/pinctrl/pinctrl-pef2256.c | 308 +++++++++++++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pef2256-regs.h create mode 100644 drivers/pinctrl/pinctrl-pef2256.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 57d57af1f624..a3aa96b59c97 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -377,6 +377,20 @@ 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 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 482b391b5deb..8f211f7671a8 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_PINCTRL_MLXBF3) += pinctrl-mlxbf3.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.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-regs.h b/drivers/pinctrl/pinctrl-pef2256-regs.h new file mode 100644 index 000000000000..cacc492a1623 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256-regs.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PEF2256 pinctrl registers definition + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __PEF2256_PINCTRL_REGS_H__ +#define __PEF2256_PINCTRL_REGS_H__ + +#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) + +#endif /* __PEF2256_PINCTRL_REGS_H__ */ diff --git a/drivers/pinctrl/pinctrl-pef2256.c b/drivers/pinctrl/pinctrl-pef2256.c new file mode 100644 index 000000000000..773f701ecf23 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256.c @@ -0,0 +1,308 @@ +// 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 "pinctrl-pef2256-regs.h" + +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)) { + dev_err(pef2256->dev, "pinctrl driver registration failed\n"); + return PTR_ERR(pctrl); + } + + 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");