1 // SPDX-License-Identifier: GPL-2.0
3 * Dialog DA9062 pinctrl and GPIO driver.
4 * Based on DA9055 GPIO driver.
7 * - add pinmux and pinctrl support (gpio alternate mode)
10 * [1] https://www.dialog-semiconductor.com/sites/default/files/da9062_datasheet_3v6.pdf
12 * Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de>
14 #include <linux/bits.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
18 #include <linux/regmap.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/gpio/driver.h>
23 #include <linux/mfd/da9062/core.h>
24 #include <linux/mfd/da9062/registers.h>
26 #define DA9062_TYPE(offset) (4 * (offset % 2))
27 #define DA9062_PIN_SHIFT(offset) (4 * (offset % 2))
28 #define DA9062_PIN_ALTERNATE 0x00 /* gpio alternate mode */
29 #define DA9062_PIN_GPI 0x01 /* gpio in */
30 #define DA9062_PIN_GPO_OD 0x02 /* gpio out open-drain */
31 #define DA9062_PIN_GPO_PP 0x03 /* gpio out push-pull */
32 #define DA9062_GPIO_NUM 5
35 struct da9062
*da9062
;
37 unsigned int pin_config
[DA9062_GPIO_NUM
];
40 static int da9062_pctl_get_pin_mode(struct da9062_pctl
*pctl
,
43 struct regmap
*regmap
= pctl
->da9062
->regmap
;
46 ret
= regmap_read(regmap
, DA9062AA_GPIO_0_1
+ (offset
>> 1), &val
);
50 val
>>= DA9062_PIN_SHIFT(offset
);
51 val
&= DA9062AA_GPIO0_PIN_MASK
;
56 static int da9062_pctl_set_pin_mode(struct da9062_pctl
*pctl
,
57 unsigned int offset
, unsigned int mode_req
)
59 struct regmap
*regmap
= pctl
->da9062
->regmap
;
60 unsigned int mode
= mode_req
;
64 mode
&= DA9062AA_GPIO0_PIN_MASK
;
65 mode
<<= DA9062_PIN_SHIFT(offset
);
66 mask
= DA9062AA_GPIO0_PIN_MASK
<< DA9062_PIN_SHIFT(offset
);
68 ret
= regmap_update_bits(regmap
, DA9062AA_GPIO_0_1
+ (offset
>> 1),
71 pctl
->pin_config
[offset
] = mode_req
;
76 static int da9062_gpio_get(struct gpio_chip
*gc
, unsigned int offset
)
78 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
79 struct regmap
*regmap
= pctl
->da9062
->regmap
;
83 gpio_mode
= da9062_pctl_get_pin_mode(pctl
, offset
);
88 case DA9062_PIN_ALTERNATE
:
91 ret
= regmap_read(regmap
, DA9062AA_STATUS_B
, &val
);
95 case DA9062_PIN_GPO_OD
:
96 case DA9062_PIN_GPO_PP
:
97 ret
= regmap_read(regmap
, DA9062AA_GPIO_MODE0_4
, &val
);
102 return !!(val
& BIT(offset
));
105 static void da9062_gpio_set(struct gpio_chip
*gc
, unsigned int offset
,
108 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
109 struct regmap
*regmap
= pctl
->da9062
->regmap
;
111 regmap_update_bits(regmap
, DA9062AA_GPIO_MODE0_4
, BIT(offset
),
115 static int da9062_gpio_get_direction(struct gpio_chip
*gc
, unsigned int offset
)
117 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
120 gpio_mode
= da9062_pctl_get_pin_mode(pctl
, offset
);
125 case DA9062_PIN_ALTERNATE
:
128 return GPIO_LINE_DIRECTION_IN
;
129 case DA9062_PIN_GPO_OD
:
130 case DA9062_PIN_GPO_PP
:
131 return GPIO_LINE_DIRECTION_OUT
;
137 static int da9062_gpio_direction_input(struct gpio_chip
*gc
,
140 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
141 struct regmap
*regmap
= pctl
->da9062
->regmap
;
142 struct gpio_desc
*desc
= gpio_device_get_desc(gc
->gpiodev
, offset
);
143 unsigned int gpi_type
;
146 ret
= da9062_pctl_set_pin_mode(pctl
, offset
, DA9062_PIN_GPI
);
151 * If the gpio is active low we should set it in hw too. No worries
152 * about gpio_get() because we read and return the gpio-level. So the
153 * gpiolib active_low handling is still correct.
155 * 0 - active low, 1 - active high
157 gpi_type
= !gpiod_is_active_low(desc
);
159 return regmap_update_bits(regmap
, DA9062AA_GPIO_0_1
+ (offset
>> 1),
160 DA9062AA_GPIO0_TYPE_MASK
<< DA9062_TYPE(offset
),
161 gpi_type
<< DA9062_TYPE(offset
));
164 static int da9062_gpio_direction_output(struct gpio_chip
*gc
,
165 unsigned int offset
, int value
)
167 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
168 unsigned int pin_config
= pctl
->pin_config
[offset
];
171 ret
= da9062_pctl_set_pin_mode(pctl
, offset
, pin_config
);
175 da9062_gpio_set(gc
, offset
, value
);
180 static int da9062_gpio_set_config(struct gpio_chip
*gc
, unsigned int offset
,
181 unsigned long config
)
183 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
184 struct regmap
*regmap
= pctl
->da9062
->regmap
;
188 * We need to meet the following restrictions [1, Figure 18]:
189 * - PIN_CONFIG_BIAS_PULL_DOWN -> only allowed if the pin is used as
191 * - PIN_CONFIG_BIAS_PULL_UP -> only allowed if the pin is used as
192 * gpio output open-drain.
195 switch (pinconf_to_config_param(config
)) {
196 case PIN_CONFIG_BIAS_DISABLE
:
197 return regmap_update_bits(regmap
, DA9062AA_CONFIG_K
,
199 case PIN_CONFIG_BIAS_PULL_DOWN
:
200 gpio_mode
= da9062_pctl_get_pin_mode(pctl
, offset
);
203 else if (gpio_mode
!= DA9062_PIN_GPI
)
205 return regmap_update_bits(regmap
, DA9062AA_CONFIG_K
,
206 BIT(offset
), BIT(offset
));
207 case PIN_CONFIG_BIAS_PULL_UP
:
208 gpio_mode
= da9062_pctl_get_pin_mode(pctl
, offset
);
211 else if (gpio_mode
!= DA9062_PIN_GPO_OD
)
213 return regmap_update_bits(regmap
, DA9062AA_CONFIG_K
,
214 BIT(offset
), BIT(offset
));
215 case PIN_CONFIG_DRIVE_OPEN_DRAIN
:
216 return da9062_pctl_set_pin_mode(pctl
, offset
,
218 case PIN_CONFIG_DRIVE_PUSH_PULL
:
219 return da9062_pctl_set_pin_mode(pctl
, offset
,
226 static int da9062_gpio_to_irq(struct gpio_chip
*gc
, unsigned int offset
)
228 struct da9062_pctl
*pctl
= gpiochip_get_data(gc
);
229 struct da9062
*da9062
= pctl
->da9062
;
231 return regmap_irq_get_virq(da9062
->regmap_irq
,
232 DA9062_IRQ_GPI0
+ offset
);
235 static const struct gpio_chip reference_gc
= {
236 .owner
= THIS_MODULE
,
237 .get
= da9062_gpio_get
,
238 .set
= da9062_gpio_set
,
239 .get_direction
= da9062_gpio_get_direction
,
240 .direction_input
= da9062_gpio_direction_input
,
241 .direction_output
= da9062_gpio_direction_output
,
242 .set_config
= da9062_gpio_set_config
,
243 .to_irq
= da9062_gpio_to_irq
,
245 .ngpio
= DA9062_GPIO_NUM
,
249 static int da9062_pctl_probe(struct platform_device
*pdev
)
251 struct device
*parent
= pdev
->dev
.parent
;
252 struct da9062_pctl
*pctl
;
255 device_set_node(&pdev
->dev
, dev_fwnode(pdev
->dev
.parent
));
257 pctl
= devm_kzalloc(&pdev
->dev
, sizeof(*pctl
), GFP_KERNEL
);
261 pctl
->da9062
= dev_get_drvdata(parent
);
265 if (!device_property_present(parent
, "gpio-controller"))
268 for (i
= 0; i
< ARRAY_SIZE(pctl
->pin_config
); i
++)
269 pctl
->pin_config
[i
] = DA9062_PIN_GPO_PP
;
272 * Currently the driver handles only the GPIO support. The
273 * pinctrl/pinmux support can be added later if needed.
275 pctl
->gc
= reference_gc
;
276 pctl
->gc
.label
= dev_name(&pdev
->dev
);
277 pctl
->gc
.parent
= &pdev
->dev
;
279 platform_set_drvdata(pdev
, pctl
);
281 return devm_gpiochip_add_data(&pdev
->dev
, &pctl
->gc
, pctl
);
284 static const struct of_device_id da9062_compatible_reg_id_table
[] = {
285 { .compatible
= "dlg,da9062-gpio" },
288 MODULE_DEVICE_TABLE(of
, da9062_compatible_reg_id_table
);
290 static struct platform_driver da9062_pctl_driver
= {
291 .probe
= da9062_pctl_probe
,
293 .name
= "da9062-gpio",
294 .of_match_table
= da9062_compatible_reg_id_table
,
297 module_platform_driver(da9062_pctl_driver
);
299 MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>");
300 MODULE_DESCRIPTION("DA9062 PMIC pinctrl and GPIO Driver");
301 MODULE_LICENSE("GPL v2");
302 MODULE_ALIAS("platform:da9062-gpio");