pinctrl: uniphier: support pin configuration in sparse pin space

Unfortunately, the pin number of the new SoC, PH1-LD11, is not
contiguous.  The base frame work must be adjusted to support the new
SoC pinctrl driver.  The pin_desc_get() exploits radix-tree for pin
look-up, so it works more efficiently with sparse pin space.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Masahiro Yamada 2016-05-31 17:05:15 +09:00 committed by Linus Walleij
parent 72e5706aa7
commit 94bf176b97
1 changed files with 42 additions and 44 deletions

View File

@ -64,10 +64,10 @@ static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned offset) struct seq_file *s, unsigned offset)
{ {
const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset]; const struct pin_desc *desc = pin_desc_get(pctldev, offset);
const char *pull_dir, *drv_type; const char *pull_dir, *drv_type;
switch (uniphier_pin_get_pull_dir(pin->drv_data)) { switch (uniphier_pin_get_pull_dir(desc->drv_data)) {
case UNIPHIER_PIN_PULL_UP: case UNIPHIER_PIN_PULL_UP:
pull_dir = "UP"; pull_dir = "UP";
break; break;
@ -87,7 +87,7 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
BUG(); BUG();
} }
switch (uniphier_pin_get_drv_type(pin->drv_data)) { switch (uniphier_pin_get_drv_type(desc->drv_data)) {
case UNIPHIER_PIN_DRV_1BIT: case UNIPHIER_PIN_DRV_1BIT:
drv_type = "4/8(mA)"; drv_type = "4/8(mA)";
break; break;
@ -129,12 +129,12 @@ static const struct pinctrl_ops uniphier_pctlops = {
}; };
static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin, const struct pin_desc *desc,
enum pin_config_param param) enum pin_config_param param)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_pull_dir pull_dir = enum uniphier_pin_pull_dir pull_dir =
uniphier_pin_get_pull_dir(pin->drv_data); uniphier_pin_get_pull_dir(desc->drv_data);
unsigned int pupdctrl, reg, shift, val; unsigned int pupdctrl, reg, shift, val;
unsigned int expected = 1; unsigned int expected = 1;
int ret; int ret;
@ -164,7 +164,7 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
BUG(); BUG();
} }
pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data); pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4; reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
shift = pupdctrl % 32; shift = pupdctrl % 32;
@ -179,12 +179,12 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
} }
static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin, const struct pin_desc *desc,
u16 *strength) u16 *strength)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_drv_type type = enum uniphier_pin_drv_type type =
uniphier_pin_get_drv_type(pin->drv_data); uniphier_pin_get_drv_type(desc->drv_data);
const unsigned int strength_1bit[] = {4, 8}; const unsigned int strength_1bit[] = {4, 8};
const unsigned int strength_2bit[] = {8, 12, 16, 20}; const unsigned int strength_2bit[] = {8, 12, 16, 20};
const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16}; const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16};
@ -222,7 +222,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
return -EINVAL; return -EINVAL;
} }
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
drvctrl *= width; drvctrl *= width;
reg += drvctrl / 32 * 4; reg += drvctrl / 32 * 4;
@ -239,10 +239,10 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
} }
static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin) const struct pin_desc *desc)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data); unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
unsigned int val; unsigned int val;
int ret; int ret;
@ -261,7 +261,7 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
unsigned pin, unsigned pin,
unsigned long *configs) unsigned long *configs)
{ {
const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin]; const struct pin_desc *desc = pin_desc_get(pctldev, pin);
enum pin_config_param param = pinconf_to_config_param(*configs); enum pin_config_param param = pinconf_to_config_param(*configs);
bool has_arg = false; bool has_arg = false;
u16 arg; u16 arg;
@ -271,14 +271,14 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param); ret = uniphier_conf_pin_bias_get(pctldev, desc, param);
break; break;
case PIN_CONFIG_DRIVE_STRENGTH: case PIN_CONFIG_DRIVE_STRENGTH:
ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg); ret = uniphier_conf_pin_drive_get(pctldev, desc, &arg);
has_arg = true; has_arg = true;
break; break;
case PIN_CONFIG_INPUT_ENABLE: case PIN_CONFIG_INPUT_ENABLE:
ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc); ret = uniphier_conf_pin_input_enable_get(pctldev, desc);
break; break;
default: default:
/* unsupported parameter */ /* unsupported parameter */
@ -293,13 +293,12 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
} }
static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin, const struct pin_desc *desc,
enum pin_config_param param, enum pin_config_param param, u16 arg)
u16 arg)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_pull_dir pull_dir = enum uniphier_pin_pull_dir pull_dir =
uniphier_pin_get_pull_dir(pin->drv_data); uniphier_pin_get_pull_dir(desc->drv_data);
unsigned int pupdctrl, reg, shift; unsigned int pupdctrl, reg, shift;
unsigned int val = 1; unsigned int val = 1;
@ -310,8 +309,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED || if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) { pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
"can not disable pull register for pin %u (%s)\n", "can not disable pull register for pin %s\n",
pin->number, pin->name); desc->name);
return -EINVAL; return -EINVAL;
} }
val = 0; val = 0;
@ -321,8 +320,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
return 0; return 0;
if (pull_dir != UNIPHIER_PIN_PULL_UP) { if (pull_dir != UNIPHIER_PIN_PULL_UP) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
"pull-up is unsupported for pin %u (%s)\n", "pull-up is unsupported for pin %s\n",
pin->number, pin->name); desc->name);
return -EINVAL; return -EINVAL;
} }
if (arg == 0) { if (arg == 0) {
@ -335,8 +334,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
return 0; return 0;
if (pull_dir != UNIPHIER_PIN_PULL_DOWN) { if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
"pull-down is unsupported for pin %u (%s)\n", "pull-down is unsupported for pin %s\n",
pin->number, pin->name); desc->name);
return -EINVAL; return -EINVAL;
} }
if (arg == 0) { if (arg == 0) {
@ -347,8 +346,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
if (pull_dir == UNIPHIER_PIN_PULL_NONE) { if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
"pull-up/down is unsupported for pin %u (%s)\n", "pull-up/down is unsupported for pin %s\n",
pin->number, pin->name); desc->name);
return -EINVAL; return -EINVAL;
} }
@ -359,7 +358,7 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
BUG(); BUG();
} }
pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data); pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4; reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
shift = pupdctrl % 32; shift = pupdctrl % 32;
@ -368,12 +367,12 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
} }
static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin, const struct pin_desc *desc,
u16 strength) u16 strength)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
enum uniphier_pin_drv_type type = enum uniphier_pin_drv_type type =
uniphier_pin_get_drv_type(pin->drv_data); uniphier_pin_get_drv_type(desc->drv_data);
const unsigned int strength_1bit[] = {4, 8, -1}; const unsigned int strength_1bit[] = {4, 8, -1};
const unsigned int strength_2bit[] = {8, 12, 16, 20, -1}; const unsigned int strength_2bit[] = {8, 12, 16, 20, -1};
const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16, -1}; const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16, -1};
@ -398,8 +397,8 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
break; break;
default: default:
dev_err(pctldev->dev, dev_err(pctldev->dev,
"cannot change drive strength for pin %u (%s)\n", "cannot change drive strength for pin %s\n",
pin->number, pin->name); desc->name);
return -EINVAL; return -EINVAL;
} }
@ -410,14 +409,14 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
if (val == 0) { if (val == 0) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
"unsupported drive strength %u mA for pin %u (%s)\n", "unsupported drive strength %u mA for pin %s\n",
strength, pin->number, pin->name); strength, desc->name);
return -EINVAL; return -EINVAL;
} }
val--; val--;
drvctrl = uniphier_pin_get_drvctrl(pin->drv_data); drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
drvctrl *= width; drvctrl *= width;
reg += drvctrl / 32 * 4; reg += drvctrl / 32 * 4;
@ -429,11 +428,11 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
} }
static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev, static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
const struct pinctrl_pin_desc *pin, const struct pin_desc *desc,
u16 enable) u16 enable)
{ {
struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev); struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data); unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
if (enable == 0) { if (enable == 0) {
/* /*
@ -457,7 +456,7 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
unsigned long *configs, unsigned long *configs,
unsigned num_configs) unsigned num_configs)
{ {
const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin]; const struct pin_desc *desc = pin_desc_get(pctldev, pin);
int i, ret; int i, ret;
for (i = 0; i < num_configs; i++) { for (i = 0; i < num_configs; i++) {
@ -470,16 +469,15 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
ret = uniphier_conf_pin_bias_set(pctldev, pin_desc, ret = uniphier_conf_pin_bias_set(pctldev, desc,
param, arg); param, arg);
break; break;
case PIN_CONFIG_DRIVE_STRENGTH: case PIN_CONFIG_DRIVE_STRENGTH:
ret = uniphier_conf_pin_drive_set(pctldev, pin_desc, ret = uniphier_conf_pin_drive_set(pctldev, desc, arg);
arg);
break; break;
case PIN_CONFIG_INPUT_ENABLE: case PIN_CONFIG_INPUT_ENABLE:
ret = uniphier_conf_pin_input_enable(pctldev, ret = uniphier_conf_pin_input_enable(pctldev, desc,
pin_desc, arg); arg);
break; break;
default: default:
dev_err(pctldev->dev, dev_err(pctldev->dev,
@ -561,7 +559,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
/* some pins need input-enabling */ /* some pins need input-enabling */
ret = uniphier_conf_pin_input_enable(pctldev, ret = uniphier_conf_pin_input_enable(pctldev,
&pctldev->desc->pins[pin], 1); pin_desc_get(pctldev, pin), 1);
if (ret) if (ret)
return ret; return ret;