diff options
Diffstat (limited to 'drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c')
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 2247eae8eaf0..1da942548ff4 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -6,6 +6,7 @@ * */ +#include <dt-bindings/pinctrl/mt65xx.h> #include <linux/device.h> #include <linux/err.h> #include <linux/gpio/driver.h> @@ -517,6 +518,226 @@ int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, return 0; } +/* Combo for the following pull register type: + * 1. PU + PD + * 2. PULLSEL + PULLEN + * 3. PUPD + R0 + R1 + */ +static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, pu, pd; + + if (arg == MTK_DISABLE) { + pu = 0; + pd = 0; + } else if ((arg == MTK_ENABLE) && pullup) { + pu = 1; + pd = 0; + } else if ((arg == MTK_ENABLE) && !pullup) { + pu = 0; + pd = 1; + } else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, enable; + + if (arg == MTK_DISABLE) + enable = 0; + else if (arg == MTK_ENABLE) + enable = 1; + else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, r0, r1; + + if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) { + pullup = 0; + r0 = 0; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_01) { + r0 = 1; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_10) { + r0 = 0; + r1 = 1; + } else if (arg == MTK_PUPD_SET_R1R0_11) { + r0 = 1; + r1 = 1; + } else { + err = -EINVAL; + goto out; + } + + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, pu, pd; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); + if (err) + goto out; + + if (pu == 0 && pd == 0) { + *pullup = 0; + *enable = MTK_DISABLE; + } else if (pu == 1 && pd == 0) { + *pullup = 1; + *enable = MTK_ENABLE; + } else if (pu == 0 && pd == 1) { + *pullup = 0; + *enable = MTK_ENABLE; + } else + err = -EINVAL; + +out: + return err; +} + +static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, r0, r1; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup); + if (err) + goto out; + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + *pullup = !(*pullup); + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1); + if (err) + goto out; + + if ((r1 == 0) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_00; + else if ((r1 == 0) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_01; + else if ((r1 == 1) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_10; + else if ((r1 == 1) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_11; + else + err = -EINVAL; + +out: + return err; +} + +int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err; + + err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg); + +out: + return err; +} + +int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable); + +out: + return err; +} + /* Revision 0 */ int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg) |