pinctrl: Add drive strength support for BM1880 SoC
Add drive strength support for Bitmain BM1880 SoC. Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
7ea6a2edbf
commit
9f1e3c5966
|
@ -4,8 +4,6 @@
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 Linaro Ltd.
|
* Copyright (c) 2019 Linaro Ltd.
|
||||||
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||||
*
|
|
||||||
* TODO: Drive strength support
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -29,6 +27,7 @@
|
||||||
* @ngroups: Number of @groups
|
* @ngroups: Number of @groups
|
||||||
* @funcs: Pinmux functions
|
* @funcs: Pinmux functions
|
||||||
* @nfuncs: Number of @funcs
|
* @nfuncs: Number of @funcs
|
||||||
|
* @pconf: Pinconf data
|
||||||
*/
|
*/
|
||||||
struct bm1880_pinctrl {
|
struct bm1880_pinctrl {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
@ -37,6 +36,7 @@ struct bm1880_pinctrl {
|
||||||
unsigned int ngroups;
|
unsigned int ngroups;
|
||||||
const struct bm1880_pinmux_function *funcs;
|
const struct bm1880_pinmux_function *funcs;
|
||||||
unsigned int nfuncs;
|
unsigned int nfuncs;
|
||||||
|
const struct bm1880_pinconf_data *pinconf;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,6 +69,14 @@ struct bm1880_pinmux_function {
|
||||||
u8 mux_shift;
|
u8 mux_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct bm1880_pinconf_data - pinconf data
|
||||||
|
* @drv_bits: Drive strength bit width
|
||||||
|
*/
|
||||||
|
struct bm1880_pinconf_data {
|
||||||
|
u32 drv_bits;
|
||||||
|
};
|
||||||
|
|
||||||
static const struct pinctrl_pin_desc bm1880_pins[] = {
|
static const struct pinctrl_pin_desc bm1880_pins[] = {
|
||||||
PINCTRL_PIN(0, "MIO0"),
|
PINCTRL_PIN(0, "MIO0"),
|
||||||
PINCTRL_PIN(1, "MIO1"),
|
PINCTRL_PIN(1, "MIO1"),
|
||||||
|
@ -785,6 +793,126 @@ static const struct bm1880_pinmux_function bm1880_pmux_functions[] = {
|
||||||
BM1880_PINMUX_FUNCTION(spi0, 1),
|
BM1880_PINMUX_FUNCTION(spi0, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BM1880_PINCONF_DAT(_width) \
|
||||||
|
{ \
|
||||||
|
.drv_bits = _width, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct bm1880_pinconf_data bm1880_pinconf[] = {
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x03),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
BM1880_PINCONF_DAT(0x02),
|
||||||
|
};
|
||||||
|
|
||||||
static int bm1880_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
static int bm1880_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||||
{
|
{
|
||||||
struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
|
@ -878,9 +1006,145 @@ static int bm1880_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||||
#define BM1880_PINCONF_PULLCTRL(pin) BM1880_PINCONF(pin, 0)
|
#define BM1880_PINCONF_PULLCTRL(pin) BM1880_PINCONF(pin, 0)
|
||||||
#define BM1880_PINCONF_PULLUP(pin) BM1880_PINCONF(pin, 1)
|
#define BM1880_PINCONF_PULLUP(pin) BM1880_PINCONF(pin, 1)
|
||||||
#define BM1880_PINCONF_PULLDOWN(pin) BM1880_PINCONF(pin, 2)
|
#define BM1880_PINCONF_PULLDOWN(pin) BM1880_PINCONF(pin, 2)
|
||||||
|
#define BM1880_PINCONF_DRV(pin) BM1880_PINCONF(pin, 6)
|
||||||
#define BM1880_PINCONF_SCHMITT(pin) BM1880_PINCONF(pin, 9)
|
#define BM1880_PINCONF_SCHMITT(pin) BM1880_PINCONF(pin, 9)
|
||||||
#define BM1880_PINCONF_SLEW(pin) BM1880_PINCONF(pin, 10)
|
#define BM1880_PINCONF_SLEW(pin) BM1880_PINCONF(pin, 10)
|
||||||
|
|
||||||
|
static int bm1880_pinconf_drv_set(unsigned int mA, u32 width,
|
||||||
|
u32 *regval, u32 bit_offset)
|
||||||
|
{
|
||||||
|
u32 _regval;
|
||||||
|
|
||||||
|
_regval = *regval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are two sets of drive strength bit width exposed by the
|
||||||
|
* SoC at 4mA step, hence we need to handle them separately.
|
||||||
|
*/
|
||||||
|
if (width == 0x03) {
|
||||||
|
switch (mA) {
|
||||||
|
case 4:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (0 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (1 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (2 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (3 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (4 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (5 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (6 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (7 << bit_offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (mA) {
|
||||||
|
case 4:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (0 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (1 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (2 << bit_offset);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
_regval &= ~(width << bit_offset);
|
||||||
|
_regval |= (3 << bit_offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*regval = _regval;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bm1880_pinconf_drv_get(u32 width, u32 drv)
|
||||||
|
{
|
||||||
|
int ret = -ENOTSUPP;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are two sets of drive strength bit width exposed by the
|
||||||
|
* SoC at 4mA step, hence we need to handle them separately.
|
||||||
|
*/
|
||||||
|
if (width == 0x03) {
|
||||||
|
switch (drv) {
|
||||||
|
case 0:
|
||||||
|
ret = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret = 8;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret = 12;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ret = 16;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ret = 20;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
ret = 24;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
ret = 28;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
ret = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (drv) {
|
||||||
|
case 0:
|
||||||
|
ret = 4;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret = 8;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret = 12;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ret = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev,
|
static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev,
|
||||||
unsigned int pin,
|
unsigned int pin,
|
||||||
unsigned long *config)
|
unsigned long *config)
|
||||||
|
@ -889,6 +1153,7 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev,
|
||||||
unsigned int param = pinconf_to_config_param(*config);
|
unsigned int param = pinconf_to_config_param(*config);
|
||||||
unsigned int arg = 0;
|
unsigned int arg = 0;
|
||||||
u32 regval, offset, bit_offset;
|
u32 regval, offset, bit_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
offset = (pin >> 1) << 2;
|
offset = (pin >> 1) << 2;
|
||||||
regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
|
regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
|
||||||
|
@ -914,6 +1179,15 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev,
|
||||||
bit_offset = BM1880_PINCONF_SLEW(pin);
|
bit_offset = BM1880_PINCONF_SLEW(pin);
|
||||||
arg = !!(regval & BIT(bit_offset));
|
arg = !!(regval & BIT(bit_offset));
|
||||||
break;
|
break;
|
||||||
|
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||||
|
bit_offset = BM1880_PINCONF_DRV(pin);
|
||||||
|
ret = bm1880_pinconf_drv_get(pctrl->pinconf[pin].drv_bits,
|
||||||
|
!!(regval & BIT(bit_offset)));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
arg = ret;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -930,7 +1204,7 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev,
|
||||||
{
|
{
|
||||||
struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
u32 regval, offset, bit_offset;
|
u32 regval, offset, bit_offset;
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
offset = (pin >> 1) << 2;
|
offset = (pin >> 1) << 2;
|
||||||
regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
|
regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset);
|
||||||
|
@ -966,6 +1240,15 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev,
|
||||||
else
|
else
|
||||||
regval &= ~BIT(bit_offset);
|
regval &= ~BIT(bit_offset);
|
||||||
break;
|
break;
|
||||||
|
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||||
|
bit_offset = BM1880_PINCONF_DRV(pin);
|
||||||
|
ret = bm1880_pinconf_drv_set(arg,
|
||||||
|
pctrl->pinconf[pin].drv_bits,
|
||||||
|
®val, bit_offset);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_warn(pctldev->dev,
|
dev_warn(pctldev->dev,
|
||||||
"unsupported configuration parameter '%u'\n",
|
"unsupported configuration parameter '%u'\n",
|
||||||
|
@ -1041,6 +1324,7 @@ static int bm1880_pinctrl_probe(struct platform_device *pdev)
|
||||||
pctrl->ngroups = ARRAY_SIZE(bm1880_pctrl_groups);
|
pctrl->ngroups = ARRAY_SIZE(bm1880_pctrl_groups);
|
||||||
pctrl->funcs = bm1880_pmux_functions;
|
pctrl->funcs = bm1880_pmux_functions;
|
||||||
pctrl->nfuncs = ARRAY_SIZE(bm1880_pmux_functions);
|
pctrl->nfuncs = ARRAY_SIZE(bm1880_pmux_functions);
|
||||||
|
pctrl->pinconf = bm1880_pinconf;
|
||||||
|
|
||||||
pctrl->pctrldev = devm_pinctrl_register(&pdev->dev, &bm1880_desc,
|
pctrl->pctrldev = devm_pinctrl_register(&pdev->dev, &bm1880_desc,
|
||||||
pctrl);
|
pctrl);
|
||||||
|
|
Loading…
Reference in New Issue