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 41 return val & BIT(offset); 42 } 43 44 static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip, 45 unsigned int offset) 46 { 47 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 48 49 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, 50 BIT(offset), 0); 51 52 return 0; 53 } 54 55 static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip, 56 unsigned int offset, int value) 57 { 58 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 59 60 /* Set the initial value */ 61 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, 62 BIT(offset), value ? BIT(offset) : 0); 63 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, 64 BIT(offset), BIT(offset)); 65 66 return 0; 67 } 68 69 static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset) 70 { 71 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 72 int ret, val; 73 74 ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val); 75 if (ret < 0) 76 return ret; 77 78 return val & BIT(offset); 79 } 80 81 static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, 82 int value) 83 { 84 struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); 85 86 regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, 87 BIT(offset), value ? BIT(offset) : 0); 88 } 89 90 static const struct gpio_chip template_chip = { 91 .label = "bd9571mwv-gpio", 92 .owner = THIS_MODULE, 93 .get_direction = bd9571mwv_gpio_get_direction, 94 .direction_input = bd9571mwv_gpio_direction_input, 95 .direction_output = bd9571mwv_gpio_direction_output, 96 .get = bd9571mwv_gpio_get, 97 .set = bd9571mwv_gpio_set, 98 .base = -1, 99 .ngpio = 2, 100 .can_sleep = true, 101 }; 102 103 static int bd9571mwv_gpio_probe(struct platform_device *pdev) 104 { 105 struct bd9571mwv_gpio *gpio; 106 int ret; 107 108 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); 109 if (!gpio) 110 return -ENOMEM; 111 112 platform_set_drvdata(pdev, gpio); 113 114 gpio->bd = dev_get_drvdata(pdev->dev.parent); 115 gpio->chip = template_chip; 116 gpio->chip.parent = gpio->bd->dev; 117 118 ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); 119 if (ret < 0) { 120 dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); 121 return ret; 122 } 123 124 return 0; 125 } 126 127 static const struct platform_device_id bd9571mwv_gpio_id_table[] = { 128 { "bd9571mwv-gpio", }, 129 { /* sentinel */ } 130 }; 131 MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table); 132 133 static struct platform_driver bd9571mwv_gpio_driver = { 134 .driver = { 135 .name = "bd9571mwv-gpio", 136 }, 137 .probe = bd9571mwv_gpio_probe, 138 .id_table = bd9571mwv_gpio_id_table, 139 }; 140 module_platform_driver(bd9571mwv_gpio_driver); 141 142 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); 143 MODULE_DESCRIPTION("BD9571MWV GPIO driver"); 144 MODULE_LICENSE("GPL v2"); 145