1 // SPDX-License-Identifier: GPL-2.0
3 * GPIO driver for TI TPS65219 PMICs
5 * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
8 #include <linux/bits.h>
9 #include <linux/gpio/driver.h>
10 #include <linux/mfd/tps65219.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
15 #define TPS65219_GPIO0_DIR_MASK BIT(3)
16 #define TPS65219_GPIO0_OFFSET 2
17 #define TPS65219_GPIO0_IDX 0
18 #define TPS65219_GPIO_DIR_IN 1
19 #define TPS65219_GPIO_DIR_OUT 0
21 struct tps65219_gpio
{
22 struct gpio_chip gpio_chip
;
26 static int tps65219_gpio_get_direction(struct gpio_chip
*gc
, unsigned int offset
)
28 struct tps65219_gpio
*gpio
= gpiochip_get_data(gc
);
31 if (offset
!= TPS65219_GPIO0_IDX
)
32 return GPIO_LINE_DIRECTION_OUT
;
34 ret
= regmap_read(gpio
->tps
->regmap
, TPS65219_REG_MFP_1_CONFIG
, &val
);
38 return !!(val
& TPS65219_GPIO0_DIR_MASK
);
41 static int tps65219_gpio_get(struct gpio_chip
*gc
, unsigned int offset
)
43 struct tps65219_gpio
*gpio
= gpiochip_get_data(gc
);
44 struct device
*dev
= gpio
->tps
->dev
;
47 if (offset
!= TPS65219_GPIO0_IDX
) {
48 dev_err(dev
, "GPIO%d is output only, cannot get\n", offset
);
52 ret
= regmap_read(gpio
->tps
->regmap
, TPS65219_REG_MFP_CTRL
, &val
);
56 ret
= !!(val
& BIT(TPS65219_MFP_GPIO_STATUS_MASK
));
57 dev_warn(dev
, "GPIO%d = %d, MULTI_DEVICE_ENABLE, not a standard GPIO\n", offset
, ret
);
60 * Depending on NVM config, return an error if direction is output, otherwise the GPIO0
64 if (tps65219_gpio_get_direction(gc
, offset
) == TPS65219_GPIO_DIR_OUT
)
70 static void tps65219_gpio_set(struct gpio_chip
*gc
, unsigned int offset
, int value
)
72 struct tps65219_gpio
*gpio
= gpiochip_get_data(gc
);
73 struct device
*dev
= gpio
->tps
->dev
;
76 bit
= (offset
== TPS65219_GPIO0_IDX
) ? TPS65219_GPIO0_OFFSET
: offset
- 1;
81 if (regmap_update_bits(gpio
->tps
->regmap
, TPS65219_REG_GENERAL_CONFIG
, mask
, v
))
82 dev_err(dev
, "GPIO%d, set to value %d failed.\n", offset
, value
);
85 static int tps65219_gpio_change_direction(struct gpio_chip
*gc
, unsigned int offset
,
86 unsigned int direction
)
88 struct tps65219_gpio
*gpio
= gpiochip_get_data(gc
);
89 struct device
*dev
= gpio
->tps
->dev
;
92 * Documentation is stating that GPIO0 direction must not be changed in Linux:
93 * Table 8-34. MFP_1_CONFIG(3): MULTI_DEVICE_ENABLE, should only be changed in INITIALIZE
94 * state (prior to ON Request).
95 * Set statically by NVM, changing direction in application can cause a hang.
96 * Below can be used for test purpose only.
100 int ret
= regmap_update_bits(gpio
->tps
->regmap
, TPS65219_REG_MFP_1_CONFIG
,
101 TPS65219_GPIO0_DIR_MASK
, direction
);
104 "GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n",
111 "GPIO%d direction set by NVM, change to %u failed, not allowed by specification\n",
117 static int tps65219_gpio_direction_input(struct gpio_chip
*gc
, unsigned int offset
)
119 struct tps65219_gpio
*gpio
= gpiochip_get_data(gc
);
120 struct device
*dev
= gpio
->tps
->dev
;
122 if (offset
!= TPS65219_GPIO0_IDX
) {
123 dev_err(dev
, "GPIO%d is output only, cannot change to input\n", offset
);
127 if (tps65219_gpio_get_direction(gc
, offset
) == TPS65219_GPIO_DIR_IN
)
130 return tps65219_gpio_change_direction(gc
, offset
, TPS65219_GPIO_DIR_IN
);
133 static int tps65219_gpio_direction_output(struct gpio_chip
*gc
, unsigned int offset
, int value
)
135 tps65219_gpio_set(gc
, offset
, value
);
136 if (offset
!= TPS65219_GPIO0_IDX
)
139 if (tps65219_gpio_get_direction(gc
, offset
) == TPS65219_GPIO_DIR_OUT
)
142 return tps65219_gpio_change_direction(gc
, offset
, TPS65219_GPIO_DIR_OUT
);
145 static const struct gpio_chip tps65219_template_chip
= {
146 .label
= "tps65219-gpio",
147 .owner
= THIS_MODULE
,
148 .get_direction
= tps65219_gpio_get_direction
,
149 .direction_input
= tps65219_gpio_direction_input
,
150 .direction_output
= tps65219_gpio_direction_output
,
151 .get
= tps65219_gpio_get
,
152 .set
= tps65219_gpio_set
,
158 static int tps65219_gpio_probe(struct platform_device
*pdev
)
160 struct tps65219
*tps
= dev_get_drvdata(pdev
->dev
.parent
);
161 struct tps65219_gpio
*gpio
;
163 gpio
= devm_kzalloc(&pdev
->dev
, sizeof(*gpio
), GFP_KERNEL
);
168 gpio
->gpio_chip
= tps65219_template_chip
;
169 gpio
->gpio_chip
.parent
= tps
->dev
;
171 return devm_gpiochip_add_data(&pdev
->dev
, &gpio
->gpio_chip
, gpio
);
174 static struct platform_driver tps65219_gpio_driver
= {
176 .name
= "tps65219-gpio",
178 .probe
= tps65219_gpio_probe
,
180 module_platform_driver(tps65219_gpio_driver
);
182 MODULE_ALIAS("platform:tps65219-gpio");
183 MODULE_AUTHOR("Jonathan Cormier <jcormier@criticallink.com>");
184 MODULE_DESCRIPTION("TPS65219 GPIO driver");
185 MODULE_LICENSE("GPL");