From patchwork Wed Jul 26 09:04:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?VFlfQ2hhbmdb5by15a2Q6YC4XQ==?= X-Patchwork-Id: 706752 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7948CC001DC for ; Wed, 26 Jul 2023 09:12:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231927AbjGZJMS (ORCPT ); Wed, 26 Jul 2023 05:12:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35818 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233430AbjGZJL5 (ORCPT ); Wed, 26 Jul 2023 05:11:57 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2124312C; Wed, 26 Jul 2023 02:08:10 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 36Q966Bc8008078, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36506.realtek.com.tw[172.21.6.27]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 36Q966Bc8008078 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=FAIL); Wed, 26 Jul 2023 17:06:06 +0800 Received: from RTEXMBS03.realtek.com.tw (172.21.6.96) by RTEXH36506.realtek.com.tw (172.21.6.27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.17; Wed, 26 Jul 2023 17:06:18 +0800 Received: from RTEXH36505.realtek.com.tw (172.21.6.25) by RTEXMBS03.realtek.com.tw (172.21.6.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Wed, 26 Jul 2023 17:06:18 +0800 Received: from localhost.localdomain (172.21.252.101) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server id 15.1.2375.32 via Frontend Transport; Wed, 26 Jul 2023 17:06:18 +0800 From: TY Chang To: Linus Walleij , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , Subject: [PATCH 1/7] pinctrl: realtek: Add common pinctrl driver for Realtek DHC RTD SoCs Date: Wed, 26 Jul 2023 17:04:03 +0800 Message-ID: <20230726090409.16606-2-tychang@realtek.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230726090409.16606-1-tychang@realtek.com> References: <20230726090409.16606-1-tychang@realtek.com> MIME-Version: 1.0 X-KSE-ServerInfo: RTEXMBS03.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The RTD SoCs share a similar design for pinmux and pinconfig. This common pinctrl driver supports different variants within the RTD SoCs. Signed-off-by: TY Chang --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/realtek/Kconfig | 8 + drivers/pinctrl/realtek/Makefile | 3 + drivers/pinctrl/realtek/pinctrl-rtd.c | 568 ++++++++++++++++++++++++++ drivers/pinctrl/realtek/pinctrl-rtd.h | 124 ++++++ 6 files changed, 705 insertions(+) create mode 100644 drivers/pinctrl/realtek/Kconfig create mode 100644 drivers/pinctrl/realtek/Makefile create mode 100644 drivers/pinctrl/realtek/pinctrl-rtd.c create mode 100644 drivers/pinctrl/realtek/pinctrl-rtd.h diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 57d57af1f624..9f79ce1bb621 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -531,6 +531,7 @@ source "drivers/pinctrl/nuvoton/Kconfig" source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/pxa/Kconfig" source "drivers/pinctrl/qcom/Kconfig" +source "drivers/pinctrl/realtek/Kconfig" source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/samsung/Kconfig" source "drivers/pinctrl/spear/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 482b391b5deb..beea6ac8b49e 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -67,6 +67,7 @@ obj-y += nuvoton/ obj-y += nxp/ obj-$(CONFIG_PINCTRL_PXA) += pxa/ obj-y += qcom/ +obj-$(CONFIG_ARCH_REALTEK) += realtek/ obj-$(CONFIG_PINCTRL_RENESAS) += renesas/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ diff --git a/drivers/pinctrl/realtek/Kconfig b/drivers/pinctrl/realtek/Kconfig new file mode 100644 index 000000000000..d92aad885a81 --- /dev/null +++ b/drivers/pinctrl/realtek/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config PINCTRL_RTD + tristate "Realtek DHC core pin controller driver" + depends on ARCH_REALTEK + default y + select PINMUX + select GENERIC_PINCONF diff --git a/drivers/pinctrl/realtek/Makefile b/drivers/pinctrl/realtek/Makefile new file mode 100644 index 000000000000..be2c65b26115 --- /dev/null +++ b/drivers/pinctrl/realtek/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Realtek DHC pin control drivers +obj-$(CONFIG_PINCTRL_RTD) += pinctrl-rtd.o diff --git a/drivers/pinctrl/realtek/pinctrl-rtd.c b/drivers/pinctrl/realtek/pinctrl-rtd.c new file mode 100644 index 000000000000..057495f0cd34 --- /dev/null +++ b/drivers/pinctrl/realtek/pinctrl-rtd.c @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Realtek DHC pin controller driver + * + * Copyright (c) 2023 Realtek Semiconductor Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../core.h" +#include "../pinctrl-utils.h" +#include "pinctrl-rtd.h" + +struct rtd_pinctrl { + struct device *dev; + struct pinctrl_dev *pcdev; + void __iomem *base; + struct pinctrl_desc desc; + const struct rtd_pinctrl_desc *info; +}; + +/* custom pinconf parameters */ +#define RTD_P_DRIVE (PIN_CONFIG_END + 1) +#define RTD_N_DRIVE (PIN_CONFIG_END + 2) +#define RTD_D_CYCLE (PIN_CONFIG_END + 3) + +static const struct pinconf_generic_params rtd_custom_bindings[] = { + {"realtek,pdrive", RTD_P_DRIVE, 0}, + {"realtek,ndrive", RTD_N_DRIVE, 0}, + {"realtek,dcycle", RTD_D_CYCLE, 0}, +}; + +static int rtd_pinctrl_get_groups_count(struct pinctrl_dev *pcdev) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + return data->info->num_groups; +} + +static const char *rtd_pinctrl_get_group_name(struct pinctrl_dev *pcdev, + unsigned int selector) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + return data->info->groups[selector].name; +} + +static int rtd_pinctrl_get_group_pins(struct pinctrl_dev *pcdev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + *pins = data->info->groups[selector].pins; + *num_pins = data->info->groups[selector].num_pins; + + return 0; +} + +static void rtd_pinctrl_dbg_show(struct pinctrl_dev *pcdev, + struct seq_file *s, + unsigned int offset) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + const struct rtd_pin_desc *mux = &data->info->muxes[offset]; + const struct rtd_pin_mux_desc *func; + u32 val; + u32 mask; + u32 pin_val; + int is_map; + + if (!mux->name) { + seq_puts(s, "[not defined]"); + return; + } + val = readl_relaxed(data->base + mux->mux_offset); + mask = mux->mux_mask; + pin_val = val & mask; + + is_map = 0; + func = &mux->functions[0]; + seq_puts(s, "function: "); + while (func->name) { + if (func->mux_value == pin_val) { + is_map = 1; + seq_printf(s, "[%s] ", func->name); + } else { + seq_printf(s, "%s ", func->name); + } + func++; + } + if (!is_map) + seq_puts(s, "[not defined]"); +} + +static const struct pinctrl_ops rtd_pinctrl_ops = { + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_free_map, + .get_groups_count = rtd_pinctrl_get_groups_count, + .get_group_name = rtd_pinctrl_get_group_name, + .get_group_pins = rtd_pinctrl_get_group_pins, + .pin_dbg_show = rtd_pinctrl_dbg_show, +}; + +static int rtd_pinctrl_get_functions_count(struct pinctrl_dev *pcdev) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + return data->info->num_functions; +} + +static const char *rtd_pinctrl_get_function_name(struct pinctrl_dev *pcdev, + unsigned int selector) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + return data->info->functions[selector].name; +} + +static int rtd_pinctrl_get_function_groups(struct pinctrl_dev *pcdev, + unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + + *groups = data->info->functions[selector].groups; + *num_groups = data->info->functions[selector].num_groups; + + return 0; +} + +static const struct rtd_pin_desc *rtd_pinctrl_find_mux(struct rtd_pinctrl *data, unsigned int pin) +{ + if (!data->info->muxes[pin].name) + return &data->info->muxes[pin]; + + return NULL; +} + +static void rtd_pinctrl_update_bits(struct rtd_pinctrl *data, unsigned int offset, + unsigned int mask, unsigned int val) +{ + unsigned int reg = readl_relaxed(data->base + offset); + + reg &= ~mask; + reg |= (mask & val); + writel_relaxed(reg, data->base + offset); +} + +static int rtd_pinctrl_set_one_mux(struct pinctrl_dev *pcdev, + unsigned int pin, const char *func_name) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + const struct rtd_pin_desc *mux; + int i; + + mux = rtd_pinctrl_find_mux(data, pin); + if (!mux) + return 0; + + if (!mux->functions) { + dev_err(pcdev->dev, "No functions available for pin %s\n", mux->name); + return -ENOTSUPP; + } + + for (i = 0; mux->functions[i].name; i++) { + if (strcmp(mux->functions[i].name, func_name) != 0) + continue; + rtd_pinctrl_update_bits(data, mux->mux_offset, mux->mux_mask, + mux->functions[i].mux_value); + return 0; + } + + dev_err(pcdev->dev, "No function %s available for pin %s\n", func_name, mux->name); + return -EINVAL; +} + +static int rtd_pinctrl_set_mux(struct pinctrl_dev *pcdev, + unsigned int function, unsigned int group) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + const unsigned int *pins; + unsigned int num_pins; + const char *func_name; + const char *group_name; + int i, ret; + + func_name = data->info->functions[function].name; + group_name = data->info->groups[group].name; + + ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins); + if (ret) { + dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name); + return ret; + } + + for (i = 0; i < num_pins; i++) { + ret = rtd_pinctrl_set_one_mux(pcdev, pins[i], func_name); + if (ret) + return ret; + } + + return 0; +} + +static int rtd_pinctrl_gpio_request_enable(struct pinctrl_dev *pcdev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + return rtd_pinctrl_set_one_mux(pcdev, offset, "gpio"); +} + +static const struct pinmux_ops rtd_pinmux_ops = { + .get_functions_count = rtd_pinctrl_get_functions_count, + .get_function_name = rtd_pinctrl_get_function_name, + .get_function_groups = rtd_pinctrl_get_function_groups, + .set_mux = rtd_pinctrl_set_mux, + .gpio_request_enable = rtd_pinctrl_gpio_request_enable, +}; + +static const struct pinctrl_pin_desc + *rtd_pinctrl_get_pin_by_number(struct rtd_pinctrl *data, int number) +{ + int i; + + for (i = 0; i < data->info->num_pins; i++) { + if (data->info->pins[i].number == number) + return &data->info->pins[i]; + } + + return NULL; +} + +static const struct rtd_pin_config_desc + *rtd_pinctrl_find_config(struct rtd_pinctrl *data, unsigned int pin) +{ + if (!data->info->configs[pin].name) + return &data->info->configs[pin]; + + return NULL; +} + +static const struct rtd_pin_sconfig_desc *rtd_pinctrl_find_sconfig(struct rtd_pinctrl *data, + unsigned int pin) +{ + int i; + const struct pinctrl_pin_desc *pin_desc; + const char *pin_name; + + pin_desc = rtd_pinctrl_get_pin_by_number(data, pin); + if (!pin_desc) + return NULL; + + pin_name = pin_desc->name; + + for (i = 0; i < data->info->num_sconfigs; i++) { + if (strcmp(data->info->sconfigs[i].name, pin_name) == 0) + return &data->info->sconfigs[i]; + } + + return NULL; +} + +static int rtd_pconf_parse_conf(struct rtd_pinctrl *data, + unsigned int pinnr, + enum pin_config_param param, + enum pin_config_param arg) +{ + const struct rtd_pin_config_desc *config_desc; + const struct rtd_pin_sconfig_desc *sconfig_desc; + u8 set_val = 0; + u16 strength; + u32 val; + u32 mask; + u32 pulsel_off, pulen_off, smt_off, curr_off, pow_off, reg_off, p_off, n_off; + const char *name = data->info->pins[pinnr].name; + + config_desc = rtd_pinctrl_find_config(data, pinnr); + if (!config_desc) { + dev_err(data->dev, "Not support pin config for pin: %s\n", name); + return -ENOTSUPP; + } + switch ((u32)param) { + case PIN_CONFIG_INPUT_SCHMITT: + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + if (config_desc->smt_offset == NA) { + dev_err(data->dev, "Not support input schmitt for pin: %s\n", name); + return -ENOTSUPP; + } + smt_off = config_desc->base_bit + config_desc->smt_offset; + set_val = arg; + + mask = BIT(smt_off); + val = set_val ? BIT(smt_off) : 0; + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (config_desc->pud_en_offset == NA) { + dev_err(data->dev, "Not support push pull for pin: %s\n", name); + return -ENOTSUPP; + } + pulen_off = config_desc->base_bit + config_desc->pud_en_offset; + + mask = BIT(pulen_off); + val = 0; + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_BIAS_DISABLE: + if (config_desc->pud_en_offset == NA) { + dev_err(data->dev, "Not support bias disable for pin: %s\n", name); + return -ENOTSUPP; + } + pulen_off = config_desc->base_bit + config_desc->pud_en_offset; + + mask = BIT(pulen_off); + val = 0; + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_BIAS_PULL_UP: + if (config_desc->pud_en_offset == NA) { + dev_err(data->dev, "Not support bias pull up for pin:%s\n", name); + return -ENOTSUPP; + } + pulen_off = config_desc->base_bit + config_desc->pud_en_offset; + pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset; + + mask = BIT(pulen_off) | BIT(pulsel_off); + val = mask; + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + if (config_desc->pud_en_offset == NA) { + dev_err(data->dev, "Not support bias pull down for pin: %s\n", name); + return -ENOTSUPP; + } + pulen_off = config_desc->base_bit + config_desc->pud_en_offset; + pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset; + + mask = BIT(pulen_off) | BIT(pulsel_off); + val = BIT(pulen_off); + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_DRIVE_STRENGTH: + curr_off = config_desc->base_bit + config_desc->curr_offset; + strength = arg; + val = 0; + switch (config_desc->curr_type) { + case PADDRI_4_8: + if (strength == 4) + val = 0; + else if (strength == 8) + val = BIT(curr_off); + else + return -EINVAL; + break; + case PADDRI_2_4: + if (strength == 2) + val = 0; + else if (strength == 4) + val = BIT(curr_off); + else + return -EINVAL; + break; + case NA: + dev_err(data->dev, "Not support drive strength for pin: %s\n", name); + return -ENOTSUPP; + default: + return -EINVAL; + } + mask = BIT(curr_off); + rtd_pinctrl_update_bits(data, config_desc->reg_offset, mask, val); + break; + + case PIN_CONFIG_POWER_SOURCE: + if (config_desc->power_offset == NA) { + dev_err(data->dev, "Not support power source for pin: %s\n", name); + return -ENOTSUPP; + } + reg_off = config_desc->reg_offset; + pow_off = config_desc->base_bit + config_desc->power_offset; + if (pow_off >= 32) { + reg_off += 0x4; + pow_off -= 32; + } + set_val = arg; + mask = BIT(pow_off); + val = set_val ? mask : 0; + rtd_pinctrl_update_bits(data, reg_off, mask, val); + break; + + case RTD_P_DRIVE: + sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr); + if (!sconfig_desc) { + dev_err(data->dev, "Not support P driving for pin: %s\n", name); + return -ENOTSUPP; + } + set_val = arg; + reg_off = sconfig_desc->reg_offset; + p_off = sconfig_desc->pdrive_offset; + if (p_off >= 32) { + reg_off += 0x4; + p_off -= 32; + } + mask = GENMASK(p_off + sconfig_desc->pdrive_maskbits - 1, p_off); + val = set_val << p_off; + rtd_pinctrl_update_bits(data, reg_off, mask, val); + break; + + case RTD_N_DRIVE: + sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr); + if (!sconfig_desc) { + dev_err(data->dev, "Not support N driving for pin: %s\n", name); + return -ENOTSUPP; + } + set_val = arg; + reg_off = sconfig_desc->reg_offset; + n_off = sconfig_desc->ndrive_offset; + if (n_off >= 32) { + reg_off += 0x4; + n_off -= 32; + } + mask = GENMASK(n_off + sconfig_desc->ndrive_maskbits - 1, n_off); + val = set_val << n_off; + rtd_pinctrl_update_bits(data, reg_off, mask, val); + break; + + case RTD_D_CYCLE: + sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr); + if (!sconfig_desc || sconfig_desc->dcycle_offset == NA) { + dev_err(data->dev, "Not support duty cycle for pin: %s\n", name); + return -ENOTSUPP; + } + set_val = arg; + mask = GENMASK(sconfig_desc->dcycle_offset + + sconfig_desc->dcycle_maskbits - 1, sconfig_desc->dcycle_offset); + val = set_val << sconfig_desc->dcycle_offset; + rtd_pinctrl_update_bits(data, sconfig_desc->reg_offset, mask, val); + break; + + default: + break; + } + + return 0; +} + +static int rtd_pin_config_get(struct pinctrl_dev *pcdev, unsigned int pinnr, + unsigned long *config) +{ + unsigned int param = pinconf_to_config_param(*config); + unsigned int arg = 0; + + switch (param) { + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; +} + +static int rtd_pin_config_set(struct pinctrl_dev *pcdev, unsigned int pinnr, + unsigned long *configs, unsigned int num_configs) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + int i; + int ret = 0; + + for (i = 0; i < num_configs; i++) { + ret = rtd_pconf_parse_conf(data, pinnr, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret < 0) + return ret; + } + + return 0; +} + +static int rtd_pin_config_group_set(struct pinctrl_dev *pcdev, unsigned int group, + unsigned long *configs, unsigned int num_configs) +{ + struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev); + const unsigned int *pins; + unsigned int num_pins; + const char *group_name; + int i, ret; + + group_name = data->info->groups[group].name; + + ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins); + if (ret) { + dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name); + return ret; + } + + for (i = 0; i < num_pins; i++) { + ret = rtd_pin_config_set(pcdev, pins[i], configs, num_configs); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinconf_ops rtd_pinconf_ops = { + .is_generic = true, + .pin_config_get = rtd_pin_config_get, + .pin_config_set = rtd_pin_config_set, + .pin_config_group_set = rtd_pin_config_group_set, +}; + +int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc) +{ + struct rtd_pinctrl *data; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->base = of_iomap(pdev->dev.of_node, 0); + if (IS_ERR(data->base)) + return PTR_ERR(data->base); + + data->dev = &pdev->dev; + data->info = desc; + data->desc.name = dev_name(&pdev->dev); + data->desc.pins = data->info->pins; + data->desc.npins = data->info->num_pins; + data->desc.pctlops = &rtd_pinctrl_ops; + data->desc.pmxops = &rtd_pinmux_ops; + data->desc.confops = &rtd_pinconf_ops; + data->desc.custom_params = rtd_custom_bindings; + data->desc.num_custom_params = ARRAY_SIZE(rtd_custom_bindings); + data->desc.owner = THIS_MODULE; + + data->pcdev = pinctrl_register(&data->desc, &pdev->dev, data); + if (!data->pcdev) + return -ENOMEM; + + platform_set_drvdata(pdev, data); + + dev_dbg(&pdev->dev, "probed\n"); + + return 0; +} +EXPORT_SYMBOL(rtd_pinctrl_probe); + +MODULE_DESCRIPTION("Realtek DHC SoC pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/realtek/pinctrl-rtd.h b/drivers/pinctrl/realtek/pinctrl-rtd.h new file mode 100644 index 000000000000..e15130896abc --- /dev/null +++ b/drivers/pinctrl/realtek/pinctrl-rtd.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Realtek Semiconductor Corp. + */ + +#define NA 0xffffffff +#define PADDRI_4_8 1 +#define PADDRI_2_4 0 + +struct rtd_pin_group_desc { + const char *name; + const unsigned int *pins; + unsigned int num_pins; +}; + +struct rtd_pin_func_desc { + const char *name; + const char * const *groups; + unsigned int num_groups; +}; + +struct rtd_pin_mux_desc { + const char *name; + u32 mux_value; +}; + +struct rtd_pin_config_desc { + const char *name; + unsigned int reg_offset; + unsigned int base_bit; + unsigned int pud_en_offset; + unsigned int pud_sel_offset; + unsigned int curr_offset; + unsigned int smt_offset; + unsigned int power_offset; + unsigned int curr_type; +}; + +struct rtd_pin_sconfig_desc { + const char *name; + unsigned int reg_offset; + unsigned int dcycle_offset; + unsigned int dcycle_maskbits; + unsigned int ndrive_offset; + unsigned int ndrive_maskbits; + unsigned int pdrive_offset; + unsigned int pdrive_maskbits; +}; + +struct rtd_pin_desc { + const char *name; + unsigned int mux_offset; + u32 mux_mask; + const struct rtd_pin_mux_desc *functions; +}; + +struct rtd_pin_reg_list { + unsigned int reg_offset; + unsigned int val; +}; + +#define SHIFT_LEFT(_val, _shift) ((_val) << (_shift)) + +#define RTK_PIN_MUX(_name, _mux_off, _mux_mask, ...) \ + { \ + .name = # _name, \ + .mux_offset = _mux_off, \ + .mux_mask = _mux_mask, \ + .functions = (const struct rtd_pin_mux_desc []) { \ + __VA_ARGS__, { } \ + }, \ + } + +#define RTK_PIN_CONFIG(_name, _reg_off, _base_bit, _pud_en_off, \ + _pud_sel_off, _curr_off, _smt_off, _pow_off, _curr_type) \ + { \ + .name = # _name, \ + .reg_offset = _reg_off, \ + .base_bit = _base_bit, \ + .pud_en_offset = _pud_en_off, \ + .pud_sel_offset = _pud_sel_off, \ + .curr_offset = _curr_off, \ + .smt_offset = _smt_off, \ + .power_offset = _pow_off, \ + .curr_type = _curr_type, \ + } + +#define RTK_PIN_SCONFIG(_name, _reg_off, _d_offset, _d_mask, \ + _n_offset, _n_mask, _p_offset, _p_mask) \ + { \ + .name = # _name, \ + .reg_offset = _reg_off, \ + .dcycle_offset = _d_offset, \ + .dcycle_maskbits = _d_mask, \ + .ndrive_offset = _n_offset, \ + .ndrive_maskbits = _n_mask, \ + .pdrive_offset = _p_offset, \ + .pdrive_maskbits = _p_mask, \ + } + +#define RTK_PIN_FUNC(_mux_val, _name) \ + { \ + .name = _name, \ + .mux_value = _mux_val, \ + } + +struct rtd_pinctrl_desc { + const struct pinctrl_pin_desc *pins; + unsigned int num_pins; + const struct rtd_pin_group_desc *groups; + unsigned int num_groups; + const struct rtd_pin_func_desc *functions; + unsigned int num_functions; + const struct rtd_pin_desc *muxes; + unsigned int num_muxes; + const struct rtd_pin_config_desc *configs; + unsigned int num_configs; + const struct rtd_pin_sconfig_desc *sconfigs; + unsigned int num_sconfigs; + struct rtd_pin_reg_list *lists; + unsigned int num_regs; +}; + +int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc); From patchwork Wed Jul 26 09:04:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?VFlfQ2hhbmdb5by15a2Q6YC4XQ==?= X-Patchwork-Id: 706750 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8058C001E0 for ; Wed, 26 Jul 2023 09:13:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229550AbjGZJNt (ORCPT ); Wed, 26 Jul 2023 05:13:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231165AbjGZJMk (ORCPT ); Wed, 26 Jul 2023 05:12:40 -0400 Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 437283583; Wed, 26 Jul 2023 02:09:02 -0700 (PDT) Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.77 with qID 36Q967prC008096, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36505.realtek.com.tw[172.21.6.25]) by rtits2.realtek.com.tw (8.15.2/2.81/5.90) with ESMTPS id 36Q967prC008096 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=FAIL); Wed, 26 Jul 2023 17:06:07 +0800 Received: from RTEXMBS03.realtek.com.tw (172.21.6.96) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.32; Wed, 26 Jul 2023 17:06:19 +0800 Received: from RTEXH36505.realtek.com.tw (172.21.6.25) by RTEXMBS03.realtek.com.tw (172.21.6.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.7; Wed, 26 Jul 2023 17:06:18 +0800 Received: from localhost.localdomain (172.21.252.101) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server id 15.1.2375.32 via Frontend Transport; Wed, 26 Jul 2023 17:06:18 +0800 From: TY Chang To: Linus Walleij , Rob Herring , Krzysztof Kozlowski , Conor Dooley CC: , , Subject: [PATCH 7/7] dt-bindings: pinctrl: realtek: add RTD1619B pinctrl binding Date: Wed, 26 Jul 2023 17:04:09 +0800 Message-ID: <20230726090409.16606-8-tychang@realtek.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230726090409.16606-1-tychang@realtek.com> References: <20230726090409.16606-1-tychang@realtek.com> MIME-Version: 1.0 X-KSE-ServerInfo: RTEXMBS03.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-ServerInfo: RTEXH36505.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add device tree bindings for RTD1619B. Signed-off-by: TY Chang --- .../pinctrl/realtek,rtd1619b-pinctrl.yaml | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml new file mode 100644 index 000000000000..8efd33c59ed8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/realtek,rtd1619b-pinctrl.yaml @@ -0,0 +1,162 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2023 Realtek Semiconductor Corporation +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/realtek,rtd1619b-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Realtek DHC RTD1619B Pin Controller + +maintainers: + - TY Chang + +description: | + Binding for Realtek DHC RTD1619B SoC pin control. + +properties: + compatible: + const: realtek,rtd1619b-pinctrl + + reg: + maxItems: 1 + +patternProperties: + '^.*$': + if: + type: object + then: + allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + + properties: + pins: + items: + enum: [ gpio_0, gpio_1, gpio_2, gpio_3, gpio_4, gpio_5, gpio_6, gpio_7, + gpio_8, gpio_9, gpio_10, gpio_11, gpio_12, gpio_13, gpio_14, + gpio_15, gpio_16, gpio_17, gpio_18, gpio_19, gpio_20, gpio_21, + gpio_22, gpio_23, usb_cc2, gpio_25, gpio_26, gpio_27, gpio_28, + gpio_29, gpio_30, gpio_31, gpio_32, gpio_33, gpio_34, gpio_35, + hif_data, hif_en, hif_rdy, hif_clk, gpio_40, gpio_41, gpio_42, + gpio_43, gpio_44, gpio_45, gpio_46, gpio_47, gpio_48, gpio_49, + gpio_50, usb_cc1, gpio_52, gpio_53, ir_rx, ur0_rx, ur0_tx, + gpio_57, gpio_58, gpio_59, gpio_60, gpio_61, gpio_62, gpio_63, + gpio_64, gpio_65, gpio_66, gpio_67, gpio_68, gpio_69, gpio_70, + gpio_71, gpio_72, gpio_73, gpio_74, gpio_75, gpio_76, emmc_cmd, + spi_ce_n, spi_sck, spi_so, spi_si, emmc_rst_n, emmc_dd_sb, + emmc_clk, emmc_data_0, emmc_data_1, emmc_data_2, emmc_data_3, + emmc_data_4, emmc_data_5, emmc_data_6, emmc_data_7, ur2_loc, + gspi_loc, sdio_loc, hi_loc, hi_width, sf_en, arm_trace_dbg_en, + pwm_01_open_drain_en_loc0, pwm_23_open_drain_en_loc0, + pwm_01_open_drain_en_loc1, pwm_23_open_drain_en_loc1, + ejtag_acpu_loc, ejtag_vcpu_loc, ejtag_scpu_loc, dmic_loc, + iso_gspi_loc, ejtag_ve3_loc, ejtag_aucpu0_loc, ejtag_aucpu1_loc ] + + function: + enum: [ gpio, nf, nf_spi, spi, pmic, spdif, spdif_coaxial, spdif_optical_loc0, + spdif_optical_loc1, emmc_spi, emmc, sc1, uart0, uart1, uart2_loc0, uart2_loc1, + gspi_loc1, iso_gspi_loc1, i2c0, i2c1, i2c3, i2c4, i2c5, pwm0, pwm1, pwm2, + pwm3, etn_led, etn_phy, etn_clk, sc0, vfd, gspi_loc0, iso_gspi_loc0, pcie1, + pcie2, sd, sdio_loc0, sdio_loc1, hi, hi_m, dc_fan, pll_test_loc0, pll_test_loc1, + usb_cc1, usb_cc2, ir_rx, tdm_ai_loc0, tdm_ai_loc1, dmic_loc0, dmic_loc1, + ai_loc0, ai_loc1, tp0, tp1, ao, uart2_disable, gspi_disable, sdio_disable, + hi_loc_disable, hi_loc0, hi_width_disable, hi_width_1bit, vtc_i2si_loc0, + vtc_tdm_loc0, vtc_dmic_loc0, vtc_i2si_loc1, vtc_tdm_loc1, vtc_dmic_loc1, + vtc_i2so, ve3_ejtag_loc0, aucpu0_ejtag_loc0, aucpu1_ejtag_loc0, ve3_ejtag_loc1, + aucpu0_ejtag_loc1, aucpu1_ejtag_loc1, ve3_ejtag_loc2, aucpu0_ejtag_loc2, + aucpu1_ejtag_loc2, scpu_ejtag_loc0, acpu_ejtag_loc0, vcpu_ejtag_loc0, + scpu_ejtag_loc1, acpu_ejtag_loc1, vcpu_ejtag_loc1, scpu_ejtag_loc2, + acpu_ejtag_loc2, vcpu_ejtag_loc2, ve3_ejtag_disable, aucpu0_ejtag_disable, + aucpu1_ejtag_disable, acpu_ejtag_disable, vcpu_ejtag_disable, + scpu_ejtag_disable, iso_gspi_disable, sf_disable, sf_enable, + arm_trace_debug_disable, arm_trace_debug_enable, pwm_normal, pwm_open_drain, + standby_dbg, test_loop_dis ] + + drive-strength: + enum: [4, 8] + + bias-pull-down: true + + bias-pull-up: true + + bias-disable: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + drive-push-pull: true + + power-source: + description: | + Valid arguments are described as below: + 0: power supply of 1.8V + 1: power supply of 3.3V + enum: [0, 1] + + realtek,pdrive: + description: | + An integer describing the level to adjust PMOS output driving capability. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + + realtek,ndrive: + description: | + An integer describing the level to adjust NMOS output driving capability. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + + realtek,dcycle: + description: | + An integer describing the level to adjust output duty cycle. + Valid arguments are described as below: + 0: 0ns + 2: + 0.25ns + 3: + 0.5ns + 4: -0.25ns + 5: -0.5ns + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 0, 2, 3, 4, 5 ] + + required: + - pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pinctrl@4e000 { + compatible = "realtek,rtd16xxb-pinctrl"; + reg = <0x4e000 0x130>; + + emmc_pins_hs200: emmc_pins_hs200 { + pins = "emmc_clk", + "emmc_cmd", + "emmc_data_0", + "emmc_data_1", + "emmc_data_2", + "emmc_data_3", + "emmc_data_4", + "emmc_data_5", + "emmc_data_6", + "emmc_data_7"; + function = "emmc"; + realtek,pdrive = <0x2>; + realtek,ndrive = <0x2>; + }; + + i2c_pins_0: i2c_pins_0 { + pins = "gpio_12", + "gpio_13"; + function = "i2c0"; + drive-strength = <4>; + }; + };