From patchwork Sun Oct 30 18:30:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sander Vanheule X-Patchwork-Id: 1696841 X-Patchwork-Delegate: sander@svanheule.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=zcine6oJ; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=svanheule.net header.i=@svanheule.net header.a=rsa-sha256 header.s=mail1707 header.b=HoNx6Ycf; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4N0lN002Rbz23kv for ; Mon, 31 Oct 2022 05:35:43 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=tGkQ/O31XbiQH5OHyiGo1wCT+lj4v7+IzOql6r86yxQ=; b=zcine6oJUOiFak YSZ1vE4uvSmdQiJY9uj0bbjV3ixDkJ/+wEpIeGj9gBEor+7VXopuX3ZsVgaCCC1fQiaXoskWHAVnn OLp/0P216f+RR8BUXtyt8efIBj0sRqogBoa7hq9o12cuRq5sG6p2XSIc1xwgAejPJ18yT8QybVuti GzHR8Zdk5OlPB0fZBWU4kvu6bgPqkHyvhTRbBfS5lTpYsL3Sxp+4VtVnOi2QPUdtScNCuxaFrto2A c7O9wMzJO842fV3NVlZ/0z7nA53NBZy7dwxjKuIx0lsSIKjRJBIPdZvVip/lc5D6ndfGHrAMpcDs4 XpkqmXuP/pmXCcvQ4XPQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1opD6a-001nQH-95; Sun, 30 Oct 2022 18:32:20 +0000 Received: from polaris.svanheule.net ([84.16.241.116]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1opD5f-001n4o-8k for openwrt-devel@lists.openwrt.org; Sun, 30 Oct 2022 18:31:28 +0000 Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 4241733BF21; Sun, 30 Oct 2022 19:31:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1667154674; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OJoq97K97c+KEl4uL2TMotH9JMP5KeaAXh2qlPiPIGg=; b=HoNx6YcfkpC+RRFtKXClPRCN78LCSNLdjvIsHWYCKoGncOEVJ3HUemleyua4tf9U22LUly 9ivVEKma5vb2xpdYM3R7N/xxQa8jNMlCjtWA0m9ZfD/9xH5m6lfEnDApwoCNUWj69ZpkRJ APpUe8MdnKTeotMavU8aRaC65L8kUykXCqaQi+sldj9Q1WfspKqo4z9zEONRh79mhMti/j KIWFFkxtvNJELi5pAjwKfLOPXceX6MdIEMDLWY21VWtP1/WGV63kyRM/qMuSkq/GI1DJLa F1+C+UIBoWRguGfotHUFis2ZSXty0BpdSjBGp7z0PVXaMyPJyl38AfJbFVHSzQ== From: Sander Vanheule To: openwrt-devel@lists.openwrt.org, Olliver Schinagl , Alexandru Gagniuc Cc: INAGAKI Hiroshi , Markus Stockhausen , Stijn Segers , Sander Vanheule Subject: [PATCH v3 02/13] realtek: add switch core pinctrl driver Date: Sun, 30 Oct 2022 19:30:55 +0100 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221030_113123_764454_69DA0245 X-CRM114-Status: GOOD ( 25.49 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Since control bits for different pin muxes are scattered throughout the switch core's register space, pin control features are provided by a table of regmap fields. This should be flexible enough to a [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Since control bits for different pin muxes are scattered throughout the switch core's register space, pin control features are provided by a table of regmap fields. This should be flexible enough to allow support for currently unsupported pin muxes, and newer SoC generations providing similar features. This driver add initial support for Maple and Cypress managed gigabit switch SoCs, with RTL838xM and RTL839xM part numbers. The fast ethernet switch SoCs from these parts series, with numbers RTL833xM and RTL835xM, should also be supported, but have not been tested. Signed-off-by: Sander Vanheule --- Changes in v3: - Merge symbol selection updates to ease bisecting --- .../drivers/pinctrl/pinctrl-rtl-switchcore.c | 447 ++++++++++++++++++ ...inctrl-add-pinctrl-for-Realtek-maple.patch | 49 ++ target/linux/realtek/rtl838x/config-5.10 | 1 + target/linux/realtek/rtl839x/config-5.10 | 1 + 4 files changed, 498 insertions(+) create mode 100644 target/linux/realtek/files-5.10/drivers/pinctrl/pinctrl-rtl-switchcore.c create mode 100644 target/linux/realtek/patches-5.10/201-pinctrl-add-pinctrl-for-Realtek-maple.patch diff --git a/target/linux/realtek/files-5.10/drivers/pinctrl/pinctrl-rtl-switchcore.c b/target/linux/realtek/files-5.10/drivers/pinctrl/pinctrl-rtl-switchcore.c new file mode 100644 index 000000000000..15a8b08793c9 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/pinctrl/pinctrl-rtl-switchcore.c @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinmux.h" + +/** + * struct rtl_swcore_mux_desc - switchcore pin group information + * + * Pins are frequently muxed between alternative functions, but the control + * bits for the muxes are scattered throughout the switchcore's register space. + * Provide a regmap-based interface to flexibly manage these mux fields, which + * may vary in size and do not always provide a GPIO function. + * + * @name: name to identify the pin group + * @field: register field with mux control bits + * @pins: array of numbers of the pins in this group + * @npins: number of pins in this group + */ +struct rtl_swcore_mux_desc { + const char *name; + struct reg_field field; + const unsigned int *pins; + unsigned int npins; +}; + +#define SWITCHCORE_MUX(_name, _field, _pins) { \ + .name = (_name), \ + .field = _field, \ + .pins = (_pins), \ + .npins = ARRAY_SIZE(_pins), \ + } + +/** + * struct rtl_swcore_mux_cfg - stored mux configuration + * + * @mux: pointer to the mux descriptor + * @setting: value to write in the mux's register field to apply this configuration + */ +struct rtl_swcore_mux_cfg { + const struct rtl_swcore_mux_desc *mux; + unsigned int setting; +}; + +/** + * struct rtl_swcore_function_desc - switchcore function information + * + * @name: name of this function + * @configs: list of mux configurations that enable this function on said mux + * @nconfigs: length of the @configs list + */ +struct rtl_swcore_function_desc { + const char *name; + const struct rtl_swcore_mux_cfg *configs; + unsigned int nconfigs; +}; + +#define SWITCHCORE_FUNCTION(_name, _configs) { \ + .name = (_name), \ + .configs = (_configs), \ + .nconfigs = ARRAY_SIZE(_configs), \ + } + +struct rtl_swcore_config { + const struct pinctrl_pin_desc *pins; + unsigned int npins; + const struct rtl_swcore_function_desc *functions; + unsigned int nfunctions; + const struct rtl_swcore_mux_desc **groups; + unsigned int ngroups; +}; + +struct rtl_swcore_pinctrl { + struct pinctrl_desc pdesc; + struct device *dev; + const struct rtl_swcore_config *config; + struct regmap_field **mux_fields; +}; + +/* + * RTL838x chips come in LQFP packages with 216 pins. Pins are indexed + * counter-clockwise, starting with pin 1 at the bottom left. + */ +static const struct pinctrl_pin_desc rtl838x_swcore_pins[] = { + /* JTAG pins */ + PINCTRL_PIN(28, "JTAG_TCK/GPIO13"), + PINCTRL_PIN(29, "JTAG_TMS/GPIO12"), + PINCTRL_PIN(30, "JTAG_TDO/GPIO10"), + PINCTRL_PIN(31, "JTAG_TDI/GPIO11"), + PINCTRL_PIN(32, "JTAG_TRST#/GPIO14"), + /* aux MDIO bus pins */ + PINCTRL_PIN(110, "GPIO3/AUX_MDIO"), + PINCTRL_PIN(111, "GPIO2/AUX_MDC"), + /* system LED pin */ + PINCTRL_PIN(113, "GPIO0/SYS_LED"), + /* UART1/SPI slave pins */ + PINCTRL_PIN(116, "SSPI_CS#/UART1_RX"), + PINCTRL_PIN(117, "SSPI_SO/UART1_TX"), + /* ethernet MDIO bus pins */ + PINCTRL_PIN(120, "MDC"), + PINCTRL_PIN(121, "MDIO"), +}; + +static const unsigned int rtl838x_jtag_pins[] = {28, 29, 30, 31, 32}; +static const unsigned int rtl838x_aux_mdio_pins[] = {110, 111}; +static const unsigned int rtl838x_sys_led_pins[] = {113}; +static const unsigned int rtl838x_uart1_pins[] = {116, 117}; + +static const struct rtl_swcore_mux_desc rtl838x_mux_jtag = + SWITCHCORE_MUX("jtag", REG_FIELD(0x1000, 2, 3), rtl838x_jtag_pins); + +static const struct rtl_swcore_mux_desc rtl838x_mux_aux_mdio = + SWITCHCORE_MUX("aux-mdio", REG_FIELD(0xa0e0, 0, 0), rtl838x_aux_mdio_pins); + +static const struct rtl_swcore_mux_desc rtl838x_mux_sys_led = + SWITCHCORE_MUX("sys-led", REG_FIELD(0xa000, 15, 15), rtl838x_sys_led_pins); + +static const struct rtl_swcore_mux_desc rtl838x_mux_uart1 = + SWITCHCORE_MUX("uart1", REG_FIELD(0x1000, 4, 4), rtl838x_uart1_pins); + +static const struct rtl_swcore_mux_desc *rtl838x_groups[] = { + &rtl838x_mux_jtag, + &rtl838x_mux_aux_mdio, + &rtl838x_mux_sys_led, + &rtl838x_mux_uart1, +}; + +static const struct rtl_swcore_mux_cfg rtl838x_gpio_configs[] = { + {&rtl838x_mux_jtag, 2}, + {&rtl838x_mux_aux_mdio, 0}, + {&rtl838x_mux_sys_led, 0}, +}; +static const struct rtl_swcore_mux_cfg rtl838x_aux_mdio_configs[] = { + {&rtl838x_mux_aux_mdio, 1}, +}; +static const struct rtl_swcore_mux_cfg rtl838x_sys_led_configs[] = { + {&rtl838x_mux_sys_led, 1}, +}; +static const struct rtl_swcore_mux_cfg rtl838x_uart1_configs[] = { + {&rtl838x_mux_uart1, 1}, +}; +static const struct rtl_swcore_mux_cfg rtl838x_spi_slave_configs[] = { + {&rtl838x_mux_uart1, 0}, +}; + +static const struct rtl_swcore_function_desc rtl838x_functions[] = { + SWITCHCORE_FUNCTION("gpio", rtl838x_gpio_configs), + SWITCHCORE_FUNCTION("aux-mdio", rtl838x_aux_mdio_configs), + SWITCHCORE_FUNCTION("sys-led", rtl838x_sys_led_configs), + SWITCHCORE_FUNCTION("uart1", rtl838x_uart1_configs), + SWITCHCORE_FUNCTION("spi-slave", rtl838x_spi_slave_configs), +}; + +static const struct rtl_swcore_config rtl838x_config = { + .pins = rtl838x_swcore_pins, + .npins = ARRAY_SIZE(rtl838x_swcore_pins), + .functions = rtl838x_functions, + .nfunctions = ARRAY_SIZE(rtl838x_functions), + .groups = rtl838x_groups, + .ngroups = ARRAY_SIZE(rtl838x_groups), +}; + +/* + * RTL839x chips are in BGA packages with 26×26 positions. Board designs number + * these as 1..26 for the rows, and A..AF for the columns, with position A1 in + * the bottom left corner. Letters I, O, Q, S, X, and Z are skipped; presumably + * to avoid ambiguities. + * This gives a total of 676 positions. Note that not all positions will + * actually have a pad, and many pads will be used for power. + * + * Index pins using (ROW + 26×COL), where ROW and COL mapped as: + * - ROW: {1..26} -> {0..25} + * - COL: {A..AF} -> {0..25} + * + * ROW | 1 2 3 4 5 6 7 8 9 10 11 12 13 + * COL | A B C D E F G H J K L M N + * ------|--------------------------------------- + * INDEX | 0 1 2 3 4 5 6 7 8 9 10 11 12 + * + * ROW | 14 15 16 17 18 19 20 21 22 23 24 25 26 + * COL | P R T U V W Y AA AB AC AD AE AF + * ------|--------------------------------------- + * INDEX | 13 14 15 16 17 18 19 20 21 22 23 24 25 + * + * Since there are no datasheets available, use a virtual pin range starting at + * 676 for pins with unknown positions. When actual pin positions are found + * (if ever), these can the be mapped to their real values. + */ +#define RTL839X_VPIN(num) (26 * 26 + (num)) +#define RTL839X_VPIN_DESC(num, name) PINCTRL_PIN(RTL839X_VPIN(num), name) + +static const struct pinctrl_pin_desc rtl839x_swcore_pins[] = { + /* sys-led, or gpio0 */ + RTL839X_VPIN_DESC(0, "GPIO0/SYS_LED"), + /* aux MDIO pins */ + RTL839X_VPIN_DESC(1, "AUX_MDC"), + RTL839X_VPIN_DESC(2, "AUX_MDIO"), + /* JTAG/UART1 pins, UART1 functions from RTL9301 pin correspondence */ + RTL839X_VPIN_DESC(3, "JTAG_TMS/UART1_RTS/GPIO3"), + RTL839X_VPIN_DESC(4, "JTAG_TCK/UART1_CTS/GPIO4"), + RTL839X_VPIN_DESC(5, "JTAG_TRST#/UART1_/GPIO5"), + RTL839X_VPIN_DESC(6, "JTAG_TDI/UART1_RX/GPIO6"), + RTL839X_VPIN_DESC(7, "JTAG_TDO/UART1_TX/GPIO7"), +}; + +static const unsigned int rtl839x_jtag_pins[] = { + RTL839X_VPIN(3), RTL839X_VPIN(4), RTL839X_VPIN(5), RTL839X_VPIN(6), RTL839X_VPIN(7) +}; +static const unsigned int rtl839x_aux_mdio_pins[] = { + RTL839X_VPIN(1), RTL839X_VPIN(2) +}; +static const unsigned int rtl839x_sys_led_pins[] = {RTL839X_VPIN(0)}; + +static const struct rtl_swcore_mux_desc rtl839x_mux_jtag = + SWITCHCORE_MUX("jtag", REG_FIELD(0x0004, 0, 1), rtl839x_jtag_pins); + +/* + * This field is three bits in size, but the SDK isn't clear on what it means + * When enabling the RTL8231 MDIO peripheral, it sets a value of 0x4. + */ +static const struct rtl_swcore_mux_desc rtl839x_mux_aux_mdio = + SWITCHCORE_MUX("aux-mdio", REG_FIELD(0x00e4, 18, 20), rtl839x_aux_mdio_pins); + +static const struct rtl_swcore_mux_desc rtl839x_mux_sys_led = + SWITCHCORE_MUX("sys-led", REG_FIELD(0x00e4, 14, 14), rtl839x_sys_led_pins); + +static const struct rtl_swcore_mux_desc *rtl839x_groups[] = { + &rtl839x_mux_jtag, + &rtl839x_mux_aux_mdio, + &rtl839x_mux_sys_led, +}; + +static const struct rtl_swcore_mux_cfg rtl839x_gpio_configs[] = { + {&rtl839x_mux_jtag, 2}, + {&rtl839x_mux_aux_mdio, 0}, /* TODO verify pin correspondence */ + {&rtl839x_mux_sys_led, 0}, +}; +static const struct rtl_swcore_mux_cfg rtl839x_aux_mdio_configs[] = { + {&rtl839x_mux_aux_mdio, 4}, +}; +static const struct rtl_swcore_mux_cfg rtl839x_jtag_configs[] = { + {&rtl839x_mux_jtag, 0}, +}; +static const struct rtl_swcore_mux_cfg rtl839x_sys_led_configs[] = { + {&rtl839x_mux_sys_led, 1}, +}; +static const struct rtl_swcore_mux_cfg rtl839x_uart1_configs[] = { + {&rtl839x_mux_jtag, 1}, +}; + +static const struct rtl_swcore_function_desc rtl839x_functions[] = { + SWITCHCORE_FUNCTION("gpio", rtl839x_gpio_configs), + SWITCHCORE_FUNCTION("aux-mdio", rtl839x_aux_mdio_configs), + SWITCHCORE_FUNCTION("jtag", rtl839x_jtag_configs), + SWITCHCORE_FUNCTION("sys-led", rtl839x_sys_led_configs), + SWITCHCORE_FUNCTION("uart1", rtl839x_uart1_configs), +}; + +static const struct rtl_swcore_config rtl839x_config = { + .pins = rtl839x_swcore_pins, + .npins = ARRAY_SIZE(rtl839x_swcore_pins), + .functions = rtl839x_functions, + .nfunctions = ARRAY_SIZE(rtl839x_functions), + .groups = rtl839x_groups, + .ngroups = ARRAY_SIZE(rtl839x_groups), +}; + +static int rtl_swcore_group_count(struct pinctrl_dev *pctldev) +{ + struct rtl_swcore_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); + + return priv->config->ngroups; +} + +static const char *rtl_swcore_group_name(struct pinctrl_dev *pctldev, unsigned int selector) +{ + struct rtl_swcore_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); + + return priv->config->groups[selector]->name; +}; + +static int rtl_swcore_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, const unsigned int **pins, + unsigned int *num_pins) +{ + struct rtl_swcore_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); + + *pins = priv->config->groups[selector]->pins; + *num_pins = priv->config->groups[selector]->npins; + + return 0; +} + +static int rtl_swcore_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int group) +{ + struct rtl_swcore_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); + const struct rtl_swcore_function_desc *function; + const struct rtl_swcore_mux_cfg *cfg; + const struct rtl_swcore_mux_desc *mux; + unsigned int i; + + function = &priv->config->functions[selector]; + mux = priv->config->groups[group]; + + for (i = 0; i < function->nconfigs; i++) { + cfg = &function->configs[i]; + if (cfg->mux == mux) + return regmap_field_write(priv->mux_fields[group], cfg->setting); + } + + /* Should never hit this, unless something was misconfigured */ + return -ENODEV; +} + +static const struct pinctrl_ops rtl_swcore_pinctrl_ops = { + .get_groups_count = rtl_swcore_group_count, + .get_group_name = rtl_swcore_group_name, + .get_group_pins = rtl_swcore_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static const struct pinmux_ops rtl_swcore_pinmux_ops = { + .get_functions_count = pinmux_generic_get_function_count, + .get_function_name = pinmux_generic_get_function_name, + .get_function_groups = pinmux_generic_get_function_groups, + .set_mux = rtl_swcore_set_mux, + .strict = true, +}; + +static int rtl_swcore_functions_init(struct pinctrl_dev *pctl, struct rtl_swcore_pinctrl *priv) +{ + const struct rtl_swcore_function_desc *function; + unsigned int ngroups; + const char **groups; + unsigned int f_idx; + unsigned int g_idx; + + for (f_idx = 0; f_idx < priv->config->nfunctions; f_idx++) { + function = &priv->config->functions[f_idx]; + ngroups = function->nconfigs; + + groups = devm_kcalloc(priv->dev, ngroups, sizeof(*groups), GFP_KERNEL); + if (!groups) + return -ENOMEM; + + for (g_idx = 0; g_idx < ngroups; g_idx++) + groups[g_idx] = function->configs[g_idx].mux->name; + + pinmux_generic_add_function(pctl, function->name, groups, ngroups, NULL); + } + + return 0; +} + +static const struct of_device_id of_rtl_swcore_pinctrl_match[] = { + { + .compatible = "realtek,maple-pinctrl", + .data = &rtl838x_config, + }, + { + .compatible = "realtek,cypress-pinctrl", + .data = &rtl839x_config, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, of_rtl_swcore_pinctrl_match); + +static int rtl_swcore_pinctrl_probe(struct platform_device *pdev) +{ + const struct rtl_swcore_config *config; + struct rtl_swcore_pinctrl *priv; + struct device *dev = &pdev->dev; + struct pinctrl_dev *pctldev; + struct regmap_field *field; + struct regmap *regmap; + unsigned int mux; + int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + config = of_device_get_match_data(dev); + if (!config) + return dev_err_probe(dev, -EINVAL, "no config\n"); + + regmap = device_node_to_regmap(of_get_parent(dev_of_node(dev))); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "failed to find parent regmap\n"); + + priv->dev = dev; + priv->config = config; + priv->pdesc.name = "realtek-switchcore-pinctrl"; + priv->pdesc.owner = THIS_MODULE; + priv->pdesc.pctlops = &rtl_swcore_pinctrl_ops; + priv->pdesc.pmxops = &rtl_swcore_pinmux_ops; + priv->pdesc.pins = config->pins; + priv->pdesc.npins = config->npins; + + priv->mux_fields = devm_kcalloc(dev, config->ngroups, sizeof(*priv->mux_fields), + GFP_KERNEL); + if (!priv->mux_fields) + return -ENOMEM; + + for (mux = 0; mux < config->ngroups; mux++) { + field = devm_regmap_field_alloc(dev, regmap, config->groups[mux]->field); + if (IS_ERR(field)) + return PTR_ERR(field); + + priv->mux_fields[mux] = field; + } + + err = devm_pinctrl_register_and_init(dev, &priv->pdesc, priv, &pctldev); + if (err) + return dev_err_probe(dev, err, "failed to register\n"); + + err = rtl_swcore_functions_init(pctldev, priv); + if (err) + return dev_err_probe(dev, err, "failed to generate function list\n"); + + err = pinctrl_enable(pctldev); + if (err) + return dev_err_probe(dev, err, "failed to enable\n"); + + return 0; +}; + +static struct platform_driver rtl_swcore_pinctrl_driver = { + .driver = { + .name = "realtek-switchcore-pinctrl", + .of_match_table = of_rtl_swcore_pinctrl_match + }, + .probe = rtl_swcore_pinctrl_probe, +}; +module_platform_driver(rtl_swcore_pinctrl_driver); diff --git a/target/linux/realtek/patches-5.10/201-pinctrl-add-pinctrl-for-Realtek-maple.patch b/target/linux/realtek/patches-5.10/201-pinctrl-add-pinctrl-for-Realtek-maple.patch new file mode 100644 index 000000000000..16819e37a1f6 --- /dev/null +++ b/target/linux/realtek/patches-5.10/201-pinctrl-add-pinctrl-for-Realtek-maple.patch @@ -0,0 +1,49 @@ +From 0efa8d564f27519d20fed39f5d650e50cbc34a0b Mon Sep 17 00:00:00 2001 +From: Sander Vanheule +Date: Mon, 11 Jul 2022 21:37:17 +0200 +Subject: pinctrl: add pinctrl for Realtek switch SoCs + +Since control bits for different pin muxes are scattered throughout the +switch core's register space, pin control features are provided by a +table of regmap fields. This should be flexible enough to allow support +for currently unsupported pin muxes, and newer SoC generations providing +similar features. + +This driver add initial support for Maple and Cypress managed gigabit +switch SoCs, with RTL838xM and RTL839xM part numbers. The fast ethernet +switch SoCs from these parts series, with numbers RTL833xM and RTL835xM, +should also be supported, but have not been tested. + +Signed-off-by: Sander Vanheule +--- + +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -215,6 +215,17 @@ config PINCTRL_ROCKCHIP + select MFD_SYSCON + select OF_GPIO + ++config PINCTRL_RTL_SWITCHCORE ++ bool "Realtek switch core pinctrl driver" ++ default MFD_REALTEK_SWITCHCORE ++ depends on MFD_REALTEK_SWITCHCORE || COMPILE_TEST ++ select PINMUX ++ select GENERIC_PINMUX_FUNCTIONS ++ select MFD_SYSCON ++ help ++ Driver for pin control fields in RTL83xx and RTL93xx managed ethernet ++ switch SoCs. ++ + config PINCTRL_SINGLE + tristate "One-register-per-pin type device tree based pinctrl driver" + depends on OF +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl- + obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o + obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RTL_SWITCHCORE) += pinctrl-rtl-switchcore.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_SIRF) += sirf/ + obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o diff --git a/target/linux/realtek/rtl838x/config-5.10 b/target/linux/realtek/rtl838x/config-5.10 index a642be8b2aee..fdfbc2461c1b 100644 --- a/target/linux/realtek/rtl838x/config-5.10 +++ b/target/linux/realtek/rtl838x/config-5.10 @@ -183,6 +183,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y CONFIG_PINCTRL=y +CONFIG_PINCTRL_RTL_SWITCHCORE=y CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y diff --git a/target/linux/realtek/rtl839x/config-5.10 b/target/linux/realtek/rtl839x/config-5.10 index 51e6d5e8e072..344e9f988209 100644 --- a/target/linux/realtek/rtl839x/config-5.10 +++ b/target/linux/realtek/rtl839x/config-5.10 @@ -178,6 +178,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y CONFIG_PINCTRL=y +CONFIG_PINCTRL_RTL_SWITCHCORE=y CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y