From patchwork Wed Feb 22 15:44:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralph Siemsen X-Patchwork-Id: 655692 Delivered-To: patch@linaro.org Received: by 2002:adf:a3c6:0:0:0:0:0 with SMTP id m6csp760469wrb; Wed, 22 Feb 2023 07:45:23 -0800 (PST) X-Google-Smtp-Source: AK7set/x42C4PGEnz82kH19Rtru+3aV81EBvSLPa/Jrfna6Q5YwnPXWq37NW+LHk51K+PjWjO4nL X-Received: by 2002:a05:6870:7028:b0:16e:591:3b94 with SMTP id u40-20020a056870702800b0016e05913b94mr10930641oae.15.1677080723489; Wed, 22 Feb 2023 07:45:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677080723; cv=none; d=google.com; s=arc-20160816; b=W+cIZzgWvpt4md7wZkHKcjKd69GG1MNn2crSq/uMV0HJUXGW0wJdcIg7IaWS3/QD6v XQ9IToBpIUm1vewIhvhviFXLZMxUOB122+lCPVaxbOkGJ3iq5PB63y3RYxey0jnM/wzZ 3Qno+QtJwE3BtIxf0mNoYjRiUBkHFaea0q+yeK57B/SjSYcWWuL8Ly9I9bkDD13Sd8ZT lUx6uDtZlWh389k6sQwLLN0dLnPzZrysHouO/ZnxKylqn43ndLAzYKgxP00sTT8r+nEH lucKuBasIwuiikmn8gyOPhaYNV5rdde9as8DLsxe6W1ZyRvOqk4by1Cj82HjR7kDGvar YQ+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=KYXQBvx4qFdLMedg2BaSEjtvFFjNZWqDyqeSzU5SZGQ=; b=x3YRmsM4Vt7cmXVG3zCK1dGpyPlG77RJlbydbCxnilWlcB+1t7A4qejCEUnSIOukdn KoVk6BYzV2ubVlvY0gw3FODyv4mw5pXGf+aviDlf2WR4FTBu97l7AL2isPq9697yl/pD 8FcCU7RSv+aVEIhx+DJfSVqegOvtO5LhMJOUVeWHcsB7dLcNnr8nrIv8LMS0KMAsNEJI rC0QcmaSA1OwJ3mzJ4Hm3yLA3SJVe+C0YGJZaINeaTg/+aczHXJCXfSgJtRtuo+xZNrB +a7zPJvgkFQxN19g/+ed5CjsciuA4tt9pDZ1+zfr5TfoL+6nwJn0onxrISwsAHhPYehE 243w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yT0pORxo; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id uk22-20020a0568714e9600b0016ddeb5bc69si22322682oab.56.2023.02.22.07.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Feb 2023 07:45:23 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yT0pORxo; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4E92D85AF7; Wed, 22 Feb 2023 16:44:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="yT0pORxo"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 42B5E85AD1; Wed, 22 Feb 2023 16:44:36 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 35D3185AA1 for ; Wed, 22 Feb 2023 16:44:28 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ralph.siemsen@linaro.org Received: by mail-qt1-x82e.google.com with SMTP id w42so7925232qtc.2 for ; Wed, 22 Feb 2023 07:44:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; 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=KYXQBvx4qFdLMedg2BaSEjtvFFjNZWqDyqeSzU5SZGQ=; b=yT0pORxoAeHQ0SNFKot3GRzkbHn604v0S7v/AOkcZULZZ+p64HYtOA0wfER3XlIErq lTnnK1DNuMemb8kQEiluy5JFuYGuRB+p6dFm9744FZRN8aOsQmkrO6huLjNLv+7X4HPq MvzTN0Hb05zXZEGzhprUEcu6iX/n2G68ui7zZDXN246fQ846LBRMdWrMcDlvFQ0cbu2W sAP2/pfyTA1izsLwyuqqmOeQqzWP3B5yYoxMrFVD1rB8JgjxkieVAtL3rsO0EePZfRq1 HWi0CSEnUNZbP3N/K0VB8TDt/Rhd0p5Rbee0ZCbma03k1Y8XtH8gM4+NpA9qK5RI6g/k Khfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=KYXQBvx4qFdLMedg2BaSEjtvFFjNZWqDyqeSzU5SZGQ=; b=dMPrABlvxBTnHZaUa9syTGh7OK4jL45hw3u4icuZtnvDLA0Np2s6r6+gHhn15D0UEl XS0RRisCxN2Mqr9WkyXHXw1vY6PMh9QEnz4nBJuJKKKNLsp/haJzhy4AB5VVFboGPdDS djE0rled2Nc6bl4ohnghKGk9V1BdxmYCKkHd3o2YPEjoqU0kc0MUSpgv3NXwZ2XMXkX8 VbNyxoFyo3ynMpxlfS8S3+Cn71cuBS2Q703AM7zX1f7A2/ifSKO9d0IkmJ+tcChLVPWd 6Xb6NHMdNJP/nZ0D0hhsOMbvRu5aIpa/jdDXLlXg/sT/eyafI4r4s0vZZ3/km664gv9P R+qw== X-Gm-Message-State: AO0yUKXRJEuSEUvJMiY5MctQA7zqQthvsOqyxdFT8/3s6MftzfKskSqM W0sFUs+I8LrYDo3ElRjzlQ4GWxsv4PBgmXpPOOw= X-Received: by 2002:ac8:7c54:0:b0:3b7:ec70:30af with SMTP id o20-20020ac87c54000000b003b7ec7030afmr15392375qtv.46.1677080667646; Wed, 22 Feb 2023 07:44:27 -0800 (PST) Received: from maple.netwinder.org (rfs.netwinder.org. [206.248.184.2]) by smtp.gmail.com with ESMTPSA id t41-20020a05622a182900b003bfad864e81sm522246qtc.69.2023.02.22.07.44.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Feb 2023 07:44:27 -0800 (PST) From: Ralph Siemsen To: u-boot@lists.denx.de Cc: Ralph Siemsen , Ashok Reddy Soma , Damien Le Moal , Hai Pham , Jim Liu , Leo Yu-Chi Liang , Marek Vasut , Niklas Cassel , Samuel Holland Subject: [RFC PATCH v3 4/9] pinctrl: renesas: add R906G032 driver Date: Wed, 22 Feb 2023 10:44:09 -0500 Message-Id: <20230222154414.49219-5-ralph.siemsen@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230222154414.49219-1-ralph.siemsen@linaro.org> References: <20230222154414.49219-1-ralph.siemsen@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean Pinctrl/pinconf driver for Renesas RZ/N1 (R906G032) SoC. This is quite rudimentary right now, and only supports applying a default pin configuration as specified by the device tree. Signed-off-by: Ralph Siemsen --- (no changes since v1) drivers/pinctrl/Makefile | 1 + drivers/pinctrl/renesas/Kconfig | 7 + drivers/pinctrl/renesas/Makefile | 1 + drivers/pinctrl/renesas/pinctrl-rzn1.c | 379 +++++++++++++++++++++ include/dt-bindings/pinctrl/rzn1-pinctrl.h | 141 ++++++++ 5 files changed, 529 insertions(+) create mode 100644 drivers/pinctrl/renesas/pinctrl-rzn1.c create mode 100644 include/dt-bindings/pinctrl/rzn1-pinctrl.h diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 3b167d099f..450267732c 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_INTEL) += intel/ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ obj-$(CONFIG_ARCH_NPCM) += nuvoton/ obj-$(CONFIG_ARCH_RMOBILE) += renesas/ +obj-$(CONFIG_ARCH_RZN1) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 8f994d8d76..b707d7549b 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -127,3 +127,10 @@ config PINCTRL_PFC_R7S72100 Support pin multiplexing control on Renesas RZ/A1 R7S72100 SoCs. endif + +config PINCTRL_RZN1 + bool "Renesas RZ/N1 R906G032 pin control driver" + depends on ARCH_RZN1 + default y if ARCH_RZN1 + help + Support pin multiplexing control on Renesas RZ/N1 R906G032 SoCs. diff --git a/drivers/pinctrl/renesas/Makefile b/drivers/pinctrl/renesas/Makefile index 1198c86855..39b2f65f2e 100644 --- a/drivers/pinctrl/renesas/Makefile +++ b/drivers/pinctrl/renesas/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o obj-$(CONFIG_PINCTRL_PFC_R8A779A0) += pfc-r8a779a0.o obj-$(CONFIG_PINCTRL_PFC_R7S72100) += pfc-r7s72100.o +obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o diff --git a/drivers/pinctrl/renesas/pinctrl-rzn1.c b/drivers/pinctrl/renesas/pinctrl-rzn1.c new file mode 100644 index 0000000000..fdc43c8e71 --- /dev/null +++ b/drivers/pinctrl/renesas/pinctrl-rzn1.c @@ -0,0 +1,379 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2014-2018 Renesas Electronics Europe Limited + * + * Phil Edworthy + * Based on a driver originally written by Michel Pollet at Renesas. + */ + +#include + +#include +#include +#include +#include +#include + +/* Field positions and masks in the pinmux registers */ +#define RZN1_L1_PIN_DRIVE_STRENGTH 10 +#define RZN1_L1_PIN_DRIVE_STRENGTH_4MA 0 +#define RZN1_L1_PIN_DRIVE_STRENGTH_6MA 1 +#define RZN1_L1_PIN_DRIVE_STRENGTH_8MA 2 +#define RZN1_L1_PIN_DRIVE_STRENGTH_12MA 3 +#define RZN1_L1_PIN_PULL 8 +#define RZN1_L1_PIN_PULL_NONE 0 +#define RZN1_L1_PIN_PULL_UP 1 +#define RZN1_L1_PIN_PULL_DOWN 3 +#define RZN1_L1_FUNCTION 0 +#define RZN1_L1_FUNC_MASK 0xf +#define RZN1_L1_FUNCTION_L2 0xf + +/* + * The hardware manual describes two levels of multiplexing, but it's more + * logical to think of the hardware as three levels, with level 3 consisting of + * the multiplexing for Ethernet MDIO signals. + * + * Level 1 functions go from 0 to 9, with level 1 function '15' (0xf) specifying + * that level 2 functions are used instead. Level 2 has a lot more options, + * going from 0 to 61. Level 3 allows selection of MDIO functions which can be + * floating, or one of seven internal peripherals. Unfortunately, there are two + * level 2 functions that can select MDIO, and two MDIO channels so we have four + * sets of level 3 functions. + * + * For this driver, we've compounded the numbers together, so: + * 0 to 9 is level 1 + * 10 to 71 is 10 + level 2 number + * 72 to 79 is 72 + MDIO0 source for level 2 MDIO function. + * 80 to 87 is 80 + MDIO0 source for level 2 MDIO_E1 function. + * 88 to 95 is 88 + MDIO1 source for level 2 MDIO function. + * 96 to 103 is 96 + MDIO1 source for level 2 MDIO_E1 function. + * Examples: + * Function 28 corresponds UART0 + * Function 73 corresponds to MDIO0 to GMAC0 + * + * There are 170 configurable pins (called PL_GPIO in the datasheet). + */ + +/* + * Structure detailing the HW registers on the RZ/N1 devices. + * Both the Level 1 mux registers and Level 2 mux registers have the same + * structure. The only difference is that Level 2 has additional MDIO registers + * at the end. + */ +struct rzn1_pinctrl_regs { + u32 conf[170]; + u32 pad0[86]; + u32 status_protect; /* 0x400 */ + /* MDIO mux registers, level2 only */ + u32 l2_mdio[2]; +}; + +#define NUM_CONF ARRAY_SIZE(((struct rzn1_pinctrl_regs *)0)->conf) + +#define level1_write(map, member, val) \ + regmap_range_set(map, 0, struct rzn1_pinctrl_regs, member, val) + +#define level1_read(map, member, valp) \ + regmap_range_get(map, 0, struct rzn1_pinctrl_regs, member, valp) + +#define level2_write(map, member, val) \ + regmap_range_set(map, 1, struct rzn1_pinctrl_regs, member, val) + +#define level2_read(map, member, valp) \ + regmap_range_get(map, 1, struct rzn1_pinctrl_regs, member, valp) + +/** + * struct rzn1_pmx_func - describes rzn1 pinmux functions + * @name: the name of this specific function + * @groups: corresponding pin groups + * @num_groups: the number of groups + */ +struct rzn1_pmx_func { + const char *name; + const char **groups; + unsigned int num_groups; +}; + +/** + * struct rzn1_pin_group - describes an rzn1 pin group + * @name: the name of this specific pin group + * @func: the name of the function selected by this group + * @npins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + * @pins: array of pins. Needed due to pinctrl_ops.get_group_pins() + * @pin_ids: array of pin_ids, i.e. the value used to select the mux + */ +struct rzn1_pin_group { + const char *name; + const char *func; + unsigned int npins; + unsigned int *pins; + u8 *pin_ids; +}; + +struct rzn1_pinctrl { + struct device *dev; + struct clk *clk; + struct pinctrl_dev *pctl; + u32 lev1_protect_phys; + u32 lev2_protect_phys; + int mdio_func[2]; + + struct rzn1_pin_group *groups; + unsigned int ngroups; + + struct rzn1_pmx_func *functions; + unsigned int nfunctions; +}; + +struct rzn1_pinctrl_priv { + struct regmap *regmap; + u32 lev1_protect_phys; + u32 lev2_protect_phys; + + struct clk *clk; +}; + +enum { + LOCK_LEVEL1 = 0x1, + LOCK_LEVEL2 = 0x2, + LOCK_ALL = LOCK_LEVEL1 | LOCK_LEVEL2, +}; + +static void rzn1_hw_set_lock(struct rzn1_pinctrl_priv *priv, u8 lock, u8 value) +{ + /* + * The pinmux configuration is locked by writing the physical address of + * the status_protect register to itself. It is unlocked by writing the + * address | 1. + */ + if (lock & LOCK_LEVEL1) { + u32 val = priv->lev1_protect_phys | !(value & LOCK_LEVEL1); + + level1_write(priv->regmap, status_protect, val); + } + + if (lock & LOCK_LEVEL2) { + u32 val = priv->lev2_protect_phys | !(value & LOCK_LEVEL2); + + level2_write(priv->regmap, status_protect, val); + } +} + +static void rzn1_pinctrl_mdio_select(struct rzn1_pinctrl_priv *priv, int mdio, + u32 func) +{ + debug("setting mdio%d to %u\n", mdio, func); + + level2_write(priv->regmap, l2_mdio[mdio], func); +} + +/* + * Using a composite pin description, set the hardware pinmux registers + * with the corresponding values. + * Make sure to unlock write protection and reset it afterward. + * + * NOTE: There is no protection for potential concurrency, it is assumed these + * calls are serialized already. + */ +static int rzn1_set_hw_pin_func(struct rzn1_pinctrl_priv *priv, + unsigned int pin, unsigned int func) +{ + u32 l1_cache; + u32 l2_cache; + u32 l1; + u32 l2; + + /* Level 3 MDIO multiplexing */ + if (func >= RZN1_FUNC_MDIO0_HIGHZ && + func <= RZN1_FUNC_MDIO1_E1_SWITCH) { + int mdio_channel; + u32 mdio_func; + + if (func <= RZN1_FUNC_MDIO1_HIGHZ) + mdio_channel = 0; + else + mdio_channel = 1; + + /* Get MDIO func, and convert the func to the level 2 number */ + if (func <= RZN1_FUNC_MDIO0_SWITCH) { + mdio_func = func - RZN1_FUNC_MDIO0_HIGHZ; + func = RZN1_FUNC_ETH_MDIO; + } else if (func <= RZN1_FUNC_MDIO0_E1_SWITCH) { + mdio_func = func - RZN1_FUNC_MDIO0_E1_HIGHZ; + func = RZN1_FUNC_ETH_MDIO_E1; + } else if (func <= RZN1_FUNC_MDIO1_SWITCH) { + mdio_func = func - RZN1_FUNC_MDIO1_HIGHZ; + func = RZN1_FUNC_ETH_MDIO; + } else { + mdio_func = func - RZN1_FUNC_MDIO1_E1_HIGHZ; + func = RZN1_FUNC_ETH_MDIO_E1; + } + rzn1_pinctrl_mdio_select(priv, mdio_channel, mdio_func); + } + + /* Note here, we do not allow anything past the MDIO Mux values */ + if (pin >= NUM_CONF || func >= RZN1_FUNC_MDIO0_HIGHZ) + return -EINVAL; + + level1_read(priv->regmap, conf[pin], &l1); + l1_cache = l1; + level2_read(priv->regmap, conf[pin], &l2); + l2_cache = l2; + + debug("setting func for pin %u to %u\n", pin, func); + + l1 &= ~(RZN1_L1_FUNC_MASK << RZN1_L1_FUNCTION); + + if (func < RZN1_FUNC_L2_OFFSET) { + l1 |= (func << RZN1_L1_FUNCTION); + } else { + l1 |= (RZN1_L1_FUNCTION_L2 << RZN1_L1_FUNCTION); + + l2 = func - RZN1_FUNC_L2_OFFSET; + } + + /* If either configuration changes, we update both anyway */ + if (l1 != l1_cache || l2 != l2_cache) { + level1_write(priv->regmap, conf[pin], l1); + level2_write(priv->regmap, conf[pin], l2); + } + + return 0; +} + +static int rzn1_pinconf_set(struct rzn1_pinctrl_priv *priv, unsigned int pin, + unsigned int bias, unsigned int strength) +{ + u32 l1, l1_cache; + u32 drv = RZN1_L1_PIN_DRIVE_STRENGTH_8MA; + + level1_read(priv->regmap, conf[pin], &l1); + l1_cache = l1; + + switch (bias) { + case PIN_CONFIG_BIAS_PULL_UP: + debug("set pin %d pull up\n", pin); + l1 &= ~(0x3 << RZN1_L1_PIN_PULL); + l1 |= (RZN1_L1_PIN_PULL_UP << RZN1_L1_PIN_PULL); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + debug("set pin %d pull down\n", pin); + l1 &= ~(0x3 << RZN1_L1_PIN_PULL); + l1 |= (RZN1_L1_PIN_PULL_DOWN << RZN1_L1_PIN_PULL); + break; + case PIN_CONFIG_BIAS_DISABLE: + debug("set pin %d bias off\n", pin); + l1 &= ~(0x3 << RZN1_L1_PIN_PULL); + l1 |= (RZN1_L1_PIN_PULL_NONE << RZN1_L1_PIN_PULL); + break; + } + + switch (strength) { + case 4: + drv = RZN1_L1_PIN_DRIVE_STRENGTH_4MA; + break; + case 6: + drv = RZN1_L1_PIN_DRIVE_STRENGTH_6MA; + break; + case 8: + drv = RZN1_L1_PIN_DRIVE_STRENGTH_8MA; + break; + case 12: + drv = RZN1_L1_PIN_DRIVE_STRENGTH_12MA; + break; + } + + debug("set pin %d drv %umA\n", pin, drv); + + l1 &= ~(0x3 << RZN1_L1_PIN_DRIVE_STRENGTH); + l1 |= (drv << RZN1_L1_PIN_DRIVE_STRENGTH); + + if (l1 != l1_cache) + level1_write(priv->regmap, conf[pin], l1); + + return 0; +} + +static int rzn1_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + struct rzn1_pinctrl_priv *priv = dev_get_priv(dev); + int size; + int ret; + u32 val; + u32 bias; + + /* Pullup/down bias, common to all pins in group */ + bias = PIN_CONFIG_BIAS_PULL_UP; + if (dev_read_bool(config, "bias-disable")) + bias = PIN_CONFIG_BIAS_DISABLE; + else if (dev_read_bool(config, "bias-pull-up")) + bias = PIN_CONFIG_BIAS_PULL_UP; + else if (dev_read_bool(config, "bias-pull-down")) + bias = PIN_CONFIG_BIAS_PULL_DOWN; + + /* Drive strength, common to all pins in group */ + u32 strength = dev_read_u32_default(config, "drive-strength", 8); + + /* Number of pins */ + ret = dev_read_size(config, "pinmux"); + if (ret < 0) + return ret; + + size = ret / sizeof(val); + + for (int i = 0; i < size; i++) { + ret = dev_read_u32_index(config, "pinmux", i, &val); + if (ret) + return ret; + unsigned int pin = val & 0xff; + unsigned int func = val >> 8; + + debug("%s pin %d func %d bias %d strength %d\n", + config->name, pin, func, bias, strength); + + rzn1_hw_set_lock(priv, LOCK_ALL, LOCK_ALL); + rzn1_set_hw_pin_func(priv, pin, func); + rzn1_pinconf_set(priv, pin, bias, strength); + rzn1_hw_set_lock(priv, LOCK_ALL, 0); + } + + return 0; +} + +static struct pinctrl_ops rzn1_pinctrl_ops = { + .set_state = rzn1_pinctrl_set_state, +}; + +static int rzn1_pinctrl_probe(struct udevice *dev) +{ + struct rzn1_pinctrl_priv *priv = dev_get_priv(dev); + ofnode node = dev_ofnode(dev); + int ret; + + ret = regmap_init_mem(node, &priv->regmap); + if (ret) + return ret; + + priv->lev1_protect_phys = (u32)regmap_get_range(priv->regmap, 0) + + offsetof(struct rzn1_pinctrl_regs, status_protect); + priv->lev2_protect_phys = (u32)regmap_get_range(priv->regmap, 1) + + offsetof(struct rzn1_pinctrl_regs, status_protect); + + return 0; +} + +static const struct udevice_id rzn1_pinctrl_ids[] = { + { .compatible = "renesas,rzn1-pinctrl", }, + { }, +}; + +U_BOOT_DRIVER(pinctrl_rzn1) = { + .name = "rzn1-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = rzn1_pinctrl_ids, + .priv_auto = sizeof(struct rzn1_pinctrl_priv), + .ops = &rzn1_pinctrl_ops, + .probe = rzn1_pinctrl_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/dt-bindings/pinctrl/rzn1-pinctrl.h b/include/dt-bindings/pinctrl/rzn1-pinctrl.h new file mode 100644 index 0000000000..21d6cc4d59 --- /dev/null +++ b/include/dt-bindings/pinctrl/rzn1-pinctrl.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Defines macros and constants for Renesas RZ/N1 pin controller pin + * muxing functions. + */ +#ifndef __DT_BINDINGS_RZN1_PINCTRL_H +#define __DT_BINDINGS_RZN1_PINCTRL_H + +#define RZN1_PINMUX(_gpio, _func) \ + (((_func) << 8) | (_gpio)) + +/* + * Given the different levels of muxing on the SoC, it was decided to + * 'linearize' them into one numerical space. So mux level 1, 2 and the MDIO + * muxes are all represented by one single value. + * + * You can derive the hardware value pretty easily too, as + * 0...9 are Level 1 + * 10...71 are Level 2. The Level 2 mux will be set to this + * value - RZN1_FUNC_L2_OFFSET, and the Level 1 mux will be + * set accordingly. + * 72...103 are for the 2 MDIO muxes. + */ +#define RZN1_FUNC_HIGHZ 0 +#define RZN1_FUNC_0L 1 +#define RZN1_FUNC_CLK_ETH_MII_RGMII_RMII 2 +#define RZN1_FUNC_CLK_ETH_NAND 3 +#define RZN1_FUNC_QSPI 4 +#define RZN1_FUNC_SDIO 5 +#define RZN1_FUNC_LCD 6 +#define RZN1_FUNC_LCD_E 7 +#define RZN1_FUNC_MSEBIM 8 +#define RZN1_FUNC_MSEBIS 9 +#define RZN1_FUNC_L2_OFFSET 10 /* I'm Special */ + +#define RZN1_FUNC_HIGHZ1 (RZN1_FUNC_L2_OFFSET + 0) +#define RZN1_FUNC_ETHERCAT (RZN1_FUNC_L2_OFFSET + 1) +#define RZN1_FUNC_SERCOS3 (RZN1_FUNC_L2_OFFSET + 2) +#define RZN1_FUNC_SDIO_E (RZN1_FUNC_L2_OFFSET + 3) +#define RZN1_FUNC_ETH_MDIO (RZN1_FUNC_L2_OFFSET + 4) +#define RZN1_FUNC_ETH_MDIO_E1 (RZN1_FUNC_L2_OFFSET + 5) +#define RZN1_FUNC_USB (RZN1_FUNC_L2_OFFSET + 6) +#define RZN1_FUNC_MSEBIM_E (RZN1_FUNC_L2_OFFSET + 7) +#define RZN1_FUNC_MSEBIS_E (RZN1_FUNC_L2_OFFSET + 8) +#define RZN1_FUNC_RSV (RZN1_FUNC_L2_OFFSET + 9) +#define RZN1_FUNC_RSV_E (RZN1_FUNC_L2_OFFSET + 10) +#define RZN1_FUNC_RSV_E1 (RZN1_FUNC_L2_OFFSET + 11) +#define RZN1_FUNC_UART0_I (RZN1_FUNC_L2_OFFSET + 12) +#define RZN1_FUNC_UART0_I_E (RZN1_FUNC_L2_OFFSET + 13) +#define RZN1_FUNC_UART1_I (RZN1_FUNC_L2_OFFSET + 14) +#define RZN1_FUNC_UART1_I_E (RZN1_FUNC_L2_OFFSET + 15) +#define RZN1_FUNC_UART2_I (RZN1_FUNC_L2_OFFSET + 16) +#define RZN1_FUNC_UART2_I_E (RZN1_FUNC_L2_OFFSET + 17) +#define RZN1_FUNC_UART0 (RZN1_FUNC_L2_OFFSET + 18) +#define RZN1_FUNC_UART0_E (RZN1_FUNC_L2_OFFSET + 19) +#define RZN1_FUNC_UART1 (RZN1_FUNC_L2_OFFSET + 20) +#define RZN1_FUNC_UART1_E (RZN1_FUNC_L2_OFFSET + 21) +#define RZN1_FUNC_UART2 (RZN1_FUNC_L2_OFFSET + 22) +#define RZN1_FUNC_UART2_E (RZN1_FUNC_L2_OFFSET + 23) +#define RZN1_FUNC_UART3 (RZN1_FUNC_L2_OFFSET + 24) +#define RZN1_FUNC_UART3_E (RZN1_FUNC_L2_OFFSET + 25) +#define RZN1_FUNC_UART4 (RZN1_FUNC_L2_OFFSET + 26) +#define RZN1_FUNC_UART4_E (RZN1_FUNC_L2_OFFSET + 27) +#define RZN1_FUNC_UART5 (RZN1_FUNC_L2_OFFSET + 28) +#define RZN1_FUNC_UART5_E (RZN1_FUNC_L2_OFFSET + 29) +#define RZN1_FUNC_UART6 (RZN1_FUNC_L2_OFFSET + 30) +#define RZN1_FUNC_UART6_E (RZN1_FUNC_L2_OFFSET + 31) +#define RZN1_FUNC_UART7 (RZN1_FUNC_L2_OFFSET + 32) +#define RZN1_FUNC_UART7_E (RZN1_FUNC_L2_OFFSET + 33) +#define RZN1_FUNC_SPI0_M (RZN1_FUNC_L2_OFFSET + 34) +#define RZN1_FUNC_SPI0_M_E (RZN1_FUNC_L2_OFFSET + 35) +#define RZN1_FUNC_SPI1_M (RZN1_FUNC_L2_OFFSET + 36) +#define RZN1_FUNC_SPI1_M_E (RZN1_FUNC_L2_OFFSET + 37) +#define RZN1_FUNC_SPI2_M (RZN1_FUNC_L2_OFFSET + 38) +#define RZN1_FUNC_SPI2_M_E (RZN1_FUNC_L2_OFFSET + 39) +#define RZN1_FUNC_SPI3_M (RZN1_FUNC_L2_OFFSET + 40) +#define RZN1_FUNC_SPI3_M_E (RZN1_FUNC_L2_OFFSET + 41) +#define RZN1_FUNC_SPI4_S (RZN1_FUNC_L2_OFFSET + 42) +#define RZN1_FUNC_SPI4_S_E (RZN1_FUNC_L2_OFFSET + 43) +#define RZN1_FUNC_SPI5_S (RZN1_FUNC_L2_OFFSET + 44) +#define RZN1_FUNC_SPI5_S_E (RZN1_FUNC_L2_OFFSET + 45) +#define RZN1_FUNC_SGPIO0_M (RZN1_FUNC_L2_OFFSET + 46) +#define RZN1_FUNC_SGPIO1_M (RZN1_FUNC_L2_OFFSET + 47) +#define RZN1_FUNC_GPIO (RZN1_FUNC_L2_OFFSET + 48) +#define RZN1_FUNC_CAN (RZN1_FUNC_L2_OFFSET + 49) +#define RZN1_FUNC_I2C (RZN1_FUNC_L2_OFFSET + 50) +#define RZN1_FUNC_SAFE (RZN1_FUNC_L2_OFFSET + 51) +#define RZN1_FUNC_PTO_PWM (RZN1_FUNC_L2_OFFSET + 52) +#define RZN1_FUNC_PTO_PWM1 (RZN1_FUNC_L2_OFFSET + 53) +#define RZN1_FUNC_PTO_PWM2 (RZN1_FUNC_L2_OFFSET + 54) +#define RZN1_FUNC_PTO_PWM3 (RZN1_FUNC_L2_OFFSET + 55) +#define RZN1_FUNC_PTO_PWM4 (RZN1_FUNC_L2_OFFSET + 56) +#define RZN1_FUNC_DELTA_SIGMA (RZN1_FUNC_L2_OFFSET + 57) +#define RZN1_FUNC_SGPIO2_M (RZN1_FUNC_L2_OFFSET + 58) +#define RZN1_FUNC_SGPIO3_M (RZN1_FUNC_L2_OFFSET + 59) +#define RZN1_FUNC_SGPIO4_S (RZN1_FUNC_L2_OFFSET + 60) +#define RZN1_FUNC_MAC_MTIP_SWITCH (RZN1_FUNC_L2_OFFSET + 61) + +#define RZN1_FUNC_MDIO_OFFSET (RZN1_FUNC_L2_OFFSET + 62) + +/* These are MDIO0 peripherals for the RZN1_FUNC_ETH_MDIO function */ +#define RZN1_FUNC_MDIO0_HIGHZ (RZN1_FUNC_MDIO_OFFSET + 0) +#define RZN1_FUNC_MDIO0_GMAC0 (RZN1_FUNC_MDIO_OFFSET + 1) +#define RZN1_FUNC_MDIO0_GMAC1 (RZN1_FUNC_MDIO_OFFSET + 2) +#define RZN1_FUNC_MDIO0_ECAT (RZN1_FUNC_MDIO_OFFSET + 3) +#define RZN1_FUNC_MDIO0_S3_MDIO0 (RZN1_FUNC_MDIO_OFFSET + 4) +#define RZN1_FUNC_MDIO0_S3_MDIO1 (RZN1_FUNC_MDIO_OFFSET + 5) +#define RZN1_FUNC_MDIO0_HWRTOS (RZN1_FUNC_MDIO_OFFSET + 6) +#define RZN1_FUNC_MDIO0_SWITCH (RZN1_FUNC_MDIO_OFFSET + 7) +/* These are MDIO0 peripherals for the RZN1_FUNC_ETH_MDIO_E1 function */ +#define RZN1_FUNC_MDIO0_E1_HIGHZ (RZN1_FUNC_MDIO_OFFSET + 8) +#define RZN1_FUNC_MDIO0_E1_GMAC0 (RZN1_FUNC_MDIO_OFFSET + 9) +#define RZN1_FUNC_MDIO0_E1_GMAC1 (RZN1_FUNC_MDIO_OFFSET + 10) +#define RZN1_FUNC_MDIO0_E1_ECAT (RZN1_FUNC_MDIO_OFFSET + 11) +#define RZN1_FUNC_MDIO0_E1_S3_MDIO0 (RZN1_FUNC_MDIO_OFFSET + 12) +#define RZN1_FUNC_MDIO0_E1_S3_MDIO1 (RZN1_FUNC_MDIO_OFFSET + 13) +#define RZN1_FUNC_MDIO0_E1_HWRTOS (RZN1_FUNC_MDIO_OFFSET + 14) +#define RZN1_FUNC_MDIO0_E1_SWITCH (RZN1_FUNC_MDIO_OFFSET + 15) + +/* These are MDIO1 peripherals for the RZN1_FUNC_ETH_MDIO function */ +#define RZN1_FUNC_MDIO1_HIGHZ (RZN1_FUNC_MDIO_OFFSET + 16) +#define RZN1_FUNC_MDIO1_GMAC0 (RZN1_FUNC_MDIO_OFFSET + 17) +#define RZN1_FUNC_MDIO1_GMAC1 (RZN1_FUNC_MDIO_OFFSET + 18) +#define RZN1_FUNC_MDIO1_ECAT (RZN1_FUNC_MDIO_OFFSET + 19) +#define RZN1_FUNC_MDIO1_S3_MDIO0 (RZN1_FUNC_MDIO_OFFSET + 20) +#define RZN1_FUNC_MDIO1_S3_MDIO1 (RZN1_FUNC_MDIO_OFFSET + 21) +#define RZN1_FUNC_MDIO1_HWRTOS (RZN1_FUNC_MDIO_OFFSET + 22) +#define RZN1_FUNC_MDIO1_SWITCH (RZN1_FUNC_MDIO_OFFSET + 23) +/* These are MDIO1 peripherals for the RZN1_FUNC_ETH_MDIO_E1 function */ +#define RZN1_FUNC_MDIO1_E1_HIGHZ (RZN1_FUNC_MDIO_OFFSET + 24) +#define RZN1_FUNC_MDIO1_E1_GMAC0 (RZN1_FUNC_MDIO_OFFSET + 25) +#define RZN1_FUNC_MDIO1_E1_GMAC1 (RZN1_FUNC_MDIO_OFFSET + 26) +#define RZN1_FUNC_MDIO1_E1_ECAT (RZN1_FUNC_MDIO_OFFSET + 27) +#define RZN1_FUNC_MDIO1_E1_S3_MDIO0 (RZN1_FUNC_MDIO_OFFSET + 28) +#define RZN1_FUNC_MDIO1_E1_S3_MDIO1 (RZN1_FUNC_MDIO_OFFSET + 29) +#define RZN1_FUNC_MDIO1_E1_HWRTOS (RZN1_FUNC_MDIO_OFFSET + 30) +#define RZN1_FUNC_MDIO1_E1_SWITCH (RZN1_FUNC_MDIO_OFFSET + 31) + +#define RZN1_FUNC_MAX (RZN1_FUNC_MDIO_OFFSET + 32) + +#endif /* __DT_BINDINGS_RZN1_PINCTRL_H */