172b5135bSBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0
272b5135bSBartosz Golaszewski //
372b5135bSBartosz Golaszewski // Copyright (C) 2018 BayLibre SAS
472b5135bSBartosz Golaszewski // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
572b5135bSBartosz Golaszewski //
672b5135bSBartosz Golaszewski // GPIO driver for MAXIM 77650/77651 charger/power-supply.
772b5135bSBartosz Golaszewski
872b5135bSBartosz Golaszewski #include <linux/gpio/driver.h>
972b5135bSBartosz Golaszewski #include <linux/i2c.h>
1072b5135bSBartosz Golaszewski #include <linux/mfd/max77650.h>
1172b5135bSBartosz Golaszewski #include <linux/module.h>
1272b5135bSBartosz Golaszewski #include <linux/platform_device.h>
1372b5135bSBartosz Golaszewski #include <linux/regmap.h>
1472b5135bSBartosz Golaszewski
1572b5135bSBartosz Golaszewski #define MAX77650_GPIO_DIR_MASK BIT(0)
1672b5135bSBartosz Golaszewski #define MAX77650_GPIO_INVAL_MASK BIT(1)
1772b5135bSBartosz Golaszewski #define MAX77650_GPIO_DRV_MASK BIT(2)
1872b5135bSBartosz Golaszewski #define MAX77650_GPIO_OUTVAL_MASK BIT(3)
1972b5135bSBartosz Golaszewski #define MAX77650_GPIO_DEBOUNCE_MASK BIT(4)
2072b5135bSBartosz Golaszewski
2172b5135bSBartosz Golaszewski #define MAX77650_GPIO_DIR_OUT 0x00
2272b5135bSBartosz Golaszewski #define MAX77650_GPIO_DIR_IN BIT(0)
2372b5135bSBartosz Golaszewski #define MAX77650_GPIO_OUT_LOW 0x00
2472b5135bSBartosz Golaszewski #define MAX77650_GPIO_OUT_HIGH BIT(3)
2572b5135bSBartosz Golaszewski #define MAX77650_GPIO_DRV_OPEN_DRAIN 0x00
2672b5135bSBartosz Golaszewski #define MAX77650_GPIO_DRV_PUSH_PULL BIT(2)
2772b5135bSBartosz Golaszewski #define MAX77650_GPIO_DEBOUNCE BIT(4)
2872b5135bSBartosz Golaszewski
2972b5135bSBartosz Golaszewski #define MAX77650_GPIO_DIR_BITS(_reg) \
3072b5135bSBartosz Golaszewski ((_reg) & MAX77650_GPIO_DIR_MASK)
3172b5135bSBartosz Golaszewski #define MAX77650_GPIO_INVAL_BITS(_reg) \
3272b5135bSBartosz Golaszewski (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1)
3372b5135bSBartosz Golaszewski
3472b5135bSBartosz Golaszewski struct max77650_gpio_chip {
3572b5135bSBartosz Golaszewski struct regmap *map;
3672b5135bSBartosz Golaszewski struct gpio_chip gc;
3772b5135bSBartosz Golaszewski int irq;
3872b5135bSBartosz Golaszewski };
3972b5135bSBartosz Golaszewski
max77650_gpio_direction_input(struct gpio_chip * gc,unsigned int offset)4072b5135bSBartosz Golaszewski static int max77650_gpio_direction_input(struct gpio_chip *gc,
4172b5135bSBartosz Golaszewski unsigned int offset)
4272b5135bSBartosz Golaszewski {
4372b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
4472b5135bSBartosz Golaszewski
4572b5135bSBartosz Golaszewski return regmap_update_bits(chip->map,
4672b5135bSBartosz Golaszewski MAX77650_REG_CNFG_GPIO,
4772b5135bSBartosz Golaszewski MAX77650_GPIO_DIR_MASK,
4872b5135bSBartosz Golaszewski MAX77650_GPIO_DIR_IN);
4972b5135bSBartosz Golaszewski }
5072b5135bSBartosz Golaszewski
max77650_gpio_direction_output(struct gpio_chip * gc,unsigned int offset,int value)5172b5135bSBartosz Golaszewski static int max77650_gpio_direction_output(struct gpio_chip *gc,
5272b5135bSBartosz Golaszewski unsigned int offset, int value)
5372b5135bSBartosz Golaszewski {
5472b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
5572b5135bSBartosz Golaszewski int mask, regval;
5672b5135bSBartosz Golaszewski
5772b5135bSBartosz Golaszewski mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK;
5872b5135bSBartosz Golaszewski regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
5972b5135bSBartosz Golaszewski regval |= MAX77650_GPIO_DIR_OUT;
6072b5135bSBartosz Golaszewski
6172b5135bSBartosz Golaszewski return regmap_update_bits(chip->map,
6272b5135bSBartosz Golaszewski MAX77650_REG_CNFG_GPIO, mask, regval);
6372b5135bSBartosz Golaszewski }
6472b5135bSBartosz Golaszewski
max77650_gpio_set_value(struct gpio_chip * gc,unsigned int offset,int value)6572b5135bSBartosz Golaszewski static void max77650_gpio_set_value(struct gpio_chip *gc,
6672b5135bSBartosz Golaszewski unsigned int offset, int value)
6772b5135bSBartosz Golaszewski {
6872b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
6972b5135bSBartosz Golaszewski int rv, regval;
7072b5135bSBartosz Golaszewski
7172b5135bSBartosz Golaszewski regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW;
7272b5135bSBartosz Golaszewski
7372b5135bSBartosz Golaszewski rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO,
7472b5135bSBartosz Golaszewski MAX77650_GPIO_OUTVAL_MASK, regval);
7572b5135bSBartosz Golaszewski if (rv)
7672b5135bSBartosz Golaszewski dev_err(gc->parent, "cannot set GPIO value: %d\n", rv);
7772b5135bSBartosz Golaszewski }
7872b5135bSBartosz Golaszewski
max77650_gpio_get_value(struct gpio_chip * gc,unsigned int offset)7972b5135bSBartosz Golaszewski static int max77650_gpio_get_value(struct gpio_chip *gc,
8072b5135bSBartosz Golaszewski unsigned int offset)
8172b5135bSBartosz Golaszewski {
8272b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
8372b5135bSBartosz Golaszewski unsigned int val;
8472b5135bSBartosz Golaszewski int rv;
8572b5135bSBartosz Golaszewski
8672b5135bSBartosz Golaszewski rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
8772b5135bSBartosz Golaszewski if (rv)
8872b5135bSBartosz Golaszewski return rv;
8972b5135bSBartosz Golaszewski
9072b5135bSBartosz Golaszewski return MAX77650_GPIO_INVAL_BITS(val);
9172b5135bSBartosz Golaszewski }
9272b5135bSBartosz Golaszewski
max77650_gpio_get_direction(struct gpio_chip * gc,unsigned int offset)9372b5135bSBartosz Golaszewski static int max77650_gpio_get_direction(struct gpio_chip *gc,
9472b5135bSBartosz Golaszewski unsigned int offset)
9572b5135bSBartosz Golaszewski {
9672b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
9772b5135bSBartosz Golaszewski unsigned int val;
9872b5135bSBartosz Golaszewski int rv;
9972b5135bSBartosz Golaszewski
10072b5135bSBartosz Golaszewski rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val);
10172b5135bSBartosz Golaszewski if (rv)
10272b5135bSBartosz Golaszewski return rv;
10372b5135bSBartosz Golaszewski
10472b5135bSBartosz Golaszewski return MAX77650_GPIO_DIR_BITS(val);
10572b5135bSBartosz Golaszewski }
10672b5135bSBartosz Golaszewski
max77650_gpio_set_config(struct gpio_chip * gc,unsigned int offset,unsigned long cfg)10772b5135bSBartosz Golaszewski static int max77650_gpio_set_config(struct gpio_chip *gc,
10872b5135bSBartosz Golaszewski unsigned int offset, unsigned long cfg)
10972b5135bSBartosz Golaszewski {
11072b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
11172b5135bSBartosz Golaszewski
11272b5135bSBartosz Golaszewski switch (pinconf_to_config_param(cfg)) {
11372b5135bSBartosz Golaszewski case PIN_CONFIG_DRIVE_OPEN_DRAIN:
11472b5135bSBartosz Golaszewski return regmap_update_bits(chip->map,
11572b5135bSBartosz Golaszewski MAX77650_REG_CNFG_GPIO,
11672b5135bSBartosz Golaszewski MAX77650_GPIO_DRV_MASK,
11772b5135bSBartosz Golaszewski MAX77650_GPIO_DRV_OPEN_DRAIN);
11872b5135bSBartosz Golaszewski case PIN_CONFIG_DRIVE_PUSH_PULL:
11972b5135bSBartosz Golaszewski return regmap_update_bits(chip->map,
12072b5135bSBartosz Golaszewski MAX77650_REG_CNFG_GPIO,
12172b5135bSBartosz Golaszewski MAX77650_GPIO_DRV_MASK,
12272b5135bSBartosz Golaszewski MAX77650_GPIO_DRV_PUSH_PULL);
12372b5135bSBartosz Golaszewski case PIN_CONFIG_INPUT_DEBOUNCE:
12472b5135bSBartosz Golaszewski return regmap_update_bits(chip->map,
12572b5135bSBartosz Golaszewski MAX77650_REG_CNFG_GPIO,
12672b5135bSBartosz Golaszewski MAX77650_GPIO_DEBOUNCE_MASK,
12772b5135bSBartosz Golaszewski MAX77650_GPIO_DEBOUNCE);
12872b5135bSBartosz Golaszewski default:
12972b5135bSBartosz Golaszewski return -ENOTSUPP;
13072b5135bSBartosz Golaszewski }
13172b5135bSBartosz Golaszewski }
13272b5135bSBartosz Golaszewski
max77650_gpio_to_irq(struct gpio_chip * gc,unsigned int offset)13372b5135bSBartosz Golaszewski static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
13472b5135bSBartosz Golaszewski {
13572b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip = gpiochip_get_data(gc);
13672b5135bSBartosz Golaszewski
13772b5135bSBartosz Golaszewski return chip->irq;
13872b5135bSBartosz Golaszewski }
13972b5135bSBartosz Golaszewski
max77650_gpio_probe(struct platform_device * pdev)14072b5135bSBartosz Golaszewski static int max77650_gpio_probe(struct platform_device *pdev)
14172b5135bSBartosz Golaszewski {
14272b5135bSBartosz Golaszewski struct max77650_gpio_chip *chip;
14372b5135bSBartosz Golaszewski struct device *dev, *parent;
14472b5135bSBartosz Golaszewski struct i2c_client *i2c;
14572b5135bSBartosz Golaszewski
14672b5135bSBartosz Golaszewski dev = &pdev->dev;
14772b5135bSBartosz Golaszewski parent = dev->parent;
14872b5135bSBartosz Golaszewski i2c = to_i2c_client(parent);
14972b5135bSBartosz Golaszewski
15072b5135bSBartosz Golaszewski chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
15172b5135bSBartosz Golaszewski if (!chip)
15272b5135bSBartosz Golaszewski return -ENOMEM;
15372b5135bSBartosz Golaszewski
15472b5135bSBartosz Golaszewski chip->map = dev_get_regmap(parent, NULL);
15572b5135bSBartosz Golaszewski if (!chip->map)
15672b5135bSBartosz Golaszewski return -ENODEV;
15772b5135bSBartosz Golaszewski
15872b5135bSBartosz Golaszewski chip->irq = platform_get_irq_byname(pdev, "GPI");
15972b5135bSBartosz Golaszewski if (chip->irq < 0)
16072b5135bSBartosz Golaszewski return chip->irq;
16172b5135bSBartosz Golaszewski
16272b5135bSBartosz Golaszewski chip->gc.base = -1;
16372b5135bSBartosz Golaszewski chip->gc.ngpio = 1;
16472b5135bSBartosz Golaszewski chip->gc.label = i2c->name;
16572b5135bSBartosz Golaszewski chip->gc.parent = dev;
16672b5135bSBartosz Golaszewski chip->gc.owner = THIS_MODULE;
16772b5135bSBartosz Golaszewski chip->gc.can_sleep = true;
16872b5135bSBartosz Golaszewski
16972b5135bSBartosz Golaszewski chip->gc.direction_input = max77650_gpio_direction_input;
17072b5135bSBartosz Golaszewski chip->gc.direction_output = max77650_gpio_direction_output;
17172b5135bSBartosz Golaszewski chip->gc.set = max77650_gpio_set_value;
17272b5135bSBartosz Golaszewski chip->gc.get = max77650_gpio_get_value;
17372b5135bSBartosz Golaszewski chip->gc.get_direction = max77650_gpio_get_direction;
17472b5135bSBartosz Golaszewski chip->gc.set_config = max77650_gpio_set_config;
17572b5135bSBartosz Golaszewski chip->gc.to_irq = max77650_gpio_to_irq;
17672b5135bSBartosz Golaszewski
17772b5135bSBartosz Golaszewski return devm_gpiochip_add_data(dev, &chip->gc, chip);
17872b5135bSBartosz Golaszewski }
17972b5135bSBartosz Golaszewski
18072b5135bSBartosz Golaszewski static struct platform_driver max77650_gpio_driver = {
18172b5135bSBartosz Golaszewski .driver = {
18272b5135bSBartosz Golaszewski .name = "max77650-gpio",
18372b5135bSBartosz Golaszewski },
18472b5135bSBartosz Golaszewski .probe = max77650_gpio_probe,
18572b5135bSBartosz Golaszewski };
18672b5135bSBartosz Golaszewski module_platform_driver(max77650_gpio_driver);
18772b5135bSBartosz Golaszewski
18872b5135bSBartosz Golaszewski MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver");
18972b5135bSBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
19072b5135bSBartosz Golaszewski MODULE_LICENSE("GPL v2");
191*a299726dSBartosz Golaszewski MODULE_ALIAS("platform:max77650-gpio");
192