18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MediaTek Pinctrl Moore Driver, which implement the generic dt-binding 48c2ecf20Sopenharmony_ci * pinctrl-bindings.txt for MediaTek SoC. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2017-2018 MediaTek Inc. 78c2ecf20Sopenharmony_ci * Author: Sean Wang <sean.wang@mediatek.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 128c2ecf20Sopenharmony_ci#include "pinctrl-moore.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* Custom pinconf parameters */ 178c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1) 188c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2) 198c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3) 208c2ecf20Sopenharmony_ci#define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic const struct pinconf_generic_params mtk_custom_bindings[] = { 238c2ecf20Sopenharmony_ci {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0}, 248c2ecf20Sopenharmony_ci {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0}, 258c2ecf20Sopenharmony_ci {"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1}, 268c2ecf20Sopenharmony_ci {"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1}, 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 308c2ecf20Sopenharmony_cistatic const struct pin_config_item mtk_conf_items[] = { 318c2ecf20Sopenharmony_ci PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true), 328c2ecf20Sopenharmony_ci PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true), 338c2ecf20Sopenharmony_ci PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true), 348c2ecf20Sopenharmony_ci PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true), 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci#endif 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev, 398c2ecf20Sopenharmony_ci unsigned int selector, unsigned int group) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 428c2ecf20Sopenharmony_ci struct function_desc *func; 438c2ecf20Sopenharmony_ci struct group_desc *grp; 448c2ecf20Sopenharmony_ci int i; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci func = pinmux_generic_get_function(pctldev, selector); 478c2ecf20Sopenharmony_ci if (!func) 488c2ecf20Sopenharmony_ci return -EINVAL; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci grp = pinctrl_generic_get_group(pctldev, group); 518c2ecf20Sopenharmony_ci if (!grp) 528c2ecf20Sopenharmony_ci return -EINVAL; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci dev_dbg(pctldev->dev, "enable function %s group %s\n", 558c2ecf20Sopenharmony_ci func->name, grp->name); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci for (i = 0; i < grp->num_pins; i++) { 588c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 598c2ecf20Sopenharmony_ci int *pin_modes = grp->data; 608c2ecf20Sopenharmony_ci int pin = grp->pins[i]; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, 658c2ecf20Sopenharmony_ci pin_modes[i]); 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return 0; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, 728c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 738c2ecf20Sopenharmony_ci unsigned int pin) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 768c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, 818c2ecf20Sopenharmony_ci hw->soc->gpio_m); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, 858c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 868c2ecf20Sopenharmony_ci unsigned int pin, bool input) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 898c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* hardware would take 0 as input direction */ 948c2ecf20Sopenharmony_ci return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic int mtk_pinconf_get(struct pinctrl_dev *pctldev, 988c2ecf20Sopenharmony_ci unsigned int pin, unsigned long *config) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 1018c2ecf20Sopenharmony_ci u32 param = pinconf_to_config_param(*config); 1028c2ecf20Sopenharmony_ci int val, val2, err, reg, ret = 1; 1038c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci switch (param) { 1088c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 1098c2ecf20Sopenharmony_ci if (hw->soc->bias_disable_get) { 1108c2ecf20Sopenharmony_ci err = hw->soc->bias_disable_get(hw, desc, &ret); 1118c2ecf20Sopenharmony_ci if (err) 1128c2ecf20Sopenharmony_ci return err; 1138c2ecf20Sopenharmony_ci } else { 1148c2ecf20Sopenharmony_ci return -ENOTSUPP; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 1188c2ecf20Sopenharmony_ci if (hw->soc->bias_get) { 1198c2ecf20Sopenharmony_ci err = hw->soc->bias_get(hw, desc, 1, &ret); 1208c2ecf20Sopenharmony_ci if (err) 1218c2ecf20Sopenharmony_ci return err; 1228c2ecf20Sopenharmony_ci } else { 1238c2ecf20Sopenharmony_ci return -ENOTSUPP; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 1278c2ecf20Sopenharmony_ci if (hw->soc->bias_get) { 1288c2ecf20Sopenharmony_ci err = hw->soc->bias_get(hw, desc, 0, &ret); 1298c2ecf20Sopenharmony_ci if (err) 1308c2ecf20Sopenharmony_ci return err; 1318c2ecf20Sopenharmony_ci } else { 1328c2ecf20Sopenharmony_ci return -ENOTSUPP; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case PIN_CONFIG_SLEW_RATE: 1368c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); 1378c2ecf20Sopenharmony_ci if (err) 1388c2ecf20Sopenharmony_ci return err; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (!val) 1418c2ecf20Sopenharmony_ci return -EINVAL; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci break; 1448c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 1458c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT_ENABLE: 1468c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); 1478c2ecf20Sopenharmony_ci if (err) 1488c2ecf20Sopenharmony_ci return err; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* HW takes input mode as zero; output mode as non-zero */ 1518c2ecf20Sopenharmony_ci if ((val && param == PIN_CONFIG_INPUT_ENABLE) || 1528c2ecf20Sopenharmony_ci (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) 1538c2ecf20Sopenharmony_ci return -EINVAL; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 1578c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); 1588c2ecf20Sopenharmony_ci if (err) 1598c2ecf20Sopenharmony_ci return err; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2); 1628c2ecf20Sopenharmony_ci if (err) 1638c2ecf20Sopenharmony_ci return err; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (val || !val2) 1668c2ecf20Sopenharmony_ci return -EINVAL; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 1708c2ecf20Sopenharmony_ci if (hw->soc->drive_get) { 1718c2ecf20Sopenharmony_ci err = hw->soc->drive_get(hw, desc, &ret); 1728c2ecf20Sopenharmony_ci if (err) 1738c2ecf20Sopenharmony_ci return err; 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci err = -ENOTSUPP; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_TDSEL: 1798c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_RDSEL: 1808c2ecf20Sopenharmony_ci reg = (param == MTK_PIN_CONFIG_TDSEL) ? 1818c2ecf20Sopenharmony_ci PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, reg, &val); 1848c2ecf20Sopenharmony_ci if (err) 1858c2ecf20Sopenharmony_ci return err; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci ret = val; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci break; 1908c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_PU_ADV: 1918c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_PD_ADV: 1928c2ecf20Sopenharmony_ci if (hw->soc->adv_pull_get) { 1938c2ecf20Sopenharmony_ci bool pullup; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci pullup = param == MTK_PIN_CONFIG_PU_ADV; 1968c2ecf20Sopenharmony_ci err = hw->soc->adv_pull_get(hw, desc, pullup, &ret); 1978c2ecf20Sopenharmony_ci if (err) 1988c2ecf20Sopenharmony_ci return err; 1998c2ecf20Sopenharmony_ci } else { 2008c2ecf20Sopenharmony_ci return -ENOTSUPP; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci break; 2038c2ecf20Sopenharmony_ci default: 2048c2ecf20Sopenharmony_ci return -ENOTSUPP; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci *config = pinconf_to_config_packed(param, ret); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return 0; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 2138c2ecf20Sopenharmony_ci unsigned long *configs, unsigned int num_configs) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 2168c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 2178c2ecf20Sopenharmony_ci u32 reg, param, arg; 2188c2ecf20Sopenharmony_ci int cfg, err = 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci for (cfg = 0; cfg < num_configs; cfg++) { 2238c2ecf20Sopenharmony_ci param = pinconf_to_config_param(configs[cfg]); 2248c2ecf20Sopenharmony_ci arg = pinconf_to_config_argument(configs[cfg]); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci switch (param) { 2278c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 2288c2ecf20Sopenharmony_ci if (hw->soc->bias_disable_set) { 2298c2ecf20Sopenharmony_ci err = hw->soc->bias_disable_set(hw, desc); 2308c2ecf20Sopenharmony_ci if (err) 2318c2ecf20Sopenharmony_ci return err; 2328c2ecf20Sopenharmony_ci } else { 2338c2ecf20Sopenharmony_ci return -ENOTSUPP; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 2378c2ecf20Sopenharmony_ci if (hw->soc->bias_set) { 2388c2ecf20Sopenharmony_ci err = hw->soc->bias_set(hw, desc, 1); 2398c2ecf20Sopenharmony_ci if (err) 2408c2ecf20Sopenharmony_ci return err; 2418c2ecf20Sopenharmony_ci } else { 2428c2ecf20Sopenharmony_ci return -ENOTSUPP; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 2468c2ecf20Sopenharmony_ci if (hw->soc->bias_set) { 2478c2ecf20Sopenharmony_ci err = hw->soc->bias_set(hw, desc, 0); 2488c2ecf20Sopenharmony_ci if (err) 2498c2ecf20Sopenharmony_ci return err; 2508c2ecf20Sopenharmony_ci } else { 2518c2ecf20Sopenharmony_ci return -ENOTSUPP; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci break; 2548c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT_ENABLE: 2558c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, 2568c2ecf20Sopenharmony_ci MTK_DISABLE); 2578c2ecf20Sopenharmony_ci if (err) 2588c2ecf20Sopenharmony_ci goto err; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 2618c2ecf20Sopenharmony_ci MTK_OUTPUT); 2628c2ecf20Sopenharmony_ci if (err) 2638c2ecf20Sopenharmony_ci goto err; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (hw->soc->ies_present) { 2688c2ecf20Sopenharmony_ci mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, 2698c2ecf20Sopenharmony_ci MTK_ENABLE); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 2738c2ecf20Sopenharmony_ci MTK_INPUT); 2748c2ecf20Sopenharmony_ci if (err) 2758c2ecf20Sopenharmony_ci goto err; 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci case PIN_CONFIG_SLEW_RATE: 2788c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, 2798c2ecf20Sopenharmony_ci arg); 2808c2ecf20Sopenharmony_ci if (err) 2818c2ecf20Sopenharmony_ci goto err; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT: 2858c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 2868c2ecf20Sopenharmony_ci MTK_OUTPUT); 2878c2ecf20Sopenharmony_ci if (err) 2888c2ecf20Sopenharmony_ci goto err; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, 2918c2ecf20Sopenharmony_ci arg); 2928c2ecf20Sopenharmony_ci if (err) 2938c2ecf20Sopenharmony_ci goto err; 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 2968c2ecf20Sopenharmony_ci /* arg = 1: Input mode & SMT enable ; 2978c2ecf20Sopenharmony_ci * arg = 0: Output mode & SMT disable 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci arg = arg ? 2 : 1; 3008c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 3018c2ecf20Sopenharmony_ci arg & 1); 3028c2ecf20Sopenharmony_ci if (err) 3038c2ecf20Sopenharmony_ci goto err; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, 3068c2ecf20Sopenharmony_ci !!(arg & 2)); 3078c2ecf20Sopenharmony_ci if (err) 3088c2ecf20Sopenharmony_ci goto err; 3098c2ecf20Sopenharmony_ci break; 3108c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 3118c2ecf20Sopenharmony_ci if (hw->soc->drive_set) { 3128c2ecf20Sopenharmony_ci err = hw->soc->drive_set(hw, desc, arg); 3138c2ecf20Sopenharmony_ci if (err) 3148c2ecf20Sopenharmony_ci return err; 3158c2ecf20Sopenharmony_ci } else { 3168c2ecf20Sopenharmony_ci err = -ENOTSUPP; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci break; 3198c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_TDSEL: 3208c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_RDSEL: 3218c2ecf20Sopenharmony_ci reg = (param == MTK_PIN_CONFIG_TDSEL) ? 3228c2ecf20Sopenharmony_ci PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci err = mtk_hw_set_value(hw, desc, reg, arg); 3258c2ecf20Sopenharmony_ci if (err) 3268c2ecf20Sopenharmony_ci goto err; 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_PU_ADV: 3298c2ecf20Sopenharmony_ci case MTK_PIN_CONFIG_PD_ADV: 3308c2ecf20Sopenharmony_ci if (hw->soc->adv_pull_set) { 3318c2ecf20Sopenharmony_ci bool pullup; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci pullup = param == MTK_PIN_CONFIG_PU_ADV; 3348c2ecf20Sopenharmony_ci err = hw->soc->adv_pull_set(hw, desc, pullup, 3358c2ecf20Sopenharmony_ci arg); 3368c2ecf20Sopenharmony_ci if (err) 3378c2ecf20Sopenharmony_ci return err; 3388c2ecf20Sopenharmony_ci } else { 3398c2ecf20Sopenharmony_ci return -ENOTSUPP; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci break; 3428c2ecf20Sopenharmony_ci default: 3438c2ecf20Sopenharmony_ci err = -ENOTSUPP; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_cierr: 3478c2ecf20Sopenharmony_ci return err; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int mtk_pinconf_group_get(struct pinctrl_dev *pctldev, 3518c2ecf20Sopenharmony_ci unsigned int group, unsigned long *config) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci const unsigned int *pins; 3548c2ecf20Sopenharmony_ci unsigned int i, npins, old = 0; 3558c2ecf20Sopenharmony_ci int ret; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 3588c2ecf20Sopenharmony_ci if (ret) 3598c2ecf20Sopenharmony_ci return ret; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci for (i = 0; i < npins; i++) { 3628c2ecf20Sopenharmony_ci if (mtk_pinconf_get(pctldev, pins[i], config)) 3638c2ecf20Sopenharmony_ci return -ENOTSUPP; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* configs do not match between two pins */ 3668c2ecf20Sopenharmony_ci if (i && old != *config) 3678c2ecf20Sopenharmony_ci return -ENOTSUPP; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci old = *config; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci return 0; 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic int mtk_pinconf_group_set(struct pinctrl_dev *pctldev, 3768c2ecf20Sopenharmony_ci unsigned int group, unsigned long *configs, 3778c2ecf20Sopenharmony_ci unsigned int num_configs) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci const unsigned int *pins; 3808c2ecf20Sopenharmony_ci unsigned int i, npins; 3818c2ecf20Sopenharmony_ci int ret; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 3848c2ecf20Sopenharmony_ci if (ret) 3858c2ecf20Sopenharmony_ci return ret; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci for (i = 0; i < npins; i++) { 3888c2ecf20Sopenharmony_ci ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs); 3898c2ecf20Sopenharmony_ci if (ret) 3908c2ecf20Sopenharmony_ci return ret; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci return 0; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic const struct pinctrl_ops mtk_pctlops = { 3978c2ecf20Sopenharmony_ci .get_groups_count = pinctrl_generic_get_group_count, 3988c2ecf20Sopenharmony_ci .get_group_name = pinctrl_generic_get_group_name, 3998c2ecf20Sopenharmony_ci .get_group_pins = pinctrl_generic_get_group_pins, 4008c2ecf20Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 4018c2ecf20Sopenharmony_ci .dt_free_map = pinconf_generic_dt_free_map, 4028c2ecf20Sopenharmony_ci}; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic const struct pinmux_ops mtk_pmxops = { 4058c2ecf20Sopenharmony_ci .get_functions_count = pinmux_generic_get_function_count, 4068c2ecf20Sopenharmony_ci .get_function_name = pinmux_generic_get_function_name, 4078c2ecf20Sopenharmony_ci .get_function_groups = pinmux_generic_get_function_groups, 4088c2ecf20Sopenharmony_ci .set_mux = mtk_pinmux_set_mux, 4098c2ecf20Sopenharmony_ci .gpio_request_enable = mtk_pinmux_gpio_request_enable, 4108c2ecf20Sopenharmony_ci .gpio_set_direction = mtk_pinmux_gpio_set_direction, 4118c2ecf20Sopenharmony_ci .strict = true, 4128c2ecf20Sopenharmony_ci}; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic const struct pinconf_ops mtk_confops = { 4158c2ecf20Sopenharmony_ci .is_generic = true, 4168c2ecf20Sopenharmony_ci .pin_config_get = mtk_pinconf_get, 4178c2ecf20Sopenharmony_ci .pin_config_set = mtk_pinconf_set, 4188c2ecf20Sopenharmony_ci .pin_config_group_get = mtk_pinconf_group_get, 4198c2ecf20Sopenharmony_ci .pin_config_group_set = mtk_pinconf_group_set, 4208c2ecf20Sopenharmony_ci .pin_config_config_dbg_show = pinconf_generic_dump_config, 4218c2ecf20Sopenharmony_ci}; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic struct pinctrl_desc mtk_desc = { 4248c2ecf20Sopenharmony_ci .name = PINCTRL_PINCTRL_DEV, 4258c2ecf20Sopenharmony_ci .pctlops = &mtk_pctlops, 4268c2ecf20Sopenharmony_ci .pmxops = &mtk_pmxops, 4278c2ecf20Sopenharmony_ci .confops = &mtk_confops, 4288c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4298c2ecf20Sopenharmony_ci}; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistatic int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = gpiochip_get_data(chip); 4348c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 4358c2ecf20Sopenharmony_ci int value, err; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); 4408c2ecf20Sopenharmony_ci if (err) 4418c2ecf20Sopenharmony_ci return err; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci return !!value; 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = gpiochip_get_data(chip); 4498c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_input(chip->base + gpio); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, 4628c2ecf20Sopenharmony_ci int value) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci mtk_gpio_set(chip, gpio, value); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_output(chip->base + gpio); 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = gpiochip_get_data(chip); 4728c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (!hw->eint) 4758c2ecf20Sopenharmony_ci return -ENOTSUPP; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (desc->eint.eint_n == (u16)EINT_NA) 4808c2ecf20Sopenharmony_ci return -ENOTSUPP; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci return mtk_eint_find_irq(hw->eint, desc->eint.eint_n); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset, 4868c2ecf20Sopenharmony_ci unsigned long config) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw = gpiochip_get_data(chip); 4898c2ecf20Sopenharmony_ci const struct mtk_pin_desc *desc; 4908c2ecf20Sopenharmony_ci u32 debounce; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci if (!hw->eint || 4958c2ecf20Sopenharmony_ci pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE || 4968c2ecf20Sopenharmony_ci desc->eint.eint_n == (u16)EINT_NA) 4978c2ecf20Sopenharmony_ci return -ENOTSUPP; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci debounce = pinconf_to_config_argument(config); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci struct gpio_chip *chip = &hw->chip; 5078c2ecf20Sopenharmony_ci int ret; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci chip->label = PINCTRL_PINCTRL_DEV; 5108c2ecf20Sopenharmony_ci chip->parent = hw->dev; 5118c2ecf20Sopenharmony_ci chip->request = gpiochip_generic_request; 5128c2ecf20Sopenharmony_ci chip->free = gpiochip_generic_free; 5138c2ecf20Sopenharmony_ci chip->direction_input = mtk_gpio_direction_input; 5148c2ecf20Sopenharmony_ci chip->direction_output = mtk_gpio_direction_output; 5158c2ecf20Sopenharmony_ci chip->get = mtk_gpio_get; 5168c2ecf20Sopenharmony_ci chip->set = mtk_gpio_set; 5178c2ecf20Sopenharmony_ci chip->to_irq = mtk_gpio_to_irq, 5188c2ecf20Sopenharmony_ci chip->set_config = mtk_gpio_set_config, 5198c2ecf20Sopenharmony_ci chip->base = -1; 5208c2ecf20Sopenharmony_ci chip->ngpio = hw->soc->npins; 5218c2ecf20Sopenharmony_ci chip->of_node = np; 5228c2ecf20Sopenharmony_ci chip->of_gpio_n_cells = 2; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci ret = gpiochip_add_data(chip, hw); 5258c2ecf20Sopenharmony_ci if (ret < 0) 5268c2ecf20Sopenharmony_ci return ret; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci /* Just for backward compatible for these old pinctrl nodes without 5298c2ecf20Sopenharmony_ci * "gpio-ranges" property. Otherwise, called directly from a 5308c2ecf20Sopenharmony_ci * DeviceTree-supported pinctrl driver is DEPRECATED. 5318c2ecf20Sopenharmony_ci * Please see Section 2.1 of 5328c2ecf20Sopenharmony_ci * Documentation/devicetree/bindings/gpio/gpio.txt on how to 5338c2ecf20Sopenharmony_ci * bind pinctrl and gpio drivers via the "gpio-ranges" property. 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_ci if (!of_find_property(np, "gpio-ranges", NULL)) { 5368c2ecf20Sopenharmony_ci ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0, 5378c2ecf20Sopenharmony_ci chip->ngpio); 5388c2ecf20Sopenharmony_ci if (ret < 0) { 5398c2ecf20Sopenharmony_ci gpiochip_remove(chip); 5408c2ecf20Sopenharmony_ci return ret; 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci } 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci return 0; 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic int mtk_build_groups(struct mtk_pinctrl *hw) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci int err, i; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci for (i = 0; i < hw->soc->ngrps; i++) { 5528c2ecf20Sopenharmony_ci const struct group_desc *group = hw->soc->grps + i; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci err = pinctrl_generic_add_group(hw->pctrl, group->name, 5558c2ecf20Sopenharmony_ci group->pins, group->num_pins, 5568c2ecf20Sopenharmony_ci group->data); 5578c2ecf20Sopenharmony_ci if (err < 0) { 5588c2ecf20Sopenharmony_ci dev_err(hw->dev, "Failed to register group %s\n", 5598c2ecf20Sopenharmony_ci group->name); 5608c2ecf20Sopenharmony_ci return err; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci } 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci return 0; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic int mtk_build_functions(struct mtk_pinctrl *hw) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci int i, err; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci for (i = 0; i < hw->soc->nfuncs ; i++) { 5728c2ecf20Sopenharmony_ci const struct function_desc *func = hw->soc->funcs + i; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci err = pinmux_generic_add_function(hw->pctrl, func->name, 5758c2ecf20Sopenharmony_ci func->group_names, 5768c2ecf20Sopenharmony_ci func->num_group_names, 5778c2ecf20Sopenharmony_ci func->data); 5788c2ecf20Sopenharmony_ci if (err < 0) { 5798c2ecf20Sopenharmony_ci dev_err(hw->dev, "Failed to register function %s\n", 5808c2ecf20Sopenharmony_ci func->name); 5818c2ecf20Sopenharmony_ci return err; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci return 0; 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ciint mtk_moore_pinctrl_probe(struct platform_device *pdev, 5898c2ecf20Sopenharmony_ci const struct mtk_pin_soc *soc) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci struct pinctrl_pin_desc *pins; 5928c2ecf20Sopenharmony_ci struct mtk_pinctrl *hw; 5938c2ecf20Sopenharmony_ci int err, i; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); 5968c2ecf20Sopenharmony_ci if (!hw) 5978c2ecf20Sopenharmony_ci return -ENOMEM; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci hw->soc = soc; 6008c2ecf20Sopenharmony_ci hw->dev = &pdev->dev; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (!hw->soc->nbase_names) { 6038c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 6048c2ecf20Sopenharmony_ci "SoC should be assigned at least one register base\n"); 6058c2ecf20Sopenharmony_ci return -EINVAL; 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names, 6098c2ecf20Sopenharmony_ci sizeof(*hw->base), GFP_KERNEL); 6108c2ecf20Sopenharmony_ci if (!hw->base) 6118c2ecf20Sopenharmony_ci return -ENOMEM; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci for (i = 0; i < hw->soc->nbase_names; i++) { 6148c2ecf20Sopenharmony_ci hw->base[i] = devm_platform_ioremap_resource_byname(pdev, 6158c2ecf20Sopenharmony_ci hw->soc->base_names[i]); 6168c2ecf20Sopenharmony_ci if (IS_ERR(hw->base[i])) 6178c2ecf20Sopenharmony_ci return PTR_ERR(hw->base[i]); 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci hw->nbase = hw->soc->nbase_names; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Copy from internal struct mtk_pin_desc to register to the core */ 6238c2ecf20Sopenharmony_ci pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins), 6248c2ecf20Sopenharmony_ci GFP_KERNEL); 6258c2ecf20Sopenharmony_ci if (!pins) 6268c2ecf20Sopenharmony_ci return -ENOMEM; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci for (i = 0; i < hw->soc->npins; i++) { 6298c2ecf20Sopenharmony_ci pins[i].number = hw->soc->pins[i].number; 6308c2ecf20Sopenharmony_ci pins[i].name = hw->soc->pins[i].name; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci /* Setup pins descriptions per SoC types */ 6348c2ecf20Sopenharmony_ci mtk_desc.pins = (const struct pinctrl_pin_desc *)pins; 6358c2ecf20Sopenharmony_ci mtk_desc.npins = hw->soc->npins; 6368c2ecf20Sopenharmony_ci mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings); 6378c2ecf20Sopenharmony_ci mtk_desc.custom_params = mtk_custom_bindings; 6388c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 6398c2ecf20Sopenharmony_ci mtk_desc.custom_conf_items = mtk_conf_items; 6408c2ecf20Sopenharmony_ci#endif 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw, 6438c2ecf20Sopenharmony_ci &hw->pctrl); 6448c2ecf20Sopenharmony_ci if (err) 6458c2ecf20Sopenharmony_ci return err; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* Setup groups descriptions per SoC types */ 6488c2ecf20Sopenharmony_ci err = mtk_build_groups(hw); 6498c2ecf20Sopenharmony_ci if (err) { 6508c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to build groups\n"); 6518c2ecf20Sopenharmony_ci return err; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* Setup functions descriptions per SoC types */ 6558c2ecf20Sopenharmony_ci err = mtk_build_functions(hw); 6568c2ecf20Sopenharmony_ci if (err) { 6578c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to build functions\n"); 6588c2ecf20Sopenharmony_ci return err; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /* For able to make pinctrl_claim_hogs, we must not enable pinctrl 6628c2ecf20Sopenharmony_ci * until all groups and functions are being added one. 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_ci err = pinctrl_enable(hw->pctrl); 6658c2ecf20Sopenharmony_ci if (err) 6668c2ecf20Sopenharmony_ci return err; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci err = mtk_build_eint(hw, pdev); 6698c2ecf20Sopenharmony_ci if (err) 6708c2ecf20Sopenharmony_ci dev_warn(&pdev->dev, 6718c2ecf20Sopenharmony_ci "Failed to add EINT, but pinctrl still can work\n"); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci /* Build gpiochip should be after pinctrl_enable is done */ 6748c2ecf20Sopenharmony_ci err = mtk_build_gpiochip(hw, pdev->dev.of_node); 6758c2ecf20Sopenharmony_ci if (err) { 6768c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to add gpio_chip\n"); 6778c2ecf20Sopenharmony_ci return err; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, hw); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci return 0; 6838c2ecf20Sopenharmony_ci} 684