1e78d57b2SSean Wang // SPDX-License-Identifier: GPL-2.0 2e78d57b2SSean Wang /* 3e78d57b2SSean Wang * MediaTek Pinctrl Moore Driver, which implement the generic dt-binding 4e78d57b2SSean Wang * pinctrl-bindings.txt for MediaTek SoC. 5e78d57b2SSean Wang * 6e78d57b2SSean Wang * Copyright (C) 2017-2018 MediaTek Inc. 7e78d57b2SSean Wang * Author: Sean Wang <sean.wang@mediatek.com> 8e78d57b2SSean Wang * 9e78d57b2SSean Wang */ 10e78d57b2SSean Wang 11e78d57b2SSean Wang #include "pinctrl-moore.h" 12e78d57b2SSean Wang 13e78d57b2SSean Wang #define PINCTRL_PINCTRL_DEV KBUILD_MODNAME 14e78d57b2SSean Wang 15e78d57b2SSean Wang /* Custom pinconf parameters */ 16e78d57b2SSean Wang #define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1) 17e78d57b2SSean Wang #define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2) 180d7ca772SSean Wang #define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3) 190d7ca772SSean Wang #define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4) 20e78d57b2SSean Wang 21e78d57b2SSean Wang static const struct pinconf_generic_params mtk_custom_bindings[] = { 22e78d57b2SSean Wang {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0}, 23e78d57b2SSean Wang {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0}, 240d7ca772SSean Wang {"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1}, 250d7ca772SSean Wang {"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1}, 26e78d57b2SSean Wang }; 27e78d57b2SSean Wang 28e78d57b2SSean Wang #ifdef CONFIG_DEBUG_FS 29e78d57b2SSean Wang static const struct pin_config_item mtk_conf_items[] = { 30e78d57b2SSean Wang PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true), 31e78d57b2SSean Wang PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true), 320d7ca772SSean Wang PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true), 330d7ca772SSean Wang PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true), 34e78d57b2SSean Wang }; 35e78d57b2SSean Wang #endif 36e78d57b2SSean Wang 37e78d57b2SSean Wang static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev, 38e78d57b2SSean Wang unsigned int selector, unsigned int group) 39e78d57b2SSean Wang { 40e78d57b2SSean Wang struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 41e78d57b2SSean Wang struct function_desc *func; 42e78d57b2SSean Wang struct group_desc *grp; 43e78d57b2SSean Wang int i; 44e78d57b2SSean Wang 45e78d57b2SSean Wang func = pinmux_generic_get_function(pctldev, selector); 46e78d57b2SSean Wang if (!func) 47e78d57b2SSean Wang return -EINVAL; 48e78d57b2SSean Wang 49e78d57b2SSean Wang grp = pinctrl_generic_get_group(pctldev, group); 50e78d57b2SSean Wang if (!grp) 51e78d57b2SSean Wang return -EINVAL; 52e78d57b2SSean Wang 53e78d57b2SSean Wang dev_dbg(pctldev->dev, "enable function %s group %s\n", 54e78d57b2SSean Wang func->name, grp->name); 55e78d57b2SSean Wang 56e78d57b2SSean Wang for (i = 0; i < grp->num_pins; i++) { 57ea051eb3SSean Wang const struct mtk_pin_desc *desc; 58e78d57b2SSean Wang int *pin_modes = grp->data; 59ea051eb3SSean Wang int pin = grp->pins[i]; 60e78d57b2SSean Wang 61ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 62ea051eb3SSean Wang 63ea051eb3SSean Wang mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, 64e78d57b2SSean Wang pin_modes[i]); 65e78d57b2SSean Wang } 66e78d57b2SSean Wang 67e78d57b2SSean Wang return 0; 68e78d57b2SSean Wang } 69e78d57b2SSean Wang 70e78d57b2SSean Wang static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, 71e78d57b2SSean Wang struct pinctrl_gpio_range *range, 72e78d57b2SSean Wang unsigned int pin) 73e78d57b2SSean Wang { 74e78d57b2SSean Wang struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 75ea051eb3SSean Wang const struct mtk_pin_desc *desc; 76e78d57b2SSean Wang 77ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 78ea051eb3SSean Wang 79ea051eb3SSean Wang return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, 80ea051eb3SSean Wang hw->soc->gpio_m); 81e78d57b2SSean Wang } 82e78d57b2SSean Wang 83e78d57b2SSean Wang static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, 84e78d57b2SSean Wang struct pinctrl_gpio_range *range, 85e78d57b2SSean Wang unsigned int pin, bool input) 86e78d57b2SSean Wang { 87e78d57b2SSean Wang struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 88ea051eb3SSean Wang const struct mtk_pin_desc *desc; 89ea051eb3SSean Wang 90ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 91e78d57b2SSean Wang 92e78d57b2SSean Wang /* hardware would take 0 as input direction */ 93ea051eb3SSean Wang return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input); 94e78d57b2SSean Wang } 95e78d57b2SSean Wang 96e78d57b2SSean Wang static int mtk_pinconf_get(struct pinctrl_dev *pctldev, 97e78d57b2SSean Wang unsigned int pin, unsigned long *config) 98e78d57b2SSean Wang { 99e78d57b2SSean Wang struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 100e78d57b2SSean Wang u32 param = pinconf_to_config_param(*config); 101e78d57b2SSean Wang int val, val2, err, reg, ret = 1; 102c2832197SSean Wang const struct mtk_pin_desc *desc; 103c2832197SSean Wang 104c2832197SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 105e78d57b2SSean Wang 106e78d57b2SSean Wang switch (param) { 107e78d57b2SSean Wang case PIN_CONFIG_BIAS_DISABLE: 10885430152SSean Wang if (hw->soc->bias_disable_get) { 10985430152SSean Wang err = hw->soc->bias_disable_get(hw, desc, &ret); 110e78d57b2SSean Wang if (err) 111e78d57b2SSean Wang return err; 11285430152SSean Wang } else { 11385430152SSean Wang return -ENOTSUPP; 11485430152SSean Wang } 115e78d57b2SSean Wang break; 116e78d57b2SSean Wang case PIN_CONFIG_BIAS_PULL_UP: 11785430152SSean Wang if (hw->soc->bias_get) { 11885430152SSean Wang err = hw->soc->bias_get(hw, desc, 1, &ret); 11985430152SSean Wang if (err) 12085430152SSean Wang return err; 12185430152SSean Wang } else { 12285430152SSean Wang return -ENOTSUPP; 12385430152SSean Wang } 12485430152SSean Wang break; 125e78d57b2SSean Wang case PIN_CONFIG_BIAS_PULL_DOWN: 12685430152SSean Wang if (hw->soc->bias_get) { 12785430152SSean Wang err = hw->soc->bias_get(hw, desc, 0, &ret); 12885430152SSean Wang if (err) 12985430152SSean Wang return err; 13085430152SSean Wang } else { 13185430152SSean Wang return -ENOTSUPP; 13285430152SSean Wang } 13385430152SSean Wang break; 134e78d57b2SSean Wang case PIN_CONFIG_SLEW_RATE: 135ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); 136e78d57b2SSean Wang if (err) 137e78d57b2SSean Wang return err; 138e78d57b2SSean Wang 139e78d57b2SSean Wang if (!val) 140e78d57b2SSean Wang return -EINVAL; 141e78d57b2SSean Wang 142e78d57b2SSean Wang break; 143e78d57b2SSean Wang case PIN_CONFIG_INPUT_ENABLE: 144e78d57b2SSean Wang case PIN_CONFIG_OUTPUT_ENABLE: 145ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); 146e78d57b2SSean Wang if (err) 147e78d57b2SSean Wang return err; 148e78d57b2SSean Wang 149e78d57b2SSean Wang /* HW takes input mode as zero; output mode as non-zero */ 150e78d57b2SSean Wang if ((val && param == PIN_CONFIG_INPUT_ENABLE) || 151e78d57b2SSean Wang (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) 152e78d57b2SSean Wang return -EINVAL; 153e78d57b2SSean Wang 154e78d57b2SSean Wang break; 155e78d57b2SSean Wang case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 156ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); 157e78d57b2SSean Wang if (err) 158e78d57b2SSean Wang return err; 159e78d57b2SSean Wang 160ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2); 161e78d57b2SSean Wang if (err) 162e78d57b2SSean Wang return err; 163e78d57b2SSean Wang 164e78d57b2SSean Wang if (val || !val2) 165e78d57b2SSean Wang return -EINVAL; 166e78d57b2SSean Wang 167e78d57b2SSean Wang break; 168e78d57b2SSean Wang case PIN_CONFIG_DRIVE_STRENGTH: 169c2832197SSean Wang if (hw->soc->drive_get) { 170c2832197SSean Wang err = hw->soc->drive_get(hw, desc, &ret); 171e78d57b2SSean Wang if (err) 172e78d57b2SSean Wang return err; 173c2832197SSean Wang } else { 174c2832197SSean Wang err = -ENOTSUPP; 175c2832197SSean Wang } 176e78d57b2SSean Wang break; 177e78d57b2SSean Wang case MTK_PIN_CONFIG_TDSEL: 178e78d57b2SSean Wang case MTK_PIN_CONFIG_RDSEL: 179e78d57b2SSean Wang reg = (param == MTK_PIN_CONFIG_TDSEL) ? 180e78d57b2SSean Wang PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; 181e78d57b2SSean Wang 182ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, reg, &val); 183e78d57b2SSean Wang if (err) 184e78d57b2SSean Wang return err; 185e78d57b2SSean Wang 186e78d57b2SSean Wang ret = val; 187e78d57b2SSean Wang 188e78d57b2SSean Wang break; 1890d7ca772SSean Wang case MTK_PIN_CONFIG_PU_ADV: 1900d7ca772SSean Wang case MTK_PIN_CONFIG_PD_ADV: 1910d7ca772SSean Wang if (hw->soc->adv_pull_get) { 1920d7ca772SSean Wang bool pullup; 1930d7ca772SSean Wang 1940d7ca772SSean Wang pullup = param == MTK_PIN_CONFIG_PU_ADV; 1950d7ca772SSean Wang err = hw->soc->adv_pull_get(hw, desc, pullup, &ret); 1960d7ca772SSean Wang if (err) 1970d7ca772SSean Wang return err; 1980d7ca772SSean Wang } else { 1990d7ca772SSean Wang return -ENOTSUPP; 2000d7ca772SSean Wang } 2010d7ca772SSean Wang break; 202e78d57b2SSean Wang default: 203e78d57b2SSean Wang return -ENOTSUPP; 204e78d57b2SSean Wang } 205e78d57b2SSean Wang 206e78d57b2SSean Wang *config = pinconf_to_config_packed(param, ret); 207e78d57b2SSean Wang 208e78d57b2SSean Wang return 0; 209e78d57b2SSean Wang } 210e78d57b2SSean Wang 211e78d57b2SSean Wang static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 212e78d57b2SSean Wang unsigned long *configs, unsigned int num_configs) 213e78d57b2SSean Wang { 214e78d57b2SSean Wang struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); 215c2832197SSean Wang const struct mtk_pin_desc *desc; 216e78d57b2SSean Wang u32 reg, param, arg; 217e78d57b2SSean Wang int cfg, err = 0; 218e78d57b2SSean Wang 219c2832197SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; 220c2832197SSean Wang 221e78d57b2SSean Wang for (cfg = 0; cfg < num_configs; cfg++) { 222e78d57b2SSean Wang param = pinconf_to_config_param(configs[cfg]); 223e78d57b2SSean Wang arg = pinconf_to_config_argument(configs[cfg]); 224e78d57b2SSean Wang 225e78d57b2SSean Wang switch (param) { 226e78d57b2SSean Wang case PIN_CONFIG_BIAS_DISABLE: 22785430152SSean Wang if (hw->soc->bias_disable_set) { 22885430152SSean Wang err = hw->soc->bias_disable_set(hw, desc); 22985430152SSean Wang if (err) 23085430152SSean Wang return err; 23185430152SSean Wang } else { 23285430152SSean Wang return -ENOTSUPP; 23385430152SSean Wang } 23485430152SSean Wang break; 235e78d57b2SSean Wang case PIN_CONFIG_BIAS_PULL_UP: 23685430152SSean Wang if (hw->soc->bias_set) { 23785430152SSean Wang err = hw->soc->bias_set(hw, desc, 1); 23885430152SSean Wang if (err) 23985430152SSean Wang return err; 24085430152SSean Wang } else { 24185430152SSean Wang return -ENOTSUPP; 24285430152SSean Wang } 24385430152SSean Wang break; 244e78d57b2SSean Wang case PIN_CONFIG_BIAS_PULL_DOWN: 24585430152SSean Wang if (hw->soc->bias_set) { 24685430152SSean Wang err = hw->soc->bias_set(hw, desc, 0); 247e78d57b2SSean Wang if (err) 24885430152SSean Wang return err; 24985430152SSean Wang } else { 25085430152SSean Wang return -ENOTSUPP; 25185430152SSean Wang } 252e78d57b2SSean Wang break; 253e78d57b2SSean Wang case PIN_CONFIG_OUTPUT_ENABLE: 254ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, 255e78d57b2SSean Wang MTK_DISABLE); 256e78d57b2SSean Wang if (err) 257e78d57b2SSean Wang goto err; 258e78d57b2SSean Wang 259ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 260182c842fSSean Wang MTK_OUTPUT); 261182c842fSSean Wang if (err) 262182c842fSSean Wang goto err; 263182c842fSSean Wang break; 264182c842fSSean Wang case PIN_CONFIG_INPUT_ENABLE: 265182c842fSSean Wang 266182c842fSSean Wang if (hw->soc->ies_present) { 267ea051eb3SSean Wang mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, 268182c842fSSean Wang MTK_ENABLE); 269182c842fSSean Wang } 270182c842fSSean Wang 271ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 272182c842fSSean Wang MTK_INPUT); 273182c842fSSean Wang if (err) 274182c842fSSean Wang goto err; 275182c842fSSean Wang break; 276182c842fSSean Wang case PIN_CONFIG_SLEW_RATE: 277ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, 278182c842fSSean Wang arg); 279e78d57b2SSean Wang if (err) 280e78d57b2SSean Wang goto err; 281e78d57b2SSean Wang 282e78d57b2SSean Wang break; 283e78d57b2SSean Wang case PIN_CONFIG_OUTPUT: 284ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 285e78d57b2SSean Wang MTK_OUTPUT); 286e78d57b2SSean Wang if (err) 287e78d57b2SSean Wang goto err; 288e78d57b2SSean Wang 289ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, 290e78d57b2SSean Wang arg); 291e78d57b2SSean Wang if (err) 292e78d57b2SSean Wang goto err; 293e78d57b2SSean Wang break; 294e78d57b2SSean Wang case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 295e78d57b2SSean Wang /* arg = 1: Input mode & SMT enable ; 296e78d57b2SSean Wang * arg = 0: Output mode & SMT disable 297e78d57b2SSean Wang */ 298e78d57b2SSean Wang arg = arg ? 2 : 1; 299ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, 300e78d57b2SSean Wang arg & 1); 301e78d57b2SSean Wang if (err) 302e78d57b2SSean Wang goto err; 303e78d57b2SSean Wang 304ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, 305e78d57b2SSean Wang !!(arg & 2)); 306e78d57b2SSean Wang if (err) 307e78d57b2SSean Wang goto err; 308e78d57b2SSean Wang break; 309e78d57b2SSean Wang case PIN_CONFIG_DRIVE_STRENGTH: 310c2832197SSean Wang if (hw->soc->drive_set) { 311c2832197SSean Wang err = hw->soc->drive_set(hw, desc, arg); 312e78d57b2SSean Wang if (err) 313c2832197SSean Wang return err; 314e78d57b2SSean Wang } else { 315e78d57b2SSean Wang err = -ENOTSUPP; 316e78d57b2SSean Wang } 317e78d57b2SSean Wang break; 318e78d57b2SSean Wang case MTK_PIN_CONFIG_TDSEL: 319e78d57b2SSean Wang case MTK_PIN_CONFIG_RDSEL: 320e78d57b2SSean Wang reg = (param == MTK_PIN_CONFIG_TDSEL) ? 321e78d57b2SSean Wang PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; 322e78d57b2SSean Wang 323ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, reg, arg); 324e78d57b2SSean Wang if (err) 325e78d57b2SSean Wang goto err; 326e78d57b2SSean Wang break; 3270d7ca772SSean Wang case MTK_PIN_CONFIG_PU_ADV: 3280d7ca772SSean Wang case MTK_PIN_CONFIG_PD_ADV: 3290d7ca772SSean Wang if (hw->soc->adv_pull_set) { 3300d7ca772SSean Wang bool pullup; 3310d7ca772SSean Wang 3320d7ca772SSean Wang pullup = param == MTK_PIN_CONFIG_PU_ADV; 3330d7ca772SSean Wang err = hw->soc->adv_pull_set(hw, desc, pullup, 3340d7ca772SSean Wang arg); 3350d7ca772SSean Wang if (err) 3360d7ca772SSean Wang return err; 3370d7ca772SSean Wang } else { 3380d7ca772SSean Wang return -ENOTSUPP; 3390d7ca772SSean Wang } 3400d7ca772SSean Wang break; 341e78d57b2SSean Wang default: 342e78d57b2SSean Wang err = -ENOTSUPP; 343e78d57b2SSean Wang } 344e78d57b2SSean Wang } 345e78d57b2SSean Wang err: 346e78d57b2SSean Wang return err; 347e78d57b2SSean Wang } 348e78d57b2SSean Wang 349e78d57b2SSean Wang static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev, 350e78d57b2SSean Wang unsigned int group, unsigned long *config) 351e78d57b2SSean Wang { 352e78d57b2SSean Wang const unsigned int *pins; 353e78d57b2SSean Wang unsigned int i, npins, old = 0; 354e78d57b2SSean Wang int ret; 355e78d57b2SSean Wang 356e78d57b2SSean Wang ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 357e78d57b2SSean Wang if (ret) 358e78d57b2SSean Wang return ret; 359e78d57b2SSean Wang 360e78d57b2SSean Wang for (i = 0; i < npins; i++) { 361e78d57b2SSean Wang if (mtk_pinconf_get(pctldev, pins[i], config)) 362e78d57b2SSean Wang return -ENOTSUPP; 363e78d57b2SSean Wang 364e78d57b2SSean Wang /* configs do not match between two pins */ 365e78d57b2SSean Wang if (i && old != *config) 366e78d57b2SSean Wang return -ENOTSUPP; 367e78d57b2SSean Wang 368e78d57b2SSean Wang old = *config; 369e78d57b2SSean Wang } 370e78d57b2SSean Wang 371e78d57b2SSean Wang return 0; 372e78d57b2SSean Wang } 373e78d57b2SSean Wang 374e78d57b2SSean Wang static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev, 375e78d57b2SSean Wang unsigned int group, unsigned long *configs, 376e78d57b2SSean Wang unsigned int num_configs) 377e78d57b2SSean Wang { 378e78d57b2SSean Wang const unsigned int *pins; 379e78d57b2SSean Wang unsigned int i, npins; 380e78d57b2SSean Wang int ret; 381e78d57b2SSean Wang 382e78d57b2SSean Wang ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); 383e78d57b2SSean Wang if (ret) 384e78d57b2SSean Wang return ret; 385e78d57b2SSean Wang 386e78d57b2SSean Wang for (i = 0; i < npins; i++) { 387e78d57b2SSean Wang ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs); 388e78d57b2SSean Wang if (ret) 389e78d57b2SSean Wang return ret; 390e78d57b2SSean Wang } 391e78d57b2SSean Wang 392e78d57b2SSean Wang return 0; 393e78d57b2SSean Wang } 394e78d57b2SSean Wang 395e78d57b2SSean Wang static const struct pinctrl_ops mtk_pctlops = { 396e78d57b2SSean Wang .get_groups_count = pinctrl_generic_get_group_count, 397e78d57b2SSean Wang .get_group_name = pinctrl_generic_get_group_name, 398e78d57b2SSean Wang .get_group_pins = pinctrl_generic_get_group_pins, 399e78d57b2SSean Wang .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 400e78d57b2SSean Wang .dt_free_map = pinconf_generic_dt_free_map, 401e78d57b2SSean Wang }; 402e78d57b2SSean Wang 403e78d57b2SSean Wang static const struct pinmux_ops mtk_pmxops = { 404e78d57b2SSean Wang .get_functions_count = pinmux_generic_get_function_count, 405e78d57b2SSean Wang .get_function_name = pinmux_generic_get_function_name, 406e78d57b2SSean Wang .get_function_groups = pinmux_generic_get_function_groups, 407e78d57b2SSean Wang .set_mux = mtk_pinmux_set_mux, 408e78d57b2SSean Wang .gpio_request_enable = mtk_pinmux_gpio_request_enable, 409e78d57b2SSean Wang .gpio_set_direction = mtk_pinmux_gpio_set_direction, 410e78d57b2SSean Wang .strict = true, 411e78d57b2SSean Wang }; 412e78d57b2SSean Wang 413e78d57b2SSean Wang static const struct pinconf_ops mtk_confops = { 414e78d57b2SSean Wang .is_generic = true, 415e78d57b2SSean Wang .pin_config_get = mtk_pinconf_get, 416e78d57b2SSean Wang .pin_config_set = mtk_pinconf_set, 417e78d57b2SSean Wang .pin_config_group_get = mtk_pinconf_group_get, 418e78d57b2SSean Wang .pin_config_group_set = mtk_pinconf_group_set, 419e78d57b2SSean Wang .pin_config_config_dbg_show = pinconf_generic_dump_config, 420e78d57b2SSean Wang }; 421e78d57b2SSean Wang 422e78d57b2SSean Wang static struct pinctrl_desc mtk_desc = { 423e78d57b2SSean Wang .name = PINCTRL_PINCTRL_DEV, 424e78d57b2SSean Wang .pctlops = &mtk_pctlops, 425e78d57b2SSean Wang .pmxops = &mtk_pmxops, 426e78d57b2SSean Wang .confops = &mtk_confops, 427e78d57b2SSean Wang .owner = THIS_MODULE, 428e78d57b2SSean Wang }; 429e78d57b2SSean Wang 430e78d57b2SSean Wang static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) 431e78d57b2SSean Wang { 432e78d57b2SSean Wang struct mtk_pinctrl *hw = gpiochip_get_data(chip); 433ea051eb3SSean Wang const struct mtk_pin_desc *desc; 434e78d57b2SSean Wang int value, err; 435e78d57b2SSean Wang 436ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; 437ea051eb3SSean Wang 438ea051eb3SSean Wang err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); 439e78d57b2SSean Wang if (err) 440e78d57b2SSean Wang return err; 441e78d57b2SSean Wang 442e78d57b2SSean Wang return !!value; 443e78d57b2SSean Wang } 444e78d57b2SSean Wang 445e78d57b2SSean Wang static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) 446e78d57b2SSean Wang { 447e78d57b2SSean Wang struct mtk_pinctrl *hw = gpiochip_get_data(chip); 448ea051eb3SSean Wang const struct mtk_pin_desc *desc; 449e78d57b2SSean Wang 450ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; 451ea051eb3SSean Wang 452ea051eb3SSean Wang mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); 453e78d57b2SSean Wang } 454e78d57b2SSean Wang 455e78d57b2SSean Wang static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) 456e78d57b2SSean Wang { 457e78d57b2SSean Wang return pinctrl_gpio_direction_input(chip->base + gpio); 458e78d57b2SSean Wang } 459e78d57b2SSean Wang 460e78d57b2SSean Wang static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, 461e78d57b2SSean Wang int value) 462e78d57b2SSean Wang { 463e78d57b2SSean Wang mtk_gpio_set(chip, gpio, value); 464e78d57b2SSean Wang 465e78d57b2SSean Wang return pinctrl_gpio_direction_output(chip->base + gpio); 466e78d57b2SSean Wang } 467e78d57b2SSean Wang 468e78d57b2SSean Wang static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) 469e78d57b2SSean Wang { 470e78d57b2SSean Wang struct mtk_pinctrl *hw = gpiochip_get_data(chip); 471fb5fa8dcSSean Wang const struct mtk_pin_desc *desc; 472e78d57b2SSean Wang 473e78d57b2SSean Wang if (!hw->eint) 474e78d57b2SSean Wang return -ENOTSUPP; 475e78d57b2SSean Wang 476fb5fa8dcSSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; 477e78d57b2SSean Wang 478fb5fa8dcSSean Wang if (desc->eint_n == EINT_NA) 479fb5fa8dcSSean Wang return -ENOTSUPP; 480fb5fa8dcSSean Wang 481fb5fa8dcSSean Wang return mtk_eint_find_irq(hw->eint, desc->eint_n); 482e78d57b2SSean Wang } 483e78d57b2SSean Wang 484e78d57b2SSean Wang static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset, 485e78d57b2SSean Wang unsigned long config) 486e78d57b2SSean Wang { 487e78d57b2SSean Wang struct mtk_pinctrl *hw = gpiochip_get_data(chip); 488fb5fa8dcSSean Wang const struct mtk_pin_desc *desc; 489e78d57b2SSean Wang u32 debounce; 490e78d57b2SSean Wang 491fb5fa8dcSSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; 492fb5fa8dcSSean Wang 493e78d57b2SSean Wang if (!hw->eint || 494fb5fa8dcSSean Wang pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE || 495fb5fa8dcSSean Wang desc->eint_n == EINT_NA) 496e78d57b2SSean Wang return -ENOTSUPP; 497e78d57b2SSean Wang 498e78d57b2SSean Wang debounce = pinconf_to_config_argument(config); 499e78d57b2SSean Wang 500fb5fa8dcSSean Wang return mtk_eint_set_debounce(hw->eint, desc->eint_n, debounce); 501e78d57b2SSean Wang } 502e78d57b2SSean Wang 503e78d57b2SSean Wang static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np) 504e78d57b2SSean Wang { 505e78d57b2SSean Wang struct gpio_chip *chip = &hw->chip; 506e78d57b2SSean Wang int ret; 507e78d57b2SSean Wang 508e78d57b2SSean Wang chip->label = PINCTRL_PINCTRL_DEV; 509e78d57b2SSean Wang chip->parent = hw->dev; 510e78d57b2SSean Wang chip->request = gpiochip_generic_request; 511e78d57b2SSean Wang chip->free = gpiochip_generic_free; 512e78d57b2SSean Wang chip->direction_input = mtk_gpio_direction_input; 513e78d57b2SSean Wang chip->direction_output = mtk_gpio_direction_output; 514e78d57b2SSean Wang chip->get = mtk_gpio_get; 515e78d57b2SSean Wang chip->set = mtk_gpio_set; 516e78d57b2SSean Wang chip->to_irq = mtk_gpio_to_irq, 517e78d57b2SSean Wang chip->set_config = mtk_gpio_set_config, 518e78d57b2SSean Wang chip->base = -1; 519e78d57b2SSean Wang chip->ngpio = hw->soc->npins; 520e78d57b2SSean Wang chip->of_node = np; 521e78d57b2SSean Wang chip->of_gpio_n_cells = 2; 522e78d57b2SSean Wang 523e78d57b2SSean Wang ret = gpiochip_add_data(chip, hw); 524e78d57b2SSean Wang if (ret < 0) 525e78d57b2SSean Wang return ret; 526e78d57b2SSean Wang 527e78d57b2SSean Wang /* Just for backward compatible for these old pinctrl nodes without 528e78d57b2SSean Wang * "gpio-ranges" property. Otherwise, called directly from a 529e78d57b2SSean Wang * DeviceTree-supported pinctrl driver is DEPRECATED. 530e78d57b2SSean Wang * Please see Section 2.1 of 531e78d57b2SSean Wang * Documentation/devicetree/bindings/gpio/gpio.txt on how to 532e78d57b2SSean Wang * bind pinctrl and gpio drivers via the "gpio-ranges" property. 533e78d57b2SSean Wang */ 534e78d57b2SSean Wang if (!of_find_property(np, "gpio-ranges", NULL)) { 535e78d57b2SSean Wang ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0, 536e78d57b2SSean Wang chip->ngpio); 537e78d57b2SSean Wang if (ret < 0) { 538e78d57b2SSean Wang gpiochip_remove(chip); 539e78d57b2SSean Wang return ret; 540e78d57b2SSean Wang } 541e78d57b2SSean Wang } 542e78d57b2SSean Wang 543e78d57b2SSean Wang return 0; 544e78d57b2SSean Wang } 545e78d57b2SSean Wang 546e78d57b2SSean Wang static int mtk_build_groups(struct mtk_pinctrl *hw) 547e78d57b2SSean Wang { 548e78d57b2SSean Wang int err, i; 549e78d57b2SSean Wang 550e78d57b2SSean Wang for (i = 0; i < hw->soc->ngrps; i++) { 551e78d57b2SSean Wang const struct group_desc *group = hw->soc->grps + i; 552e78d57b2SSean Wang 553e78d57b2SSean Wang err = pinctrl_generic_add_group(hw->pctrl, group->name, 554e78d57b2SSean Wang group->pins, group->num_pins, 555e78d57b2SSean Wang group->data); 556e78d57b2SSean Wang if (err < 0) { 557e78d57b2SSean Wang dev_err(hw->dev, "Failed to register group %s\n", 558e78d57b2SSean Wang group->name); 559e78d57b2SSean Wang return err; 560e78d57b2SSean Wang } 561e78d57b2SSean Wang } 562e78d57b2SSean Wang 563e78d57b2SSean Wang return 0; 564e78d57b2SSean Wang } 565e78d57b2SSean Wang 566e78d57b2SSean Wang static int mtk_build_functions(struct mtk_pinctrl *hw) 567e78d57b2SSean Wang { 568e78d57b2SSean Wang int i, err; 569e78d57b2SSean Wang 570e78d57b2SSean Wang for (i = 0; i < hw->soc->nfuncs ; i++) { 571e78d57b2SSean Wang const struct function_desc *func = hw->soc->funcs + i; 572e78d57b2SSean Wang 573e78d57b2SSean Wang err = pinmux_generic_add_function(hw->pctrl, func->name, 574e78d57b2SSean Wang func->group_names, 575e78d57b2SSean Wang func->num_group_names, 576e78d57b2SSean Wang func->data); 577e78d57b2SSean Wang if (err < 0) { 578e78d57b2SSean Wang dev_err(hw->dev, "Failed to register function %s\n", 579e78d57b2SSean Wang func->name); 580e78d57b2SSean Wang return err; 581e78d57b2SSean Wang } 582e78d57b2SSean Wang } 583e78d57b2SSean Wang 584e78d57b2SSean Wang return 0; 585e78d57b2SSean Wang } 586e78d57b2SSean Wang 587fb5fa8dcSSean Wang static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, 588fb5fa8dcSSean Wang unsigned long eint_n) 589fb5fa8dcSSean Wang { 590fb5fa8dcSSean Wang const struct mtk_pin_desc *desc; 591fb5fa8dcSSean Wang int i = 0; 592fb5fa8dcSSean Wang 593fb5fa8dcSSean Wang desc = (const struct mtk_pin_desc *)hw->soc->pins; 594fb5fa8dcSSean Wang 595fb5fa8dcSSean Wang while (i < hw->soc->npins) { 596fb5fa8dcSSean Wang if (desc[i].eint_n == eint_n) 597fb5fa8dcSSean Wang return desc[i].number; 598fb5fa8dcSSean Wang i++; 599fb5fa8dcSSean Wang } 600fb5fa8dcSSean Wang 601fb5fa8dcSSean Wang return EINT_NA; 602fb5fa8dcSSean Wang } 603fb5fa8dcSSean Wang 604e78d57b2SSean Wang static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n, 605e78d57b2SSean Wang unsigned int *gpio_n, 606e78d57b2SSean Wang struct gpio_chip **gpio_chip) 607e78d57b2SSean Wang { 608e78d57b2SSean Wang struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; 609fb5fa8dcSSean Wang const struct mtk_pin_desc *desc; 610e78d57b2SSean Wang 611fb5fa8dcSSean Wang desc = (const struct mtk_pin_desc *)hw->soc->pins; 612e78d57b2SSean Wang *gpio_chip = &hw->chip; 613e78d57b2SSean Wang 614fb5fa8dcSSean Wang /* Be greedy to guess first gpio_n is equal to eint_n */ 615fb5fa8dcSSean Wang if (desc[eint_n].eint_n == eint_n) 616fb5fa8dcSSean Wang *gpio_n = eint_n; 617fb5fa8dcSSean Wang else 618fb5fa8dcSSean Wang *gpio_n = mtk_xt_find_eint_num(hw, eint_n); 619fb5fa8dcSSean Wang 620fb5fa8dcSSean Wang return *gpio_n == EINT_NA ? -EINVAL : 0; 621e78d57b2SSean Wang } 622e78d57b2SSean Wang 623e78d57b2SSean Wang static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n) 624e78d57b2SSean Wang { 625e78d57b2SSean Wang struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; 626e78d57b2SSean Wang struct gpio_chip *gpio_chip; 627e78d57b2SSean Wang unsigned int gpio_n; 628e78d57b2SSean Wang int err; 629e78d57b2SSean Wang 630e78d57b2SSean Wang err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); 631e78d57b2SSean Wang if (err) 632e78d57b2SSean Wang return err; 633e78d57b2SSean Wang 634e78d57b2SSean Wang return mtk_gpio_get(gpio_chip, gpio_n); 635e78d57b2SSean Wang } 636e78d57b2SSean Wang 637e78d57b2SSean Wang static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n) 638e78d57b2SSean Wang { 639e78d57b2SSean Wang struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data; 640ea051eb3SSean Wang const struct mtk_pin_desc *desc; 641e78d57b2SSean Wang struct gpio_chip *gpio_chip; 642e78d57b2SSean Wang unsigned int gpio_n; 643e78d57b2SSean Wang int err; 644e78d57b2SSean Wang 645e78d57b2SSean Wang err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip); 646e78d57b2SSean Wang if (err) 647e78d57b2SSean Wang return err; 648e78d57b2SSean Wang 649ea051eb3SSean Wang desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n]; 650ea051eb3SSean Wang 651ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, 6521dc5e536SSean Wang hw->soc->eint_m); 653e78d57b2SSean Wang if (err) 654e78d57b2SSean Wang return err; 655e78d57b2SSean Wang 656ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT); 657e78d57b2SSean Wang if (err) 658e78d57b2SSean Wang return err; 659e78d57b2SSean Wang 660ea051eb3SSean Wang err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE); 661e78d57b2SSean Wang if (err) 662e78d57b2SSean Wang return err; 663e78d57b2SSean Wang 664e78d57b2SSean Wang return 0; 665e78d57b2SSean Wang } 666e78d57b2SSean Wang 667e78d57b2SSean Wang static const struct mtk_eint_xt mtk_eint_xt = { 668e78d57b2SSean Wang .get_gpio_n = mtk_xt_get_gpio_n, 669e78d57b2SSean Wang .get_gpio_state = mtk_xt_get_gpio_state, 670e78d57b2SSean Wang .set_gpio_as_eint = mtk_xt_set_gpio_as_eint, 671e78d57b2SSean Wang }; 672e78d57b2SSean Wang 673e78d57b2SSean Wang static int 674e78d57b2SSean Wang mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev) 675e78d57b2SSean Wang { 676e78d57b2SSean Wang struct device_node *np = pdev->dev.of_node; 677e78d57b2SSean Wang struct resource *res; 678e78d57b2SSean Wang 679e78d57b2SSean Wang if (!IS_ENABLED(CONFIG_EINT_MTK)) 680e78d57b2SSean Wang return 0; 681e78d57b2SSean Wang 682e78d57b2SSean Wang if (!of_property_read_bool(np, "interrupt-controller")) 683e78d57b2SSean Wang return -ENODEV; 684e78d57b2SSean Wang 685e78d57b2SSean Wang hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL); 686e78d57b2SSean Wang if (!hw->eint) 687e78d57b2SSean Wang return -ENOMEM; 688e78d57b2SSean Wang 689e78d57b2SSean Wang res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint"); 690e78d57b2SSean Wang if (!res) { 691e78d57b2SSean Wang dev_err(&pdev->dev, "Unable to get eint resource\n"); 692e78d57b2SSean Wang return -ENODEV; 693e78d57b2SSean Wang } 694e78d57b2SSean Wang 695e78d57b2SSean Wang hw->eint->base = devm_ioremap_resource(&pdev->dev, res); 696e78d57b2SSean Wang if (IS_ERR(hw->eint->base)) 697e78d57b2SSean Wang return PTR_ERR(hw->eint->base); 698e78d57b2SSean Wang 699e78d57b2SSean Wang hw->eint->irq = irq_of_parse_and_map(np, 0); 700e78d57b2SSean Wang if (!hw->eint->irq) 701e78d57b2SSean Wang return -EINVAL; 702e78d57b2SSean Wang 703e78d57b2SSean Wang hw->eint->dev = &pdev->dev; 704e78d57b2SSean Wang hw->eint->hw = hw->soc->eint_hw; 705e78d57b2SSean Wang hw->eint->pctl = hw; 706e78d57b2SSean Wang hw->eint->gpio_xlate = &mtk_eint_xt; 707e78d57b2SSean Wang 708e78d57b2SSean Wang return mtk_eint_do_init(hw->eint); 709e78d57b2SSean Wang } 710e78d57b2SSean Wang 711e78d57b2SSean Wang int mtk_moore_pinctrl_probe(struct platform_device *pdev, 712e78d57b2SSean Wang const struct mtk_pin_soc *soc) 713e78d57b2SSean Wang { 714e78d57b2SSean Wang struct resource *res; 715e78d57b2SSean Wang struct mtk_pinctrl *hw; 716*2bc47dfeSSean Wang int err, i; 717e78d57b2SSean Wang 718e78d57b2SSean Wang hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); 719e78d57b2SSean Wang if (!hw) 720e78d57b2SSean Wang return -ENOMEM; 721e78d57b2SSean Wang 722e78d57b2SSean Wang hw->soc = soc; 723*2bc47dfeSSean Wang hw->dev = &pdev->dev; 724e78d57b2SSean Wang 725*2bc47dfeSSean Wang if (!hw->soc->nbase_names) { 726*2bc47dfeSSean Wang dev_err(&pdev->dev, 727*2bc47dfeSSean Wang "SoC should be assigned at least one register base\n"); 728*2bc47dfeSSean Wang return -EINVAL; 729*2bc47dfeSSean Wang } 730*2bc47dfeSSean Wang 731*2bc47dfeSSean Wang hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names, 732*2bc47dfeSSean Wang sizeof(*hw->base), GFP_KERNEL); 733*2bc47dfeSSean Wang if (IS_ERR(hw->base)) 734*2bc47dfeSSean Wang return PTR_ERR(hw->base); 735*2bc47dfeSSean Wang 736*2bc47dfeSSean Wang for (i = 0; i < hw->soc->nbase_names; i++) { 737*2bc47dfeSSean Wang res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 738*2bc47dfeSSean Wang hw->soc->base_names[i]); 739e78d57b2SSean Wang if (!res) { 740e78d57b2SSean Wang dev_err(&pdev->dev, "missing IO resource\n"); 741e78d57b2SSean Wang return -ENXIO; 742e78d57b2SSean Wang } 743e78d57b2SSean Wang 744*2bc47dfeSSean Wang hw->base[i] = devm_ioremap_resource(&pdev->dev, res); 745*2bc47dfeSSean Wang if (IS_ERR(hw->base[i])) 746*2bc47dfeSSean Wang return PTR_ERR(hw->base[i]); 747*2bc47dfeSSean Wang } 748*2bc47dfeSSean Wang 749*2bc47dfeSSean Wang hw->nbase = hw->soc->nbase_names; 750e78d57b2SSean Wang 751e78d57b2SSean Wang /* Setup pins descriptions per SoC types */ 752fb5fa8dcSSean Wang mtk_desc.pins = (const struct pinctrl_pin_desc *)hw->soc->pins; 753e78d57b2SSean Wang mtk_desc.npins = hw->soc->npins; 754e78d57b2SSean Wang mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings); 755e78d57b2SSean Wang mtk_desc.custom_params = mtk_custom_bindings; 756e78d57b2SSean Wang #ifdef CONFIG_DEBUG_FS 757e78d57b2SSean Wang mtk_desc.custom_conf_items = mtk_conf_items; 758e78d57b2SSean Wang #endif 759e78d57b2SSean Wang 760e78d57b2SSean Wang err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw, 761e78d57b2SSean Wang &hw->pctrl); 762e78d57b2SSean Wang if (err) 763e78d57b2SSean Wang return err; 764e78d57b2SSean Wang 765e78d57b2SSean Wang /* Setup groups descriptions per SoC types */ 766e78d57b2SSean Wang err = mtk_build_groups(hw); 767e78d57b2SSean Wang if (err) { 768e78d57b2SSean Wang dev_err(&pdev->dev, "Failed to build groups\n"); 769e78d57b2SSean Wang return err; 770e78d57b2SSean Wang } 771e78d57b2SSean Wang 772e78d57b2SSean Wang /* Setup functions descriptions per SoC types */ 773e78d57b2SSean Wang err = mtk_build_functions(hw); 774e78d57b2SSean Wang if (err) { 775e78d57b2SSean Wang dev_err(&pdev->dev, "Failed to build functions\n"); 776e78d57b2SSean Wang return err; 777e78d57b2SSean Wang } 778e78d57b2SSean Wang 779e78d57b2SSean Wang /* For able to make pinctrl_claim_hogs, we must not enable pinctrl 780e78d57b2SSean Wang * until all groups and functions are being added one. 781e78d57b2SSean Wang */ 782e78d57b2SSean Wang err = pinctrl_enable(hw->pctrl); 783e78d57b2SSean Wang if (err) 784e78d57b2SSean Wang return err; 785e78d57b2SSean Wang 786e78d57b2SSean Wang err = mtk_build_eint(hw, pdev); 787e78d57b2SSean Wang if (err) 788e78d57b2SSean Wang dev_warn(&pdev->dev, 789e78d57b2SSean Wang "Failed to add EINT, but pinctrl still can work\n"); 790e78d57b2SSean Wang 791e78d57b2SSean Wang /* Build gpiochip should be after pinctrl_enable is done */ 792e78d57b2SSean Wang err = mtk_build_gpiochip(hw, pdev->dev.of_node); 793e78d57b2SSean Wang if (err) { 794e78d57b2SSean Wang dev_err(&pdev->dev, "Failed to add gpio_chip\n"); 795e78d57b2SSean Wang return err; 796e78d57b2SSean Wang } 797e78d57b2SSean Wang 798e78d57b2SSean Wang platform_set_drvdata(pdev, hw); 799e78d57b2SSean Wang 800e78d57b2SSean Wang return 0; 801e78d57b2SSean Wang } 802