Skip to content

Commit 4c82005

Browse files
author
Uwe Kleine-König
committed
Merge tag 'ib-mfd-gpio-pwm-v6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Immutable branch between MFD, GPIO and PWM due for the v6.12 merge window
2 parents a550d6a + e9b5038 commit 4c82005

File tree

13 files changed

+876
-4
lines changed

13 files changed

+876
-4
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/mfd/adi,adp5585.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Analog Devices ADP5585 Keypad Decoder and I/O Expansion
8+
9+
maintainers:
10+
- Laurent Pinchart <[email protected]>
11+
12+
description:
13+
The ADP5585 is a 10/11 input/output port expander with a built in keypad
14+
matrix decoder, programmable logic, reset generator, and PWM generator.
15+
16+
properties:
17+
compatible:
18+
items:
19+
- enum:
20+
- adi,adp5585-00 # Default
21+
- adi,adp5585-01 # 11 GPIOs
22+
- adi,adp5585-02 # No pull-up resistors by default on special pins
23+
- adi,adp5585-03 # Alternate I2C address
24+
- adi,adp5585-04 # Pull-down resistors on all pins by default
25+
- const: adi,adp5585
26+
27+
reg:
28+
maxItems: 1
29+
30+
interrupts:
31+
maxItems: 1
32+
33+
vdd-supply: true
34+
35+
gpio-controller: true
36+
37+
'#gpio-cells':
38+
const: 2
39+
40+
gpio-reserved-ranges: true
41+
42+
"#pwm-cells":
43+
const: 3
44+
45+
required:
46+
- compatible
47+
- reg
48+
- gpio-controller
49+
- "#gpio-cells"
50+
- "#pwm-cells"
51+
52+
allOf:
53+
- if:
54+
properties:
55+
compatible:
56+
contains:
57+
const: adi,adp5585-01
58+
then:
59+
properties:
60+
gpio-reserved-ranges: false
61+
else:
62+
properties:
63+
gpio-reserved-ranges:
64+
maxItems: 1
65+
items:
66+
items:
67+
- const: 5
68+
- const: 1
69+
70+
additionalProperties: false
71+
72+
examples:
73+
- |
74+
i2c {
75+
#address-cells = <1>;
76+
#size-cells = <0>;
77+
78+
io-expander@34 {
79+
compatible = "adi,adp5585-00", "adi,adp5585";
80+
reg = <0x34>;
81+
82+
vdd-supply = <&reg_3v3>;
83+
84+
gpio-controller;
85+
#gpio-cells = <2>;
86+
gpio-reserved-ranges = <5 1>;
87+
88+
#pwm-cells = <3>;
89+
};
90+
};
91+
92+
...

Documentation/devicetree/bindings/trivial-devices.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ properties:
3838
- ad,adm9240
3939
# AD5110 - Nonvolatile Digital Potentiometer
4040
- adi,ad5110
41-
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion
42-
- adi,adp5585
43-
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion with support for Row5
44-
- adi,adp5585-02
4541
# Analog Devices ADP5589 Keypad Decoder and I/O Expansion
4642
- adi,adp5589
4743
# Analog Devices LT7182S Dual Channel 6A, 20V PolyPhase Step-Down Silent Switcher

MAINTAINERS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,17 @@ F: drivers/leds/leds-adp5520.c
537537
F: drivers/mfd/adp5520.c
538538
F: drivers/video/backlight/adp5520_bl.c
539539

540+
ADP5585 GPIO EXPANDER, PWM AND KEYPAD CONTROLLER DRIVER
541+
M: Laurent Pinchart <[email protected]>
542+
543+
544+
S: Maintained
545+
F: Documentation/devicetree/bindings/*/adi,adp5585*.yaml
546+
F: drivers/gpio/gpio-adp5585.c
547+
F: drivers/mfd/adp5585.c
548+
F: drivers/pwm/pwm-adp5585.c
549+
F: include/linux/mfd/adp5585.h
550+
540551
ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
541552
M: Michael Hennerich <[email protected]>
542553
S: Supported

drivers/gpio/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,13 @@ config GPIO_ADP5520
12331233
This option enables support for on-chip GPIO found
12341234
on Analog Devices ADP5520 PMICs.
12351235

1236+
config GPIO_ADP5585
1237+
tristate "GPIO Support for ADP5585"
1238+
depends on MFD_ADP5585
1239+
help
1240+
This option enables support for the GPIO function found in the Analog
1241+
Devices ADP5585.
1242+
12361243
config GPIO_ALTERA_A10SR
12371244
tristate "Altera Arria10 System Resource GPIO"
12381245
depends on MFD_ALTERA_A10SR

drivers/gpio/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
2626
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
2727
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
2828
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
29+
obj-$(CONFIG_GPIO_ADP5585) += gpio-adp5585.o
2930
obj-$(CONFIG_GPIO_AGGREGATOR) += gpio-aggregator.o
3031
obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
3132
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o

drivers/gpio/gpio-adp5585.c

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Analog Devices ADP5585 GPIO driver
4+
*
5+
* Copyright 2022 NXP
6+
* Copyright 2024 Ideas on Board Oy
7+
*/
8+
9+
#include <linux/device.h>
10+
#include <linux/gpio/driver.h>
11+
#include <linux/mfd/adp5585.h>
12+
#include <linux/module.h>
13+
#include <linux/platform_device.h>
14+
#include <linux/regmap.h>
15+
#include <linux/types.h>
16+
17+
#define ADP5585_GPIO_MAX 11
18+
19+
struct adp5585_gpio_dev {
20+
struct gpio_chip gpio_chip;
21+
struct regmap *regmap;
22+
};
23+
24+
static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off)
25+
{
26+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
27+
unsigned int bank = ADP5585_BANK(off);
28+
unsigned int bit = ADP5585_BIT(off);
29+
unsigned int val;
30+
31+
regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
32+
33+
return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
34+
}
35+
36+
static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off)
37+
{
38+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
39+
unsigned int bank = ADP5585_BANK(off);
40+
unsigned int bit = ADP5585_BIT(off);
41+
42+
return regmap_clear_bits(adp5585_gpio->regmap,
43+
ADP5585_GPIO_DIRECTION_A + bank, bit);
44+
}
45+
46+
static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val)
47+
{
48+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
49+
unsigned int bank = ADP5585_BANK(off);
50+
unsigned int bit = ADP5585_BIT(off);
51+
int ret;
52+
53+
ret = regmap_update_bits(adp5585_gpio->regmap,
54+
ADP5585_GPO_DATA_OUT_A + bank, bit,
55+
val ? bit : 0);
56+
if (ret)
57+
return ret;
58+
59+
return regmap_set_bits(adp5585_gpio->regmap,
60+
ADP5585_GPIO_DIRECTION_A + bank, bit);
61+
}
62+
63+
static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off)
64+
{
65+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
66+
unsigned int bank = ADP5585_BANK(off);
67+
unsigned int bit = ADP5585_BIT(off);
68+
unsigned int reg;
69+
unsigned int val;
70+
71+
/*
72+
* The input status register doesn't reflect the pin state when the
73+
* GPIO is configured as an output. Check the direction, and read the
74+
* input status from GPI_STATUS or output value from GPO_DATA_OUT
75+
* accordingly.
76+
*
77+
* We don't need any locking, as concurrent access to the same GPIO
78+
* isn't allowed by the GPIO API, so there's no risk of the
79+
* .direction_input(), .direction_output() or .set() operations racing
80+
* with this.
81+
*/
82+
regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
83+
reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A;
84+
regmap_read(adp5585_gpio->regmap, reg + bank, &val);
85+
86+
return !!(val & bit);
87+
}
88+
89+
static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val)
90+
{
91+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
92+
unsigned int bank = ADP5585_BANK(off);
93+
unsigned int bit = ADP5585_BIT(off);
94+
95+
regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank,
96+
bit, val ? bit : 0);
97+
}
98+
99+
static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,
100+
unsigned int off, unsigned int bias)
101+
{
102+
unsigned int bit, reg, mask, val;
103+
104+
/*
105+
* The bias configuration fields are 2 bits wide and laid down in
106+
* consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits
107+
* after R5.
108+
*/
109+
bit = off * 2 + (off > 5 ? 4 : 0);
110+
reg = ADP5585_RPULL_CONFIG_A + bit / 8;
111+
mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8);
112+
val = bias << (bit % 8);
113+
114+
return regmap_update_bits(adp5585_gpio->regmap, reg, mask, val);
115+
}
116+
117+
static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio,
118+
unsigned int off, enum pin_config_param drive)
119+
{
120+
unsigned int bank = ADP5585_BANK(off);
121+
unsigned int bit = ADP5585_BIT(off);
122+
123+
return regmap_update_bits(adp5585_gpio->regmap,
124+
ADP5585_GPO_OUT_MODE_A + bank, bit,
125+
drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0);
126+
}
127+
128+
static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio,
129+
unsigned int off, unsigned int debounce)
130+
{
131+
unsigned int bank = ADP5585_BANK(off);
132+
unsigned int bit = ADP5585_BIT(off);
133+
134+
return regmap_update_bits(adp5585_gpio->regmap,
135+
ADP5585_DEBOUNCE_DIS_A + bank, bit,
136+
debounce ? 0 : bit);
137+
}
138+
139+
static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off,
140+
unsigned long config)
141+
{
142+
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
143+
enum pin_config_param param = pinconf_to_config_param(config);
144+
u32 arg = pinconf_to_config_argument(config);
145+
146+
switch (param) {
147+
case PIN_CONFIG_BIAS_DISABLE:
148+
return adp5585_gpio_set_bias(adp5585_gpio, off,
149+
ADP5585_Rx_PULL_CFG_DISABLE);
150+
151+
case PIN_CONFIG_BIAS_PULL_DOWN:
152+
return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
153+
ADP5585_Rx_PULL_CFG_PD_300K :
154+
ADP5585_Rx_PULL_CFG_DISABLE);
155+
156+
case PIN_CONFIG_BIAS_PULL_UP:
157+
return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
158+
ADP5585_Rx_PULL_CFG_PU_300K :
159+
ADP5585_Rx_PULL_CFG_DISABLE);
160+
161+
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
162+
case PIN_CONFIG_DRIVE_PUSH_PULL:
163+
return adp5585_gpio_set_drive(adp5585_gpio, off, param);
164+
165+
case PIN_CONFIG_INPUT_DEBOUNCE:
166+
return adp5585_gpio_set_debounce(adp5585_gpio, off, arg);
167+
168+
default:
169+
return -ENOTSUPP;
170+
};
171+
}
172+
173+
static int adp5585_gpio_probe(struct platform_device *pdev)
174+
{
175+
struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent);
176+
struct adp5585_gpio_dev *adp5585_gpio;
177+
struct device *dev = &pdev->dev;
178+
struct gpio_chip *gc;
179+
int ret;
180+
181+
adp5585_gpio = devm_kzalloc(dev, sizeof(*adp5585_gpio), GFP_KERNEL);
182+
if (!adp5585_gpio)
183+
return -ENOMEM;
184+
185+
adp5585_gpio->regmap = adp5585->regmap;
186+
187+
device_set_of_node_from_dev(dev, dev->parent);
188+
189+
gc = &adp5585_gpio->gpio_chip;
190+
gc->parent = dev;
191+
gc->get_direction = adp5585_gpio_get_direction;
192+
gc->direction_input = adp5585_gpio_direction_input;
193+
gc->direction_output = adp5585_gpio_direction_output;
194+
gc->get = adp5585_gpio_get_value;
195+
gc->set = adp5585_gpio_set_value;
196+
gc->set_config = adp5585_gpio_set_config;
197+
gc->can_sleep = true;
198+
199+
gc->base = -1;
200+
gc->ngpio = ADP5585_GPIO_MAX;
201+
gc->label = pdev->name;
202+
gc->owner = THIS_MODULE;
203+
204+
ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip,
205+
adp5585_gpio);
206+
if (ret)
207+
return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
208+
209+
return 0;
210+
}
211+
212+
static const struct platform_device_id adp5585_gpio_id_table[] = {
213+
{ "adp5585-gpio" },
214+
{ /* Sentinel */ }
215+
};
216+
MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table);
217+
218+
static struct platform_driver adp5585_gpio_driver = {
219+
.driver = {
220+
.name = "adp5585-gpio",
221+
},
222+
.probe = adp5585_gpio_probe,
223+
.id_table = adp5585_gpio_id_table,
224+
};
225+
module_platform_driver(adp5585_gpio_driver);
226+
227+
MODULE_AUTHOR("Haibo Chen <[email protected]>");
228+
MODULE_DESCRIPTION("GPIO ADP5585 Driver");
229+
MODULE_LICENSE("GPL");

drivers/mfd/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@ config MFD_CS5535
2020
This is the core driver for CS5535/CS5536 MFD functions. This is
2121
necessary for using the board's GPIO and MFGPT functionality.
2222

23+
config MFD_ADP5585
24+
tristate "Analog Devices ADP5585 keypad decoder and I/O expander driver"
25+
select MFD_CORE
26+
select REGMAP_I2C
27+
depends on I2C
28+
depends on OF || COMPILE_TEST
29+
help
30+
Say yes here to add support for the Analog Devices ADP5585 GPIO
31+
expander, PWM and keypad controller. This includes the I2C driver and
32+
the core APIs _only_, you have to select individual components like
33+
the GPIO and PWM functions under the corresponding menus.
34+
2335
config MFD_ALTERA_A10SR
2436
bool "Altera Arria10 DevKit System Resource chip"
2537
depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF

0 commit comments

Comments
 (0)