diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 008b8babf31e..d4729fa59edb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -339,22 +339,23 @@ config GPIO_PXA Say yes here to support the PXA GPIO device config GPIO_QPNP_PIN + tristate "Qualcomm Technologies, Inc. QPNP GPIO support" depends on SPMI - tristate "Qualcomm QPNP gpio support" help - Say 'y' here to include support for the Qualcomm QPNP gpio - driver. This driver supports Device Tree and allows a - device_node to be registered as a gpio-controller. It - does not handle gpio interrupts directly, they are handled - via the spmi arbiter interrupt driver. + Say 'y' here to include support for the Qualcomm Technologies, Inc. + QPNP GPIO driver. This driver supports Device Tree and allows a + device_node to be registered as a gpio-controller. It does not handle + GPIO interrupts directly; they are handled via the SPMI arbiter + interrupt driver. config GPIO_QPNP_PIN_DEBUG - depends on GPIO_QPNP_PIN - depends on DEBUG_FS - bool "Qualcomm QPNP GPIO debug support" + bool "Qualcomm Technologies, Inc. QPNP GPIO debug support" + depends on GPIO_QPNP_PIN && DEBUG_FS help - Say 'y' here to include debug support for the Qualcomm - QPNP gpio driver. + Say 'y' here to include debug support for the Qualcomm Technologies, + Inc. QPNP GPIO driver. This provides a userspace debug interface to + get and set all of the supported features of PMIC GPIO and MPP pins + including those which are managed by the gpio framework. config GPIO_RCAR tristate "Renesas R-Car GPIO" diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c index de24d99ea34e..62cd78a95303 100644 --- a/drivers/gpio/qpnp-pin.c +++ b/drivers/gpio/qpnp-pin.c @@ -295,7 +295,7 @@ static int qpnp_pin_check_config(enum qpnp_pin_param_type idx, if (val >= QPNP_PIN_GPIO_LV_MV_MODE_INVALID) return -EINVAL; } else if (val >= QPNP_PIN_GPIO_MODE_INVALID) { - return -EINVAL; + return -EINVAL; } } else if (q_spec->type == Q_MPP_TYPE) { if (val >= QPNP_PIN_MPP_MODE_INVALID) @@ -753,16 +753,17 @@ int qpnp_pin_config(int gpio, struct qpnp_pin_cfg *param) } EXPORT_SYMBOL(qpnp_pin_config); -#define Q_MAX_CHIP_NAME 128 int qpnp_pin_map(const char *name, uint32_t pmic_pin) { struct qpnp_pin_chip *q_chip; struct qpnp_pin_spec *q_spec = NULL; + if (!name) + return -EINVAL; + mutex_lock(&qpnp_pin_chips_lock); list_for_each_entry(q_chip, &qpnp_pin_chips, chip_list) { - if (strncmp(q_chip->gpio_chip.label, name, - Q_MAX_CHIP_NAME) != 0) + if (strcmp(q_chip->gpio_chip.label, name) != 0) continue; if (q_chip->pmic_pin_lowest <= pmic_pin && q_chip->pmic_pin_highest >= pmic_pin) { @@ -778,7 +779,7 @@ int qpnp_pin_map(const char *name, uint32_t pmic_pin) } EXPORT_SYMBOL(qpnp_pin_map); -static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -811,14 +812,13 @@ static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) return q_spec->irq; } -static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned int offset) { - int rc, ret_val; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec = NULL; - u8 buf[1], en_mask; - u8 shift, mask, reg; - int val; + u8 buf, en_mask, shift, mask, reg; + unsigned int val; + int rc; if (WARN_ON(!q_chip)) return -ENODEV; @@ -840,7 +840,9 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) == QPNP_PIN_MODE_DIG_IN) { rc = regmap_read(q_chip->regmap, Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val); - buf[0] = (u8)val; + if (rc) + return rc; + buf = val; if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0) en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK; @@ -850,26 +852,23 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) else /* MPP */ en_mask = Q_REG_STATUS1_MPP_EN_MASK; - if (!(buf[0] & en_mask)) + if (!(buf & en_mask)) return -EPERM; - return buf[0] & Q_REG_STATUS1_VAL_MASK; - } else { - if (is_gpio_lv_mv(q_spec)) { - shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; - mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; - } else { - shift = Q_REG_OUT_INVERT_SHIFT; - mask = Q_REG_OUT_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_MODE_CTL]; - } - - ret_val = (reg & mask) >> shift; - return ret_val; + return buf & Q_REG_STATUS1_VAL_MASK; } - return 0; + if (is_gpio_lv_mv(q_spec)) { + shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; + mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; + } else { + shift = Q_REG_OUT_INVERT_SHIFT; + mask = Q_REG_OUT_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_MODE_CTL]; + } + + return (reg & mask) >> shift; } static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, @@ -905,7 +904,7 @@ static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, static void qpnp_pin_set(struct gpio_chip *gpio_chip, - unsigned offset, int value) + unsigned int offset, int value) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -950,7 +949,7 @@ static int qpnp_pin_set_mode(struct qpnp_pin_chip *q_chip, } static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, - unsigned offset) + unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -966,8 +965,7 @@ static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, } static int qpnp_pin_direction_output(struct gpio_chip *gpio_chip, - unsigned offset, - int val) + unsigned int offset, int val) { int rc; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); @@ -1343,7 +1341,7 @@ struct qpnp_pin_debugfs_args { const char *filename; }; -static struct qpnp_pin_debugfs_args dfs_args[] = { +static struct qpnp_pin_debugfs_args dfs_args[Q_NUM_PARAMS] = { { Q_PIN_CFG_MODE, "mode" }, { Q_PIN_CFG_OUTPUT_TYPE, "output_type" }, { Q_PIN_CFG_INVERT, "invert" }, @@ -1371,8 +1369,6 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) struct dentry *dfs, *dfs_io_dir; int i, j, rc; - BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args)); - q_chip->dfs_dir = debugfs_create_dir(q_chip->gpio_chip.label, driver_dfs_dir); if (q_chip->dfs_dir == NULL) { @@ -1403,12 +1399,8 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) continue; params[type] = type; - dfs = debugfs_create_file( - filename, - S_IRUGO | S_IWUSR, - dfs_io_dir, - &q_spec->params[type], - &qpnp_pin_fops); + dfs = debugfs_create_file(filename, 0644, dfs_io_dir, + &q_spec->params[type], &qpnp_pin_fops); if (dfs == NULL) goto dfs_err; } @@ -1674,7 +1666,7 @@ static int qpnp_pin_remove(struct platform_device *pdev) return qpnp_pin_free_chip(q_chip); } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-pin", }, {}