1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ROHM BD9571MWV-M GPIO driver 4 * 5 * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com> 6 * 7 * Based on the TPS65086 driver 8 * 9 * NOTE: Interrupts are not supported yet. 10 */ 11 12 #include <linux/gpio/driver.h> 13 #include <linux/module.h> 14 #include <linux/platform_device.h> 15 16 #include <linux/mfd/bd9571mwv.h> 17 18 struct bd9571mwv_gpio { 19 struct gpio_chip chip; 20 struct bd9571mwv *bd; 21 }; 22 23 static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip, 24 unsigned int offset) 25 { 26 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 27 int ret, val; 28 29 ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val); 30 if (ret < 0) 31 return ret; 32 if (val & BIT(offset)) 33 return GPIO_LINE_DIRECTION_IN; 34 35 return GPIO_LINE_DIRECTION_OUT; 36 } 37 38 static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip, 39 unsigned int offset) 40 { 41 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 42 43 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, 44 BIT(offset), 0); 45 46 return 0; 47 } 48 49 static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip, 50 unsigned int offset, int value) 51 { 52 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 53 54 /* Set the initial value */ 55 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, 56 BIT(offset), value ? BIT(offset) : 0); 57 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, 58 BIT(offset), BIT(offset)); 59 60 return 0; 61 } 62 63 static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset) 64 { 65 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 66 int ret, val; 67 68 ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val); 69 if (ret < 0) 70 return ret; 71 72 return val & BIT(offset); 73 } 74 75 static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, 76 int value) 77 { 78 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 79 80 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, 81 BIT(offset), value ? BIT(offset) : 0); 82 } 83 84 static const struct gpio_chip template_chip = { 85 .label = "bd9571mwv-gpio", 86 .owner = THIS_MODULE, 87 .get_direction = bd9571mwv_gpio_get_direction, 88 .direction_input = bd9571mwv_gpio_direction_input, 89 .direction_output = bd9571mwv_gpio_direction_output, 90 .get = bd9571mwv_gpio_get, 91 .set = bd9571mwv_gpio_set, 92 .base = -1, 93 .ngpio = 2, 94 .can_sleep = true, 95 }; 96 97 static int bd9571mwv_gpio_probe(struct platform_device *pdev) 98 { 99 struct bd9571mwv_gpio *gpio; 100 int ret; 101 102 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 103 if (!gpio) 104 return -ENOMEM; 105 106 platform_set_drvdata(pdev, gpio); 107 108 gpio->bd = dev_get_drvdata(pdev->dev.parent); 109 gpio->chip = template_chip; 110 gpio->chip.parent = gpio->bd->dev; 111 112 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); 113 if (ret < 0) { 114 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 115 return ret; 116 } 117 118 return 0; 119 } 120 121 static const struct platform_device_id bd9571mwv_gpio_id_table[] = { 122 { "bd9571mwv-gpio", }, 123 { /* sentinel */ } 124 }; 125 MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table); 126 127 static struct platform_driver bd9571mwv_gpio_driver = { 128 .driver = { 129 .name = "bd9571mwv-gpio", 130 }, 131 .probe = bd9571mwv_gpio_probe, 132 .id_table = bd9571mwv_gpio_id_table, 133 }; 134 module_platform_driver(bd9571mwv_gpio_driver); 135 136 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); 137 MODULE_DESCRIPTION("BD9571MWV GPIO driver"); 138 MODULE_LICENSE("GPL v2"); 139