1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for PCA9570 I2C GPO expander
5 * Copyright (C) 2020 Sungbo Eo <mans0n@gorani.run>
7 * Based on gpio-tpic2810.c
8 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
9 * Andrew F. Davis <afd@ti.com>
12 #include <linux/gpio/driver.h>
13 #include <linux/i2c.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/property.h>
18 #define SLG7XL45106_GPO_REG 0xDB
21 * struct pca9570_chip_data - GPIO platformdata
23 * @command: Command to be sent
25 struct pca9570_chip_data
{
31 * struct pca9570 - GPIO driver data
32 * @chip: GPIO controller chip
33 * @chip_data: GPIO controller platform data
34 * @lock: Protects write sequences
35 * @out: Buffer for device register
38 struct gpio_chip chip
;
39 const struct pca9570_chip_data
*chip_data
;
44 static int pca9570_read(struct pca9570
*gpio
, u8
*value
)
46 struct i2c_client
*client
= to_i2c_client(gpio
->chip
.parent
);
49 if (gpio
->chip_data
->command
!= 0)
50 ret
= i2c_smbus_read_byte_data(client
, gpio
->chip_data
->command
);
52 ret
= i2c_smbus_read_byte(client
);
61 static int pca9570_write(struct pca9570
*gpio
, u8 value
)
63 struct i2c_client
*client
= to_i2c_client(gpio
->chip
.parent
);
65 if (gpio
->chip_data
->command
!= 0)
66 return i2c_smbus_write_byte_data(client
, gpio
->chip_data
->command
, value
);
68 return i2c_smbus_write_byte(client
, value
);
71 static int pca9570_get_direction(struct gpio_chip
*chip
,
74 /* This device always output */
75 return GPIO_LINE_DIRECTION_OUT
;
78 static int pca9570_get(struct gpio_chip
*chip
, unsigned offset
)
80 struct pca9570
*gpio
= gpiochip_get_data(chip
);
84 ret
= pca9570_read(gpio
, &buffer
);
88 return !!(buffer
& BIT(offset
));
91 static void pca9570_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
93 struct pca9570
*gpio
= gpiochip_get_data(chip
);
97 mutex_lock(&gpio
->lock
);
101 buffer
|= BIT(offset
);
103 buffer
&= ~BIT(offset
);
105 ret
= pca9570_write(gpio
, buffer
);
112 mutex_unlock(&gpio
->lock
);
115 static int pca9570_probe(struct i2c_client
*client
)
117 struct pca9570
*gpio
;
119 gpio
= devm_kzalloc(&client
->dev
, sizeof(*gpio
), GFP_KERNEL
);
123 gpio
->chip
.label
= client
->name
;
124 gpio
->chip
.parent
= &client
->dev
;
125 gpio
->chip
.owner
= THIS_MODULE
;
126 gpio
->chip
.get_direction
= pca9570_get_direction
;
127 gpio
->chip
.get
= pca9570_get
;
128 gpio
->chip
.set
= pca9570_set
;
129 gpio
->chip
.base
= -1;
130 gpio
->chip_data
= device_get_match_data(&client
->dev
);
131 gpio
->chip
.ngpio
= gpio
->chip_data
->ngpio
;
132 gpio
->chip
.can_sleep
= true;
134 mutex_init(&gpio
->lock
);
136 /* Read the current output level */
137 pca9570_read(gpio
, &gpio
->out
);
139 i2c_set_clientdata(client
, gpio
);
141 return devm_gpiochip_add_data(&client
->dev
, &gpio
->chip
, gpio
);
144 static const struct pca9570_chip_data pca9570_gpio
= {
148 static const struct pca9570_chip_data pca9571_gpio
= {
152 static const struct pca9570_chip_data slg7xl45106_gpio
= {
154 .command
= SLG7XL45106_GPO_REG
,
157 static const struct i2c_device_id pca9570_id_table
[] = {
158 { "pca9570", (kernel_ulong_t
)&pca9570_gpio
},
159 { "pca9571", (kernel_ulong_t
)&pca9571_gpio
},
160 { "slg7xl45106", (kernel_ulong_t
)&slg7xl45106_gpio
},
163 MODULE_DEVICE_TABLE(i2c
, pca9570_id_table
);
165 static const struct of_device_id pca9570_of_match_table
[] = {
166 { .compatible
= "dlg,slg7xl45106", .data
= &slg7xl45106_gpio
},
167 { .compatible
= "nxp,pca9570", .data
= &pca9570_gpio
},
168 { .compatible
= "nxp,pca9571", .data
= &pca9571_gpio
},
171 MODULE_DEVICE_TABLE(of
, pca9570_of_match_table
);
173 static struct i2c_driver pca9570_driver
= {
176 .of_match_table
= pca9570_of_match_table
,
178 .probe
= pca9570_probe
,
179 .id_table
= pca9570_id_table
,
181 module_i2c_driver(pca9570_driver
);
183 MODULE_AUTHOR("Sungbo Eo <mans0n@gorani.run>");
184 MODULE_DESCRIPTION("GPIO expander driver for PCA9570");
185 MODULE_LICENSE("GPL v2");