Re: [PATCHv3 02/14] pinctrl: mcp23s08: add pinconf support

From: Sebastian Reichel
Date: Mon May 15 2017 - 08:34:55 EST


Hi,

On Mon, May 15, 2017 at 11:24:26AM +0200, Sebastian Reichel wrote:
> mcp23xxx device have configurable 100k pullup resistors. This adds
> support for enabling them using pinctrl's pinconf interface.
>
> Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxxxx>

I just noticed, that I forgot to add:

Tested-by: Enric Balletbo i Serra <enric.balletbo@xxxxxxxxxxxxx>

-- Sebastian

> ---
> drivers/pinctrl/Kconfig | 1 +
> drivers/pinctrl/pinctrl-mcp23s08.c | 199 ++++++++++++++++++++++++++++++++-----
> 2 files changed, 176 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index b5aa50c51633..1dabd1d79c1d 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -153,6 +153,7 @@ config PINCTRL_MCP23S08
> select GPIOLIB_IRQCHIP
> select REGMAP_I2C if I2C
> select REGMAP_SPI if SPI_MASTER
> + select GENERIC_PINCONF
> help
> SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
> I/O expanders.
> diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
> index 2a57d024481d..d957c4bbc8c1 100644
> --- a/drivers/pinctrl/pinctrl-mcp23s08.c
> +++ b/drivers/pinctrl/pinctrl-mcp23s08.c
> @@ -24,6 +24,9 @@
> #include <linux/of_irq.h>
> #include <linux/of_device.h>
> #include <linux/regmap.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
>
> /**
> * MCP types supported by driver
> @@ -77,6 +80,9 @@ struct mcp23s08 {
>
> struct regmap *regmap;
> struct device *dev;
> +
> + struct pinctrl_dev *pctldev;
> + struct pinctrl_desc pinctrl_desc;
> };
>
> static const struct regmap_config mcp23x08_regmap = {
> @@ -96,6 +102,158 @@ static const struct regmap_config mcp23x17_regmap = {
> .val_format_endian = REGMAP_ENDIAN_LITTLE,
> };
>
> +static int mcp_read(struct mcp23s08 *mcp, unsigned int reg, unsigned int *val)
> +{
> + return regmap_read(mcp->regmap, reg << mcp->reg_shift, val);
> +}
> +
> +static int mcp_write(struct mcp23s08 *mcp, unsigned int reg, unsigned int val)
> +{
> + return regmap_write(mcp->regmap, reg << mcp->reg_shift, val);
> +}
> +
> +static int mcp_set_bit(struct mcp23s08 *mcp, unsigned int reg,
> + unsigned int pin, bool enabled)
> +{
> + u16 val = enabled ? 0xffff : 0x0000;
> + u16 mask = BIT(pin);
> + return regmap_update_bits(mcp->regmap, reg << mcp->reg_shift,
> + mask, val);
> +}
> +
> +static int mcp_update_cache(struct mcp23s08 *mcp)
> +{
> + int ret, reg, i;
> +
> + for (i = 0; i < ARRAY_SIZE(mcp->cache); i++) {
> + ret = mcp_read(mcp, i, &reg);
> + if (ret < 0)
> + return ret;
> + mcp->cache[i] = reg;
> + }
> +
> + return 0;
> +}
> +
> +static const struct pinctrl_pin_desc mcp23x08_pins[] = {
> + PINCTRL_PIN(0, "gpio0"),
> + PINCTRL_PIN(1, "gpio1"),
> + PINCTRL_PIN(2, "gpio2"),
> + PINCTRL_PIN(3, "gpio3"),
> + PINCTRL_PIN(4, "gpio4"),
> + PINCTRL_PIN(5, "gpio5"),
> + PINCTRL_PIN(6, "gpio6"),
> + PINCTRL_PIN(7, "gpio7"),
> +};
> +
> +static const struct pinctrl_pin_desc mcp23x17_pins[] = {
> + PINCTRL_PIN(0, "gpio0"),
> + PINCTRL_PIN(1, "gpio1"),
> + PINCTRL_PIN(2, "gpio2"),
> + PINCTRL_PIN(3, "gpio3"),
> + PINCTRL_PIN(4, "gpio4"),
> + PINCTRL_PIN(5, "gpio5"),
> + PINCTRL_PIN(6, "gpio6"),
> + PINCTRL_PIN(7, "gpio7"),
> + PINCTRL_PIN(8, "gpio8"),
> + PINCTRL_PIN(9, "gpio9"),
> + PINCTRL_PIN(10, "gpio10"),
> + PINCTRL_PIN(11, "gpio11"),
> + PINCTRL_PIN(12, "gpio12"),
> + PINCTRL_PIN(13, "gpio13"),
> + PINCTRL_PIN(14, "gpio14"),
> + PINCTRL_PIN(15, "gpio15"),
> +};
> +
> +static int mcp_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
> +{
> + return 0;
> +}
> +
> +static const char *mcp_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
> + unsigned int group)
> +{
> + return NULL;
> +}
> +
> +static int mcp_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
> + unsigned int group,
> + const unsigned int **pins,
> + unsigned int *num_pins)
> +{
> + return -ENOTSUPP;
> +}
> +
> +static const struct pinctrl_ops mcp_pinctrl_ops = {
> + .get_groups_count = mcp_pinctrl_get_groups_count,
> + .get_group_name = mcp_pinctrl_get_group_name,
> + .get_group_pins = mcp_pinctrl_get_group_pins,
> +#ifdef CONFIG_OF
> + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
> + .dt_free_map = pinconf_generic_dt_free_map,
> +#endif
> +};
> +
> +static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
> + unsigned long *config)
> +{
> + struct mcp23s08 *mcp = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param param = pinconf_to_config_param(*config);
> + unsigned int data, status;
> + int ret;
> +
> + switch (param) {
> + case PIN_CONFIG_BIAS_PULL_UP:
> + ret = mcp_read(mcp, MCP_GPPU, &data);
> + if (ret < 0)
> + return ret;
> + status = (data & BIT(pin)) ? 1 : 0;
> + break;
> + default:
> + dev_err(mcp->dev, "Invalid config param %04x\n", param);
> + return -ENOTSUPP;
> + }
> +
> + *config = 0;
> +
> + return status ? 0 : -EINVAL;
> +}
> +
> +static int mcp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
> + unsigned long *configs, unsigned int num_configs)
> +{
> + struct mcp23s08 *mcp = pinctrl_dev_get_drvdata(pctldev);
> + enum pin_config_param param;
> + u32 arg, mask;
> + u16 val;
> + int ret = 0;
> + int i;
> +
> + for (i = 0; i < num_configs; i++) {
> + param = pinconf_to_config_param(configs[i]);
> + arg = pinconf_to_config_argument(configs[i]);
> +
> + switch (param) {
> + case PIN_CONFIG_BIAS_PULL_UP:
> + val = arg ? 0xFFFF : 0x0000;
> + mask = BIT(pin);
> + ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg);
> + break;
> + default:
> + dev_err(mcp->dev, "Invalid config param %04x\n", param);
> + return -ENOTSUPP;
> + }
> + }
> +
> + return ret;
> +}
> +
> +static const struct pinconf_ops mcp_pinconf_ops = {
> + .pin_config_get = mcp_pinconf_get,
> + .pin_config_set = mcp_pinconf_set,
> + .is_generic = true,
> +};
> +
> /*----------------------------------------------------------------------*/
>
> #ifdef CONFIG_SPI_MASTER
> @@ -158,30 +316,6 @@ static const struct regmap_bus mcp23sxx_spi_regmap = {
>
> #endif /* CONFIG_SPI_MASTER */
>
> -static int mcp_read(struct mcp23s08 *mcp, unsigned int reg, unsigned int *val)
> -{
> - return regmap_read(mcp->regmap, reg << mcp->reg_shift, val);
> -}
> -
> -static int mcp_write(struct mcp23s08 *mcp, unsigned int reg, unsigned int val)
> -{
> - return regmap_write(mcp->regmap, reg << mcp->reg_shift, val);
> -}
> -
> -static int mcp_update_cache(struct mcp23s08 *mcp)
> -{
> - int ret, reg, i;
> -
> - for (i = 0; i < ARRAY_SIZE(mcp->cache); i++) {
> - ret = mcp_read(mcp, i, &reg);
> - if (ret < 0)
> - return ret;
> - mcp->cache[i] = reg;
> - }
> -
> - return 0;
> -}
> -
> /*----------------------------------------------------------------------*/
>
> /* A given spi_device can represent up to eight mcp23sxx chips
> @@ -682,6 +816,23 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
> if (ret)
> goto fail;
> }
> +
> + mcp->pinctrl_desc.name = "mcp23xxx-pinctrl";
> + mcp->pinctrl_desc.pctlops = &mcp_pinctrl_ops;
> + mcp->pinctrl_desc.confops = &mcp_pinconf_ops;
> + mcp->pinctrl_desc.npins = mcp->chip.ngpio;
> + if (mcp->pinctrl_desc.npins == 8)
> + mcp->pinctrl_desc.pins = mcp23x08_pins;
> + else if (mcp->pinctrl_desc.npins == 16)
> + mcp->pinctrl_desc.pins = mcp23x17_pins;
> + mcp->pinctrl_desc.owner = THIS_MODULE;
> +
> + mcp->pctldev = devm_pinctrl_register(dev, &mcp->pinctrl_desc, mcp);
> + if (IS_ERR(mcp->pctldev)) {
> + ret = PTR_ERR(mcp->pctldev);
> + goto fail;
> + }
> +
> fail:
> if (ret < 0)
> dev_dbg(dev, "can't setup chip %d, --> %d\n", addr, ret);
> --
> 2.11.0
>

Attachment: signature.asc
Description: PGP signature