pinctrl: mediatek: add driving strength related support to pinctrl-mtk-common-v2.c
Put driving strength support related functions to pinctrl-mtk-common-v2.c as these operations might be different by chips and allow different type of driver to reuse them. Signed-off-by: Ryder.Lee <ryder.lee@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
1dc5e53691
commit
c28321979b
@ -82,6 +82,9 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
u32 param = pinconf_to_config_param(*config);
|
||||
int val, val2, err, reg, ret = 1;
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
@ -139,19 +142,13 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
|
||||
* 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
ret = ((val2 << 1) + val + 1) * 4;
|
||||
|
||||
if (hw->soc->drive_get) {
|
||||
err = hw->soc->drive_get(hw, desc, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case MTK_PIN_CONFIG_TDSEL:
|
||||
case MTK_PIN_CONFIG_RDSEL:
|
||||
@ -178,9 +175,12 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
u32 reg, param, arg;
|
||||
int cfg, err = 0;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
for (cfg = 0; cfg < num_configs; cfg++) {
|
||||
param = pinconf_to_config_param(configs[cfg]);
|
||||
arg = pinconf_to_config_argument(configs[cfg]);
|
||||
@ -247,24 +247,10 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
/* 4mA when (e8, e4) = (0, 0);
|
||||
* 8mA when (e8, e4) = (0, 1);
|
||||
* 12mA when (e8, e4) = (1, 0);
|
||||
* 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
if (!(arg % 4) && (arg >= 4 && arg <= 16)) {
|
||||
arg = arg / 4 - 1;
|
||||
err = mtk_hw_set_value(hw, pin,
|
||||
PINCTRL_PIN_REG_E4,
|
||||
arg & 0x1);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, pin,
|
||||
PINCTRL_PIN_REG_E8,
|
||||
(arg & 0x2) >> 1);
|
||||
if (err)
|
||||
goto err;
|
||||
if (hw->soc->drive_set) {
|
||||
err = hw->soc->drive_set(hw, desc, arg);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
|
@ -767,6 +767,8 @@ static const struct mtk_pin_soc mt7622_data = {
|
||||
.eint_hw = &mt7622_eint_hw,
|
||||
.gpio_m = 1,
|
||||
.eint_m = 1,
|
||||
.drive_set = mtk_pinconf_drive_set,
|
||||
.drive_get = mtk_pinconf_drive_get,
|
||||
};
|
||||
|
||||
static const struct of_device_id mt7622_pinctrl_of_match[] = {
|
||||
|
@ -13,6 +13,32 @@
|
||||
|
||||
#include "pinctrl-mtk-common-v2.h"
|
||||
|
||||
/**
|
||||
* struct mtk_drive_desc - the structure that holds the information
|
||||
* of the driving current
|
||||
* @min: the minimum current of this group
|
||||
* @max: the maximum current of this group
|
||||
* @step: the step current of this group
|
||||
* @scal: the weight factor
|
||||
*
|
||||
* formula: output = ((input) / step - 1) * scal
|
||||
*/
|
||||
struct mtk_drive_desc {
|
||||
u8 min;
|
||||
u8 max;
|
||||
u8 step;
|
||||
u8 scal;
|
||||
};
|
||||
|
||||
/* The groups of drive strength */
|
||||
const struct mtk_drive_desc mtk_drive[] = {
|
||||
[DRV_GRP0] = { 4, 16, 4, 1 },
|
||||
[DRV_GRP1] = { 4, 16, 4, 2 },
|
||||
[DRV_GRP2] = { 2, 8, 2, 1 },
|
||||
[DRV_GRP3] = { 2, 8, 2, 2 },
|
||||
[DRV_GRP4] = { 2, 16, 2, 1 },
|
||||
};
|
||||
|
||||
static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
|
||||
{
|
||||
writel_relaxed(val, pctl->base + reg);
|
||||
@ -163,3 +189,56 @@ int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field, int *value)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Revision 0 */
|
||||
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err = -ENOTSUPP;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
/* 4mA when (e8, e4) = (0, 0)
|
||||
* 8mA when (e8, e4) = (0, 1)
|
||||
* 12mA when (e8, e4) = (1, 0)
|
||||
* 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
|
||||
arg = (arg / tb->step - 1) * tb->scal;
|
||||
err = mtk_hw_set_value(hw, desc->number, PINCTRL_PIN_REG_E4,
|
||||
arg & 0x1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc->number, PINCTRL_PIN_REG_E8,
|
||||
(arg & 0x2) >> 1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err, val1, val2;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc->number, PINCTRL_PIN_REG_E4, &val1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc->number, PINCTRL_PIN_REG_E8, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
|
||||
* 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
*val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ enum {
|
||||
PINCTRL_PIN_REG_E8,
|
||||
PINCTRL_PIN_REG_TDSEL,
|
||||
PINCTRL_PIN_REG_RDSEL,
|
||||
PINCTRL_PIN_REG_DRV,
|
||||
PINCTRL_PIN_REG_MAX,
|
||||
};
|
||||
|
||||
@ -130,6 +131,8 @@ struct mtk_pin_desc {
|
||||
u8 drv_n;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl;
|
||||
|
||||
/* struct mtk_pin_soc - the structure that holds SoC-specific data */
|
||||
struct mtk_pin_soc {
|
||||
const struct mtk_pin_reg_calc *reg_cal;
|
||||
@ -145,6 +148,12 @@ struct mtk_pin_soc {
|
||||
/* Specific parameters per SoC */
|
||||
u8 gpio_m;
|
||||
u8 eint_m;
|
||||
|
||||
/* Specific pinconfig operations */
|
||||
int (*drive_set)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg);
|
||||
int (*drive_get)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val);
|
||||
};
|
||||
|
||||
struct mtk_pinctrl {
|
||||
@ -161,4 +170,9 @@ void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set);
|
||||
int mtk_hw_set_value(struct mtk_pinctrl *hw, int pin, int field, int value);
|
||||
int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field, int *value);
|
||||
|
||||
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg);
|
||||
int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val);
|
||||
|
||||
#endif /* __PINCTRL_MTK_COMMON_V2_H */
|
||||
|
Loading…
Reference in New Issue
Block a user