xref: /linux/drivers/gpio/gpio-bd72720.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1*6b367741SMatti Vaittinen // SPDX-License-Identifier: GPL-2.0
2*6b367741SMatti Vaittinen /*
3*6b367741SMatti Vaittinen  * Support to GPIOs on ROHM BD72720 and BD79300
4*6b367741SMatti Vaittinen  * Copyright 2025 ROHM Semiconductors.
5*6b367741SMatti Vaittinen  * Author: Matti Vaittinen <mazziesaccount@gmail.com>
6*6b367741SMatti Vaittinen  */
7*6b367741SMatti Vaittinen 
8*6b367741SMatti Vaittinen #include <linux/gpio/driver.h>
9*6b367741SMatti Vaittinen #include <linux/init.h>
10*6b367741SMatti Vaittinen #include <linux/irq.h>
11*6b367741SMatti Vaittinen #include <linux/module.h>
12*6b367741SMatti Vaittinen #include <linux/of.h>
13*6b367741SMatti Vaittinen #include <linux/platform_device.h>
14*6b367741SMatti Vaittinen #include <linux/mfd/rohm-bd72720.h>
15*6b367741SMatti Vaittinen 
16*6b367741SMatti Vaittinen #define BD72720_GPIO_OPEN_DRAIN		0
17*6b367741SMatti Vaittinen #define BD72720_GPIO_CMOS		BIT(1)
18*6b367741SMatti Vaittinen #define BD72720_INT_GPIO1_IN_SRC	4
19*6b367741SMatti Vaittinen /*
20*6b367741SMatti Vaittinen  * The BD72720 has several "one time programmable" (OTP) configurations which
21*6b367741SMatti Vaittinen  * can be set at manufacturing phase. A set of these options allow using pins
22*6b367741SMatti Vaittinen  * as GPIO. The OTP configuration can't be read at run-time, so drivers rely on
23*6b367741SMatti Vaittinen  * device-tree to advertise the correct options.
24*6b367741SMatti Vaittinen  *
25*6b367741SMatti Vaittinen  * Both DVS[0,1] pins can be configured to be used for:
26*6b367741SMatti Vaittinen  *  - OTP0: regulator RUN state control
27*6b367741SMatti Vaittinen  *  - OTP1: GPI
28*6b367741SMatti Vaittinen  *  - OTP2: GPO
29*6b367741SMatti Vaittinen  *  - OTP3: Power sequencer output
30*6b367741SMatti Vaittinen  *  Data-sheet also states that these PINs can always be used for IRQ but the
31*6b367741SMatti Vaittinen  *  driver limits this by allowing them to be used for IRQs with OTP1 only.
32*6b367741SMatti Vaittinen  *
33*6b367741SMatti Vaittinen  * Pins GPIO_EXTEN0 (GPIO3), GPIO_EXTEN1 (GPIO4), GPIO_FAULT_B (GPIO5) have OTP
34*6b367741SMatti Vaittinen  * options for a specific (non GPIO) purposes, but also an option to configure
35*6b367741SMatti Vaittinen  * them to be used as a GPO.
36*6b367741SMatti Vaittinen  *
37*6b367741SMatti Vaittinen  * OTP settings can be separately configured for each pin.
38*6b367741SMatti Vaittinen  *
39*6b367741SMatti Vaittinen  * DT properties:
40*6b367741SMatti Vaittinen  * "rohm,pin-dvs0" and "rohm,pin-dvs1" can be set to one of the values:
41*6b367741SMatti Vaittinen  * "dvs-input", "gpi", "gpo".
42*6b367741SMatti Vaittinen  *
43*6b367741SMatti Vaittinen  * "rohm,pin-exten0", "rohm,pin-exten1" and "rohm,pin-fault_b" can be set to:
44*6b367741SMatti Vaittinen  * "gpo"
45*6b367741SMatti Vaittinen  */
46*6b367741SMatti Vaittinen 
47*6b367741SMatti Vaittinen enum bd72720_gpio_state {
48*6b367741SMatti Vaittinen 	BD72720_PIN_UNKNOWN,
49*6b367741SMatti Vaittinen 	BD72720_PIN_GPI,
50*6b367741SMatti Vaittinen 	BD72720_PIN_GPO,
51*6b367741SMatti Vaittinen };
52*6b367741SMatti Vaittinen 
53*6b367741SMatti Vaittinen enum {
54*6b367741SMatti Vaittinen 	BD72720_GPIO1,
55*6b367741SMatti Vaittinen 	BD72720_GPIO2,
56*6b367741SMatti Vaittinen 	BD72720_GPIO3,
57*6b367741SMatti Vaittinen 	BD72720_GPIO4,
58*6b367741SMatti Vaittinen 	BD72720_GPIO5,
59*6b367741SMatti Vaittinen 	BD72720_GPIO_EPDEN,
60*6b367741SMatti Vaittinen 	BD72720_NUM_GPIOS
61*6b367741SMatti Vaittinen };
62*6b367741SMatti Vaittinen 
63*6b367741SMatti Vaittinen struct bd72720_gpio {
64*6b367741SMatti Vaittinen 	/* chip.parent points the MFD which provides DT node and regmap */
65*6b367741SMatti Vaittinen 	struct gpio_chip chip;
66*6b367741SMatti Vaittinen 	/* dev points to the platform device for devm and prints */
67*6b367741SMatti Vaittinen 	struct device *dev;
68*6b367741SMatti Vaittinen 	struct regmap *regmap;
69*6b367741SMatti Vaittinen 	int gpio_is_input;
70*6b367741SMatti Vaittinen };
71*6b367741SMatti Vaittinen 
72*6b367741SMatti Vaittinen static int bd72720gpi_get(struct bd72720_gpio *bdgpio, unsigned int reg_offset)
73*6b367741SMatti Vaittinen {
74*6b367741SMatti Vaittinen 	int ret, val, shift;
75*6b367741SMatti Vaittinen 
76*6b367741SMatti Vaittinen 	ret = regmap_read(bdgpio->regmap, BD72720_REG_INT_ETC1_SRC, &val);
77*6b367741SMatti Vaittinen 	if (ret)
78*6b367741SMatti Vaittinen 		return ret;
79*6b367741SMatti Vaittinen 
80*6b367741SMatti Vaittinen 	shift = BD72720_INT_GPIO1_IN_SRC + reg_offset;
81*6b367741SMatti Vaittinen 
82*6b367741SMatti Vaittinen 	return (val >> shift) & 1;
83*6b367741SMatti Vaittinen }
84*6b367741SMatti Vaittinen 
85*6b367741SMatti Vaittinen static int bd72720gpo_get(struct bd72720_gpio *bdgpio,
86*6b367741SMatti Vaittinen 			  unsigned int offset)
87*6b367741SMatti Vaittinen {
88*6b367741SMatti Vaittinen 	const int regs[] = { BD72720_REG_GPIO1_CTRL, BD72720_REG_GPIO2_CTRL,
89*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO3_CTRL, BD72720_REG_GPIO4_CTRL,
90*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO5_CTRL, BD72720_REG_EPDEN_CTRL };
91*6b367741SMatti Vaittinen 	int ret, val;
92*6b367741SMatti Vaittinen 
93*6b367741SMatti Vaittinen 	ret = regmap_read(bdgpio->regmap, regs[offset], &val);
94*6b367741SMatti Vaittinen 	if (ret)
95*6b367741SMatti Vaittinen 		return ret;
96*6b367741SMatti Vaittinen 
97*6b367741SMatti Vaittinen 	return val & BD72720_GPIO_HIGH;
98*6b367741SMatti Vaittinen }
99*6b367741SMatti Vaittinen 
100*6b367741SMatti Vaittinen static int bd72720gpio_get(struct gpio_chip *chip, unsigned int offset)
101*6b367741SMatti Vaittinen {
102*6b367741SMatti Vaittinen 	struct bd72720_gpio *bdgpio = gpiochip_get_data(chip);
103*6b367741SMatti Vaittinen 
104*6b367741SMatti Vaittinen 	if (BIT(offset) & bdgpio->gpio_is_input)
105*6b367741SMatti Vaittinen 		return bd72720gpi_get(bdgpio, offset);
106*6b367741SMatti Vaittinen 
107*6b367741SMatti Vaittinen 	return bd72720gpo_get(bdgpio, offset);
108*6b367741SMatti Vaittinen }
109*6b367741SMatti Vaittinen 
110*6b367741SMatti Vaittinen static int bd72720gpo_set(struct gpio_chip *chip, unsigned int offset,
111*6b367741SMatti Vaittinen 			  int value)
112*6b367741SMatti Vaittinen {
113*6b367741SMatti Vaittinen 	struct bd72720_gpio *bdgpio = gpiochip_get_data(chip);
114*6b367741SMatti Vaittinen 	const int regs[] = { BD72720_REG_GPIO1_CTRL, BD72720_REG_GPIO2_CTRL,
115*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO3_CTRL, BD72720_REG_GPIO4_CTRL,
116*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO5_CTRL, BD72720_REG_EPDEN_CTRL };
117*6b367741SMatti Vaittinen 
118*6b367741SMatti Vaittinen 	if (BIT(offset) & bdgpio->gpio_is_input) {
119*6b367741SMatti Vaittinen 		dev_dbg(bdgpio->dev, "pin %d not output.\n", offset);
120*6b367741SMatti Vaittinen 		return -EINVAL;
121*6b367741SMatti Vaittinen 	}
122*6b367741SMatti Vaittinen 
123*6b367741SMatti Vaittinen 	if (value)
124*6b367741SMatti Vaittinen 		return regmap_set_bits(bdgpio->regmap, regs[offset],
125*6b367741SMatti Vaittinen 				      BD72720_GPIO_HIGH);
126*6b367741SMatti Vaittinen 
127*6b367741SMatti Vaittinen 	return regmap_clear_bits(bdgpio->regmap, regs[offset],
128*6b367741SMatti Vaittinen 					BD72720_GPIO_HIGH);
129*6b367741SMatti Vaittinen }
130*6b367741SMatti Vaittinen 
131*6b367741SMatti Vaittinen static int bd72720_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
132*6b367741SMatti Vaittinen 				   unsigned long config)
133*6b367741SMatti Vaittinen {
134*6b367741SMatti Vaittinen 	struct bd72720_gpio *bdgpio = gpiochip_get_data(chip);
135*6b367741SMatti Vaittinen 	const int regs[] = { BD72720_REG_GPIO1_CTRL, BD72720_REG_GPIO2_CTRL,
136*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO3_CTRL, BD72720_REG_GPIO4_CTRL,
137*6b367741SMatti Vaittinen 			     BD72720_REG_GPIO5_CTRL, BD72720_REG_EPDEN_CTRL };
138*6b367741SMatti Vaittinen 
139*6b367741SMatti Vaittinen 	/*
140*6b367741SMatti Vaittinen 	 * We can only set the output mode, which makes sense only when output
141*6b367741SMatti Vaittinen 	 * OTP configuration is used.
142*6b367741SMatti Vaittinen 	 */
143*6b367741SMatti Vaittinen 	if (BIT(offset) & bdgpio->gpio_is_input)
144*6b367741SMatti Vaittinen 		return -ENOTSUPP;
145*6b367741SMatti Vaittinen 
146*6b367741SMatti Vaittinen 	switch (pinconf_to_config_param(config)) {
147*6b367741SMatti Vaittinen 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
148*6b367741SMatti Vaittinen 		return regmap_update_bits(bdgpio->regmap,
149*6b367741SMatti Vaittinen 					  regs[offset],
150*6b367741SMatti Vaittinen 					  BD72720_GPIO_DRIVE_MASK,
151*6b367741SMatti Vaittinen 					  BD72720_GPIO_OPEN_DRAIN);
152*6b367741SMatti Vaittinen 	case PIN_CONFIG_DRIVE_PUSH_PULL:
153*6b367741SMatti Vaittinen 		return regmap_update_bits(bdgpio->regmap,
154*6b367741SMatti Vaittinen 					  regs[offset],
155*6b367741SMatti Vaittinen 					  BD72720_GPIO_DRIVE_MASK,
156*6b367741SMatti Vaittinen 					  BD72720_GPIO_CMOS);
157*6b367741SMatti Vaittinen 	default:
158*6b367741SMatti Vaittinen 		break;
159*6b367741SMatti Vaittinen 	}
160*6b367741SMatti Vaittinen 
161*6b367741SMatti Vaittinen 	return -ENOTSUPP;
162*6b367741SMatti Vaittinen }
163*6b367741SMatti Vaittinen 
164*6b367741SMatti Vaittinen static int bd72720gpo_direction_get(struct gpio_chip *chip,
165*6b367741SMatti Vaittinen 				    unsigned int offset)
166*6b367741SMatti Vaittinen {
167*6b367741SMatti Vaittinen 	struct bd72720_gpio *bdgpio = gpiochip_get_data(chip);
168*6b367741SMatti Vaittinen 
169*6b367741SMatti Vaittinen 	if (BIT(offset) & bdgpio->gpio_is_input)
170*6b367741SMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
171*6b367741SMatti Vaittinen 
172*6b367741SMatti Vaittinen 	return GPIO_LINE_DIRECTION_OUT;
173*6b367741SMatti Vaittinen }
174*6b367741SMatti Vaittinen 
175*6b367741SMatti Vaittinen static int bd72720_valid_mask(struct gpio_chip *gc,
176*6b367741SMatti Vaittinen 			      unsigned long *valid_mask,
177*6b367741SMatti Vaittinen 			      unsigned int ngpios)
178*6b367741SMatti Vaittinen {
179*6b367741SMatti Vaittinen 	static const char * const properties[] = {
180*6b367741SMatti Vaittinen 		"rohm,pin-dvs0", "rohm,pin-dvs1", "rohm,pin-exten0",
181*6b367741SMatti Vaittinen 		"rohm,pin-exten1", "rohm,pin-fault_b"
182*6b367741SMatti Vaittinen 	};
183*6b367741SMatti Vaittinen 	struct bd72720_gpio *g = gpiochip_get_data(gc);
184*6b367741SMatti Vaittinen 	const char *val;
185*6b367741SMatti Vaittinen 	int i, ret;
186*6b367741SMatti Vaittinen 
187*6b367741SMatti Vaittinen 	*valid_mask = BIT(BD72720_GPIO_EPDEN);
188*6b367741SMatti Vaittinen 
189*6b367741SMatti Vaittinen 	if (!gc->parent)
190*6b367741SMatti Vaittinen 		return 0;
191*6b367741SMatti Vaittinen 
192*6b367741SMatti Vaittinen 	for (i = 0; i < ARRAY_SIZE(properties); i++) {
193*6b367741SMatti Vaittinen 		ret = fwnode_property_read_string(dev_fwnode(gc->parent),
194*6b367741SMatti Vaittinen 						  properties[i], &val);
195*6b367741SMatti Vaittinen 
196*6b367741SMatti Vaittinen 		if (ret) {
197*6b367741SMatti Vaittinen 			if (ret == -EINVAL)
198*6b367741SMatti Vaittinen 				continue;
199*6b367741SMatti Vaittinen 
200*6b367741SMatti Vaittinen 			dev_err(g->dev, "pin %d (%s), bad configuration\n", i,
201*6b367741SMatti Vaittinen 				properties[i]);
202*6b367741SMatti Vaittinen 
203*6b367741SMatti Vaittinen 			return ret;
204*6b367741SMatti Vaittinen 		}
205*6b367741SMatti Vaittinen 
206*6b367741SMatti Vaittinen 		if (strcmp(val, "gpi") == 0) {
207*6b367741SMatti Vaittinen 			if (i != BD72720_GPIO1 && i != BD72720_GPIO2) {
208*6b367741SMatti Vaittinen 				dev_warn(g->dev,
209*6b367741SMatti Vaittinen 					 "pin %d (%s) does not support INPUT mode",
210*6b367741SMatti Vaittinen 					 i, properties[i]);
211*6b367741SMatti Vaittinen 				continue;
212*6b367741SMatti Vaittinen 			}
213*6b367741SMatti Vaittinen 
214*6b367741SMatti Vaittinen 			*valid_mask |= BIT(i);
215*6b367741SMatti Vaittinen 			g->gpio_is_input |= BIT(i);
216*6b367741SMatti Vaittinen 		} else if (strcmp(val, "gpo") == 0) {
217*6b367741SMatti Vaittinen 			*valid_mask |= BIT(i);
218*6b367741SMatti Vaittinen 		}
219*6b367741SMatti Vaittinen 	}
220*6b367741SMatti Vaittinen 
221*6b367741SMatti Vaittinen 	return 0;
222*6b367741SMatti Vaittinen }
223*6b367741SMatti Vaittinen 
224*6b367741SMatti Vaittinen /* Template for GPIO chip */
225*6b367741SMatti Vaittinen static const struct gpio_chip bd72720gpo_chip = {
226*6b367741SMatti Vaittinen 	.label			= "bd72720",
227*6b367741SMatti Vaittinen 	.owner			= THIS_MODULE,
228*6b367741SMatti Vaittinen 	.get			= bd72720gpio_get,
229*6b367741SMatti Vaittinen 	.get_direction		= bd72720gpo_direction_get,
230*6b367741SMatti Vaittinen 	.set			= bd72720gpo_set,
231*6b367741SMatti Vaittinen 	.set_config		= bd72720_gpio_set_config,
232*6b367741SMatti Vaittinen 	.init_valid_mask	= bd72720_valid_mask,
233*6b367741SMatti Vaittinen 	.can_sleep		= true,
234*6b367741SMatti Vaittinen 	.ngpio			= BD72720_NUM_GPIOS,
235*6b367741SMatti Vaittinen 	.base			= -1,
236*6b367741SMatti Vaittinen };
237*6b367741SMatti Vaittinen 
238*6b367741SMatti Vaittinen static int gpo_bd72720_probe(struct platform_device *pdev)
239*6b367741SMatti Vaittinen {
240*6b367741SMatti Vaittinen 	struct bd72720_gpio *g;
241*6b367741SMatti Vaittinen 	struct device *parent, *dev;
242*6b367741SMatti Vaittinen 
243*6b367741SMatti Vaittinen 	/*
244*6b367741SMatti Vaittinen 	 * Bind devm lifetime to this platform device => use dev for devm.
245*6b367741SMatti Vaittinen 	 * also the prints should originate from this device.
246*6b367741SMatti Vaittinen 	 */
247*6b367741SMatti Vaittinen 	dev = &pdev->dev;
248*6b367741SMatti Vaittinen 	/* The device-tree and regmap come from MFD => use parent for that */
249*6b367741SMatti Vaittinen 	parent = dev->parent;
250*6b367741SMatti Vaittinen 
251*6b367741SMatti Vaittinen 	g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
252*6b367741SMatti Vaittinen 	if (!g)
253*6b367741SMatti Vaittinen 		return -ENOMEM;
254*6b367741SMatti Vaittinen 
255*6b367741SMatti Vaittinen 	g->chip = bd72720gpo_chip;
256*6b367741SMatti Vaittinen 	g->dev = dev;
257*6b367741SMatti Vaittinen 	g->chip.parent = parent;
258*6b367741SMatti Vaittinen 	g->regmap = dev_get_regmap(parent, NULL);
259*6b367741SMatti Vaittinen 
260*6b367741SMatti Vaittinen 	return devm_gpiochip_add_data(dev, &g->chip, g);
261*6b367741SMatti Vaittinen }
262*6b367741SMatti Vaittinen 
263*6b367741SMatti Vaittinen static const struct platform_device_id bd72720_gpio_id[] = {
264*6b367741SMatti Vaittinen 	{ "bd72720-gpio" },
265*6b367741SMatti Vaittinen 	{ },
266*6b367741SMatti Vaittinen };
267*6b367741SMatti Vaittinen MODULE_DEVICE_TABLE(platform, bd72720_gpio_id);
268*6b367741SMatti Vaittinen 
269*6b367741SMatti Vaittinen static struct platform_driver gpo_bd72720_driver = {
270*6b367741SMatti Vaittinen 	.driver = {
271*6b367741SMatti Vaittinen 		.name = "bd72720-gpio",
272*6b367741SMatti Vaittinen 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
273*6b367741SMatti Vaittinen 	},
274*6b367741SMatti Vaittinen 	.probe = gpo_bd72720_probe,
275*6b367741SMatti Vaittinen 	.id_table = bd72720_gpio_id,
276*6b367741SMatti Vaittinen };
277*6b367741SMatti Vaittinen module_platform_driver(gpo_bd72720_driver);
278*6b367741SMatti Vaittinen 
279*6b367741SMatti Vaittinen MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
280*6b367741SMatti Vaittinen MODULE_DESCRIPTION("GPIO interface for BD72720 and BD73900");
281*6b367741SMatti Vaittinen MODULE_LICENSE("GPL");
282