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