xref: /openbmc/linux/drivers/gpio/gpio-max77650.c (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
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