Commit | Line | Data |
---|---|---|
d5a4da15 | 1 | // SPDX-License-Identifier: GPL-2.0 |
668a6cc7 | 2 | /* |
ca801a22 | 3 | * GPIO driver for TI TPS65912x PMICs |
668a6cc7 | 4 | * |
ca801a22 AD |
5 | * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ |
6 | * Andrew F. Davis <afd@ti.com> | |
668a6cc7 | 7 | * |
ca801a22 AD |
8 | * Based on the Arizona GPIO driver and the previous TPS65912 driver by |
9 | * Margarita Olaya Cabrera <magi@slimlogic.co.uk> | |
668a6cc7 MO |
10 | */ |
11 | ||
5d75683e | 12 | #include <linux/gpio/driver.h> |
ca801a22 | 13 | #include <linux/module.h> |
668a6cc7 | 14 | #include <linux/platform_device.h> |
ca801a22 | 15 | |
668a6cc7 MO |
16 | #include <linux/mfd/tps65912.h> |
17 | ||
ca801a22 | 18 | struct tps65912_gpio { |
668a6cc7 | 19 | struct gpio_chip gpio_chip; |
ca801a22 | 20 | struct tps65912 *tps; |
668a6cc7 MO |
21 | }; |
22 | ||
ca801a22 AD |
23 | static int tps65912_gpio_get_direction(struct gpio_chip *gc, |
24 | unsigned offset) | |
668a6cc7 | 25 | { |
ca801a22 | 26 | struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
668a6cc7 | 27 | |
ca801a22 | 28 | int ret, val; |
668a6cc7 | 29 | |
ca801a22 AD |
30 | ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); |
31 | if (ret) | |
32 | return ret; | |
668a6cc7 | 33 | |
ca801a22 | 34 | if (val & GPIO_CFG_MASK) |
e42615ec | 35 | return GPIO_LINE_DIRECTION_OUT; |
ca801a22 | 36 | else |
e42615ec | 37 | return GPIO_LINE_DIRECTION_IN; |
668a6cc7 MO |
38 | } |
39 | ||
ca801a22 | 40 | static int tps65912_gpio_direction_input(struct gpio_chip *gc, unsigned offset) |
668a6cc7 | 41 | { |
ca801a22 | 42 | struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
668a6cc7 | 43 | |
ca801a22 AD |
44 | return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, |
45 | GPIO_CFG_MASK, 0); | |
668a6cc7 MO |
46 | } |
47 | ||
ca801a22 AD |
48 | static int tps65912_gpio_direction_output(struct gpio_chip *gc, |
49 | unsigned offset, int value) | |
668a6cc7 | 50 | { |
ca801a22 | 51 | struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
668a6cc7 MO |
52 | |
53 | /* Set the initial value */ | |
ca801a22 AD |
54 | regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, |
55 | GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); | |
668a6cc7 | 56 | |
ca801a22 AD |
57 | return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, |
58 | GPIO_CFG_MASK, GPIO_CFG_MASK); | |
668a6cc7 MO |
59 | } |
60 | ||
ca801a22 | 61 | static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) |
668a6cc7 | 62 | { |
ca801a22 AD |
63 | struct tps65912_gpio *gpio = gpiochip_get_data(gc); |
64 | int ret, val; | |
65 | ||
66 | ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); | |
67 | if (ret) | |
68 | return ret; | |
668a6cc7 | 69 | |
ca801a22 AD |
70 | if (val & GPIO_STS_MASK) |
71 | return 1; | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, | |
77 | int value) | |
78 | { | |
79 | struct tps65912_gpio *gpio = gpiochip_get_data(gc); | |
80 | ||
81 | regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, | |
82 | GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); | |
668a6cc7 MO |
83 | } |
84 | ||
e35b5ab0 | 85 | static const struct gpio_chip template_chip = { |
ca801a22 | 86 | .label = "tps65912-gpio", |
668a6cc7 | 87 | .owner = THIS_MODULE, |
ca801a22 AD |
88 | .get_direction = tps65912_gpio_get_direction, |
89 | .direction_input = tps65912_gpio_direction_input, | |
90 | .direction_output = tps65912_gpio_direction_output, | |
668a6cc7 MO |
91 | .get = tps65912_gpio_get, |
92 | .set = tps65912_gpio_set, | |
668a6cc7 | 93 | .base = -1, |
ca801a22 AD |
94 | .ngpio = 5, |
95 | .can_sleep = true, | |
668a6cc7 MO |
96 | }; |
97 | ||
3836309d | 98 | static int tps65912_gpio_probe(struct platform_device *pdev) |
668a6cc7 | 99 | { |
ca801a22 AD |
100 | struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); |
101 | struct tps65912_gpio *gpio; | |
668a6cc7 | 102 | |
ca801a22 AD |
103 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); |
104 | if (!gpio) | |
668a6cc7 MO |
105 | return -ENOMEM; |
106 | ||
ca801a22 AD |
107 | gpio->tps = dev_get_drvdata(pdev->dev.parent); |
108 | gpio->gpio_chip = template_chip; | |
109 | gpio->gpio_chip.parent = tps->dev; | |
668a6cc7 | 110 | |
effe3781 | 111 | return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); |
668a6cc7 MO |
112 | } |
113 | ||
ca801a22 AD |
114 | static const struct platform_device_id tps65912_gpio_id_table[] = { |
115 | { "tps65912-gpio", }, | |
116 | { /* sentinel */ } | |
117 | }; | |
118 | MODULE_DEVICE_TABLE(platform, tps65912_gpio_id_table); | |
119 | ||
668a6cc7 MO |
120 | static struct platform_driver tps65912_gpio_driver = { |
121 | .driver = { | |
122 | .name = "tps65912-gpio", | |
668a6cc7 MO |
123 | }, |
124 | .probe = tps65912_gpio_probe, | |
ca801a22 | 125 | .id_table = tps65912_gpio_id_table, |
668a6cc7 | 126 | }; |
ca801a22 | 127 | module_platform_driver(tps65912_gpio_driver); |
668a6cc7 | 128 | |
ca801a22 AD |
129 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); |
130 | MODULE_DESCRIPTION("TPS65912 GPIO driver"); | |
668a6cc7 | 131 | MODULE_LICENSE("GPL v2"); |