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