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>
19 * struct pca9570 - GPIO driver data
20 * @chip: GPIO controller chip
21 * @lock: Protects write sequences
22 * @out: Buffer for device register
25 struct gpio_chip chip
;
30 static int pca9570_read(struct pca9570
*gpio
, u8
*value
)
32 struct i2c_client
*client
= to_i2c_client(gpio
->chip
.parent
);
35 ret
= i2c_smbus_read_byte(client
);
43 static int pca9570_write(struct pca9570
*gpio
, u8 value
)
45 struct i2c_client
*client
= to_i2c_client(gpio
->chip
.parent
);
47 return i2c_smbus_write_byte(client
, value
);
50 static int pca9570_get_direction(struct gpio_chip
*chip
,
53 /* This device always output */
54 return GPIO_LINE_DIRECTION_OUT
;
57 static int pca9570_get(struct gpio_chip
*chip
, unsigned offset
)
59 struct pca9570
*gpio
= gpiochip_get_data(chip
);
63 ret
= pca9570_read(gpio
, &buffer
);
67 return !!(buffer
& BIT(offset
));
70 static void pca9570_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
72 struct pca9570
*gpio
= gpiochip_get_data(chip
);
76 mutex_lock(&gpio
->lock
);
80 buffer
|= BIT(offset
);
82 buffer
&= ~BIT(offset
);
84 ret
= pca9570_write(gpio
, buffer
);
91 mutex_unlock(&gpio
->lock
);
94 static int pca9570_probe(struct i2c_client
*client
)
98 gpio
= devm_kzalloc(&client
->dev
, sizeof(*gpio
), GFP_KERNEL
);
102 gpio
->chip
.label
= client
->name
;
103 gpio
->chip
.parent
= &client
->dev
;
104 gpio
->chip
.owner
= THIS_MODULE
;
105 gpio
->chip
.get_direction
= pca9570_get_direction
;
106 gpio
->chip
.get
= pca9570_get
;
107 gpio
->chip
.set
= pca9570_set
;
108 gpio
->chip
.base
= -1;
109 gpio
->chip
.ngpio
= (uintptr_t)device_get_match_data(&client
->dev
);
110 gpio
->chip
.can_sleep
= true;
112 mutex_init(&gpio
->lock
);
114 /* Read the current output level */
115 pca9570_read(gpio
, &gpio
->out
);
117 i2c_set_clientdata(client
, gpio
);
119 return devm_gpiochip_add_data(&client
->dev
, &gpio
->chip
, gpio
);
122 static const struct i2c_device_id pca9570_id_table
[] = {
126 MODULE_DEVICE_TABLE(i2c
, pca9570_id_table
);
128 static const struct of_device_id pca9570_of_match_table
[] = {
129 { .compatible
= "nxp,pca9570", .data
= (void *)4 },
132 MODULE_DEVICE_TABLE(of
, pca9570_of_match_table
);
134 static struct i2c_driver pca9570_driver
= {
137 .of_match_table
= pca9570_of_match_table
,
139 .probe_new
= pca9570_probe
,
140 .id_table
= pca9570_id_table
,
142 module_i2c_driver(pca9570_driver
);
144 MODULE_AUTHOR("Sungbo Eo <mans0n@gorani.run>");
145 MODULE_DESCRIPTION("GPIO expander driver for PCA9570");
146 MODULE_LICENSE("GPL v2");