xref: /OK3568_Linux_fs/kernel/drivers/gpio/gpio-aw9110.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Driver for aw9110 I2C GPIO expanders
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #include <linux/gpio/driver.h>
8*4882a593Smuzhiyun #include <linux/i2c.h>
9*4882a593Smuzhiyun #include <linux/interrupt.h>
10*4882a593Smuzhiyun #include <linux/irq.h>
11*4882a593Smuzhiyun #include <linux/irqdomain.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun #include <linux/of_device.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun #include <linux/of_gpio.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define REG_INPUT_P0        0x00
21*4882a593Smuzhiyun #define REG_INPUT_P1        0x01
22*4882a593Smuzhiyun #define REG_OUTPUT_P0       0x02
23*4882a593Smuzhiyun #define REG_OUTPUT_P1       0x03
24*4882a593Smuzhiyun #define REG_CONFIG_P0       0x04
25*4882a593Smuzhiyun #define REG_CONFIG_P1       0x05
26*4882a593Smuzhiyun #define REG_INT_P0          0x06
27*4882a593Smuzhiyun #define REG_INT_P1          0x07
28*4882a593Smuzhiyun #define REG_ID              0x10
29*4882a593Smuzhiyun #define REG_CTRL            0x11
30*4882a593Smuzhiyun #define REG_WORK_MODE_P0    0x12
31*4882a593Smuzhiyun #define REG_WORK_MODE_P1    0x13
32*4882a593Smuzhiyun #define REG_EN_BREATH       0x14
33*4882a593Smuzhiyun #define REG_FADE_TIME       0x15
34*4882a593Smuzhiyun #define REG_FULL_TIME       0x16
35*4882a593Smuzhiyun #define REG_DLY0_BREATH     0x17
36*4882a593Smuzhiyun #define REG_DLY1_BREATH     0x18
37*4882a593Smuzhiyun #define REG_DLY2_BREATH     0x19
38*4882a593Smuzhiyun #define REG_DLY3_BREATH     0x1a
39*4882a593Smuzhiyun #define REG_DLY4_BREATH     0x1b
40*4882a593Smuzhiyun #define REG_DLY5_BREATH     0x1c
41*4882a593Smuzhiyun #define REG_DIM00           0x20
42*4882a593Smuzhiyun #define REG_DIM01           0x21
43*4882a593Smuzhiyun #define REG_DIM02           0x22
44*4882a593Smuzhiyun #define REG_DIM03           0x23
45*4882a593Smuzhiyun #define REG_DIM04           0x24
46*4882a593Smuzhiyun #define REG_DIM05           0x25
47*4882a593Smuzhiyun #define REG_DIM06           0x26
48*4882a593Smuzhiyun #define REG_DIM07           0x27
49*4882a593Smuzhiyun #define REG_DIM08           0x28
50*4882a593Smuzhiyun #define REG_DIM09           0x29
51*4882a593Smuzhiyun #define REG_SWRST           0x7F
52*4882a593Smuzhiyun #define REG_81H             0x81
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static const struct i2c_device_id aw9110_id[] = {
56*4882a593Smuzhiyun 	{ "aw9110", 10 },
57*4882a593Smuzhiyun 	{ }
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, aw9110_id);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #ifdef CONFIG_OF
62*4882a593Smuzhiyun static const struct of_device_id aw9110_of_table[] = {
63*4882a593Smuzhiyun 	{ .compatible = "awinic,aw9110" },
64*4882a593Smuzhiyun 	{ }
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, aw9110_of_table);
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun struct aw9110 {
71*4882a593Smuzhiyun 	struct gpio_chip	chip;
72*4882a593Smuzhiyun 	struct irq_chip		irqchip;
73*4882a593Smuzhiyun 	struct i2c_client	*client;
74*4882a593Smuzhiyun 	struct mutex		lock;		/* protect 'out' */
75*4882a593Smuzhiyun 	unsigned int		out;		/* software latch */
76*4882a593Smuzhiyun 	unsigned int		direct;		/* gpio direct */
77*4882a593Smuzhiyun 	unsigned int		status;		/* current status */
78*4882a593Smuzhiyun 	unsigned int		irq_enabled;	/* enabled irqs */
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	struct device		*dev;
81*4882a593Smuzhiyun 	int			shdn_en;	/* shutdown ctrl */
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	int (*write)(struct i2c_client *client, u8 reg, u8 data);
84*4882a593Smuzhiyun 	int (*read)(struct i2c_client *client, u8 reg);
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 
aw9110_i2c_write_le8(struct i2c_client * client,u8 reg,u8 data)88*4882a593Smuzhiyun static int aw9110_i2c_write_le8(struct i2c_client *client, u8 reg, u8 data)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	return i2c_smbus_write_byte_data(client, reg, data);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
aw9110_i2c_read_le8(struct i2c_client * client,u8 reg)93*4882a593Smuzhiyun static int aw9110_i2c_read_le8(struct i2c_client *client, u8 reg)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	return (int)i2c_smbus_read_byte_data(client, reg);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
aw9110_get(struct gpio_chip * chip,unsigned int offset)98*4882a593Smuzhiyun static int aw9110_get(struct gpio_chip *chip, unsigned int offset)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	struct aw9110	*gpio = gpiochip_get_data(chip);
101*4882a593Smuzhiyun 	int value = 0;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	if (offset < 4) {
106*4882a593Smuzhiyun 		value = gpio->read(gpio->client, REG_INPUT_P1);
107*4882a593Smuzhiyun 		mutex_unlock(&gpio->lock);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 		value = (value < 0) ? value : !!(value & (1 << offset));
110*4882a593Smuzhiyun 	} else {
111*4882a593Smuzhiyun 		value = gpio->read(gpio->client, REG_INPUT_P0);
112*4882a593Smuzhiyun 		mutex_unlock(&gpio->lock);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 		value = (value < 0) ? value : !!((value<<4) & (1 << offset));
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	return value;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
aw9110_get_direction(struct gpio_chip * chip,unsigned int offset)120*4882a593Smuzhiyun static int aw9110_get_direction(struct gpio_chip *chip, unsigned int offset)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	struct aw9110	*gpio = gpiochip_get_data(chip);
123*4882a593Smuzhiyun 	unsigned int reg_val;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	reg_val = gpio->direct;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	dev_dbg(gpio->dev, "direct get: %04X, pin:%d\n", reg_val, offset);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (reg_val & (1<<offset))
130*4882a593Smuzhiyun 		return GPIO_LINE_DIRECTION_IN;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return GPIO_LINE_DIRECTION_OUT;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
aw9110_direction_input(struct gpio_chip * chip,unsigned int offset)135*4882a593Smuzhiyun static int aw9110_direction_input(struct gpio_chip *chip, unsigned int offset)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	struct aw9110	*gpio = gpiochip_get_data(chip);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	/* set direct */
142*4882a593Smuzhiyun 	gpio->direct |= (1<<offset);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	if (offset < 4)
145*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_CONFIG_P1, gpio->direct&0x0F);
146*4882a593Smuzhiyun 	else
147*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_CONFIG_P0, (gpio->direct >> 4)&0x3F);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	mutex_unlock(&gpio->lock);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	dev_dbg(gpio->dev, "direct in: %04X, pin:%d\n", gpio->direct, offset);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
aw9110_direction_output(struct gpio_chip * chip,unsigned int offset,int value)156*4882a593Smuzhiyun static int aw9110_direction_output(struct gpio_chip *chip, unsigned int offset, int value)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	struct aw9110	*gpio = gpiochip_get_data(chip);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* set level */
161*4882a593Smuzhiyun 	chip->set(chip, offset, value);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	/* set direct */
166*4882a593Smuzhiyun 	gpio->direct &= ~(1<<offset);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	if (offset < 4)
169*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_CONFIG_P1, gpio->direct&0x0F);
170*4882a593Smuzhiyun 	else
171*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_CONFIG_P0, (gpio->direct >> 4)&0x3F);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	mutex_unlock(&gpio->lock);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	dev_dbg(gpio->dev, "direct out: %04X, pin:%d\n", gpio->direct, offset);
176*4882a593Smuzhiyun 	return 0;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
aw9110_set(struct gpio_chip * chip,unsigned int offset,int value)179*4882a593Smuzhiyun static void aw9110_set(struct gpio_chip *chip, unsigned int offset, int value)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	struct aw9110 *gpio = gpiochip_get_data(chip);
182*4882a593Smuzhiyun 	unsigned int bit = 1 << offset;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (value)
187*4882a593Smuzhiyun 		gpio->out |= bit;
188*4882a593Smuzhiyun 	else
189*4882a593Smuzhiyun 		gpio->out &= ~bit;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	if (offset < 4)
192*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_OUTPUT_P1, gpio->out >> 0);
193*4882a593Smuzhiyun 	else
194*4882a593Smuzhiyun 		gpio->write(gpio->client, REG_OUTPUT_P0, gpio->out >> 4);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	mutex_unlock(&gpio->lock);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
200*4882a593Smuzhiyun 
aw9110_irq(int irq,void * data)201*4882a593Smuzhiyun static irqreturn_t aw9110_irq(int irq, void *data)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	struct aw9110  *gpio = data;
204*4882a593Smuzhiyun 	unsigned long change, i, status = 0;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	int value = 0;
207*4882a593Smuzhiyun 	int nirq;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	value = gpio->read(gpio->client, REG_INPUT_P1);
210*4882a593Smuzhiyun 	status |= (value < 0) ? 0 : value;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	value = gpio->read(gpio->client, REG_INPUT_P0);
213*4882a593Smuzhiyun 	status |= (value < 0) ? 0 : (value<<4);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	/*
217*4882a593Smuzhiyun 	 * call the interrupt handler iff gpio is used as
218*4882a593Smuzhiyun 	 * interrupt source, just to avoid bad irqs
219*4882a593Smuzhiyun 	 */
220*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
221*4882a593Smuzhiyun 	change = (gpio->status ^ status) & gpio->irq_enabled;
222*4882a593Smuzhiyun 	gpio->status = status;
223*4882a593Smuzhiyun 	mutex_unlock(&gpio->lock);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	for_each_set_bit(i, &change, gpio->chip.ngpio) {
226*4882a593Smuzhiyun 		nirq = irq_find_mapping(gpio->chip.irq.domain, i);
227*4882a593Smuzhiyun 		if (nirq) {
228*4882a593Smuzhiyun 			dev_dbg(gpio->dev, "status:%04lx,change:%04lx,index:%ld,nirq:%d\n",
229*4882a593Smuzhiyun 					status, change, i, nirq);
230*4882a593Smuzhiyun 			handle_nested_irq(nirq);
231*4882a593Smuzhiyun 		}
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	return IRQ_HANDLED;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun /*
238*4882a593Smuzhiyun  * NOP functions
239*4882a593Smuzhiyun  */
aw9110_noop(struct irq_data * data)240*4882a593Smuzhiyun static void aw9110_noop(struct irq_data *data) { }
241*4882a593Smuzhiyun 
aw9110_irq_set_wake(struct irq_data * data,unsigned int on)242*4882a593Smuzhiyun static int aw9110_irq_set_wake(struct irq_data *data, unsigned int on)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	struct aw9110 *gpio = irq_data_get_irq_chip_data(data);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return irq_set_irq_wake(gpio->client->irq, on);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
aw9110_irq_enable(struct irq_data * data)249*4882a593Smuzhiyun static void aw9110_irq_enable(struct irq_data *data)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	struct aw9110 *gpio = irq_data_get_irq_chip_data(data);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	gpio->irq_enabled |= (1 << data->hwirq);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
aw9110_irq_disable(struct irq_data * data)256*4882a593Smuzhiyun static void aw9110_irq_disable(struct irq_data *data)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	struct aw9110 *gpio = irq_data_get_irq_chip_data(data);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	gpio->irq_enabled &= ~(1 << data->hwirq);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
aw9110_irq_bus_lock(struct irq_data * data)263*4882a593Smuzhiyun static void aw9110_irq_bus_lock(struct irq_data *data)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	struct aw9110 *gpio = irq_data_get_irq_chip_data(data);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	mutex_lock(&gpio->lock);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
aw9110_irq_bus_sync_unlock(struct irq_data * data)270*4882a593Smuzhiyun static void aw9110_irq_bus_sync_unlock(struct irq_data *data)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct aw9110 *gpio = irq_data_get_irq_chip_data(data);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	mutex_unlock(&gpio->lock);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
aw9110_state_init(struct aw9110 * gpio)277*4882a593Smuzhiyun static void aw9110_state_init(struct aw9110	*gpio)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	/* out4-9 push-pull */
280*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CTRL, (1<<4));
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	/* work mode : gpio */
283*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_WORK_MODE_P1, 0x0F);
284*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_WORK_MODE_P0, 0x3F);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	/* default direct */
287*4882a593Smuzhiyun 	gpio->direct = 0x03FF;	/* 0: output, 1:input */
288*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CONFIG_P1, gpio->direct & 0x0F);
289*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CONFIG_P0, (gpio->direct>>4) & 0x3F);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	/* interrupt enable */
292*4882a593Smuzhiyun 	gpio->irq_enabled = 0x03FF;	/* 0: disable 1:enable, chip: 0:enable,  1: disable */
293*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_INT_P1, ((~gpio->irq_enabled) >> 0)&0x0F);
294*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_INT_P0, ((~gpio->irq_enabled) >> 4)&0x3F);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	/* clear interrupt */
297*4882a593Smuzhiyun 	gpio->read(gpio->client, REG_INPUT_P1);
298*4882a593Smuzhiyun 	gpio->read(gpio->client, REG_INPUT_P1);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
aw9110_parse_dt(struct aw9110 * chip,struct i2c_client * client)301*4882a593Smuzhiyun static int aw9110_parse_dt(struct aw9110 *chip, struct i2c_client *client)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	struct device_node *np = client->dev.of_node;
304*4882a593Smuzhiyun 	int ret = 0;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	/* shdn_en */
307*4882a593Smuzhiyun 	ret = of_get_named_gpio(np, "shdn_en", 0);
308*4882a593Smuzhiyun 	if (ret < 0) {
309*4882a593Smuzhiyun 		dev_err(chip->dev, "of get shdn_en failed\n");
310*4882a593Smuzhiyun 		chip->shdn_en = -1;
311*4882a593Smuzhiyun 	} else {
312*4882a593Smuzhiyun 		chip->shdn_en = ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 		ret = devm_gpio_request_one(chip->dev, chip->shdn_en,
315*4882a593Smuzhiyun 					    GPIOF_OUT_INIT_LOW, "AW9110_SHDN_EN");
316*4882a593Smuzhiyun 		if (ret) {
317*4882a593Smuzhiyun 			dev_err(chip->dev,
318*4882a593Smuzhiyun 				"devm_gpio_request_one shdn_en failed\n");
319*4882a593Smuzhiyun 			return ret;
320*4882a593Smuzhiyun 		}
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 		/* enable chip */
323*4882a593Smuzhiyun 		gpio_set_value(chip->shdn_en, 1);
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
aw9110_check_dev_id(struct i2c_client * client)329*4882a593Smuzhiyun static int aw9110_check_dev_id(struct i2c_client *client)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	int ret;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	ret = aw9110_i2c_read_le8(client, REG_ID);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (ret < 0) {
336*4882a593Smuzhiyun 		dev_err(&client->dev, "fail to read dev id(%d)\n", ret);
337*4882a593Smuzhiyun 		return ret;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	dev_info(&client->dev, "dev id : 0x%02x\n", ret);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	return 0;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
346*4882a593Smuzhiyun 
aw9110_probe(struct i2c_client * client,const struct i2c_device_id * id)347*4882a593Smuzhiyun static int aw9110_probe(struct i2c_client *client,
348*4882a593Smuzhiyun 			 const struct i2c_device_id *id)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	struct aw9110			*gpio;
351*4882a593Smuzhiyun 	int				status;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	dev_info(&client->dev, "===aw9110 probe===\n");
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* Allocate, initialize, and register this gpio_chip. */
356*4882a593Smuzhiyun 	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
357*4882a593Smuzhiyun 	if (!gpio)
358*4882a593Smuzhiyun 		return -ENOMEM;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	gpio->dev = &client->dev;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	aw9110_parse_dt(gpio, client);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	mutex_init(&gpio->lock);
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	gpio->chip.base			= -1;
367*4882a593Smuzhiyun 	gpio->chip.can_sleep		= true;
368*4882a593Smuzhiyun 	gpio->chip.parent		= &client->dev;
369*4882a593Smuzhiyun 	gpio->chip.owner		= THIS_MODULE;
370*4882a593Smuzhiyun 	gpio->chip.get			= aw9110_get;
371*4882a593Smuzhiyun 	gpio->chip.set			= aw9110_set;
372*4882a593Smuzhiyun 	gpio->chip.get_direction	= aw9110_get_direction;
373*4882a593Smuzhiyun 	gpio->chip.direction_input	= aw9110_direction_input;
374*4882a593Smuzhiyun 	gpio->chip.direction_output	= aw9110_direction_output;
375*4882a593Smuzhiyun 	gpio->chip.ngpio		= id->driver_data;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	gpio->write	= aw9110_i2c_write_le8;
378*4882a593Smuzhiyun 	gpio->read	= aw9110_i2c_read_le8;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	gpio->chip.label = client->name;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	gpio->client = client;
383*4882a593Smuzhiyun 	i2c_set_clientdata(client, gpio);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	status = aw9110_check_dev_id(client);
386*4882a593Smuzhiyun 	if (status < 0) {
387*4882a593Smuzhiyun 		dev_err(&client->dev, "check device id fail(%d)\n", status);
388*4882a593Smuzhiyun 		goto fail;
389*4882a593Smuzhiyun 	}
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	aw9110_state_init(gpio);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	/* Enable irqchip if we have an interrupt */
394*4882a593Smuzhiyun 	if (client->irq) {
395*4882a593Smuzhiyun 		struct gpio_irq_chip *girq;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 		gpio->irqchip.name = "aw9110";
398*4882a593Smuzhiyun 		gpio->irqchip.irq_enable = aw9110_irq_enable;
399*4882a593Smuzhiyun 		gpio->irqchip.irq_disable = aw9110_irq_disable;
400*4882a593Smuzhiyun 		gpio->irqchip.irq_ack = aw9110_noop;
401*4882a593Smuzhiyun 		gpio->irqchip.irq_mask = aw9110_noop;
402*4882a593Smuzhiyun 		gpio->irqchip.irq_unmask = aw9110_noop;
403*4882a593Smuzhiyun 		gpio->irqchip.irq_set_wake = aw9110_irq_set_wake;
404*4882a593Smuzhiyun 		gpio->irqchip.irq_bus_lock = aw9110_irq_bus_lock;
405*4882a593Smuzhiyun 		gpio->irqchip.irq_bus_sync_unlock = aw9110_irq_bus_sync_unlock;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 		status = devm_request_threaded_irq(&client->dev, client->irq,
408*4882a593Smuzhiyun 					NULL, aw9110_irq, IRQF_ONESHOT |
409*4882a593Smuzhiyun 					IRQF_TRIGGER_FALLING | IRQF_SHARED,
410*4882a593Smuzhiyun 					dev_name(&client->dev), gpio);
411*4882a593Smuzhiyun 		if (status)
412*4882a593Smuzhiyun 			goto fail;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 		girq = &gpio->chip.irq;
415*4882a593Smuzhiyun 		girq->chip = &gpio->irqchip;
416*4882a593Smuzhiyun 		/* This will let us handle the parent IRQ in the driver */
417*4882a593Smuzhiyun 		girq->parent_handler = NULL;
418*4882a593Smuzhiyun 		girq->num_parents = 0;
419*4882a593Smuzhiyun 		girq->parents = NULL;
420*4882a593Smuzhiyun 		girq->default_type = IRQ_TYPE_NONE;
421*4882a593Smuzhiyun 		girq->handler = handle_level_irq;
422*4882a593Smuzhiyun 		girq->threaded = true;
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
426*4882a593Smuzhiyun 	if (status < 0)
427*4882a593Smuzhiyun 		goto fail;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	dev_info(&client->dev, "probed\n");
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	return 0;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun fail:
434*4882a593Smuzhiyun 	dev_err(&client->dev, "probe error %d for '%s'\n", status,
435*4882a593Smuzhiyun 		client->name);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	return status;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
aw9110_pm_resume(struct device * dev)440*4882a593Smuzhiyun static int aw9110_pm_resume(struct device *dev)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	struct aw9110 *gpio = dev->driver_data;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	/* out4-9 push-pull */
445*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CTRL, (1<<4));
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	/* work mode : gpio */
448*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_WORK_MODE_P1, 0x0F);
449*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_WORK_MODE_P0, 0x3F);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	/* direct */
452*4882a593Smuzhiyun 	//gpio->direct = 0x03FF;	/* 0: output, 1:input */
453*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CONFIG_P1, gpio->direct & 0x0F);
454*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_CONFIG_P0, (gpio->direct>>4) & 0x3F);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	/* out */
457*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_OUTPUT_P1, gpio->out >> 0);
458*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_OUTPUT_P0, gpio->out >> 4);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* interrupt enable */
461*4882a593Smuzhiyun 	//gpio->irq_enabled = 0x03FF;	/* 0: disable 1:enable, chip: 0:enable,  1: disable */
462*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_INT_P1, ((~gpio->irq_enabled) >> 0)&0x0F);
463*4882a593Smuzhiyun 	gpio->write(gpio->client, REG_INT_P0, ((~gpio->irq_enabled) >> 4)&0x3F);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	return 0;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun static const struct dev_pm_ops aw9110_pm_ops = {
469*4882a593Smuzhiyun 	.resume = aw9110_pm_resume,
470*4882a593Smuzhiyun };
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun static struct i2c_driver aw9110_driver = {
473*4882a593Smuzhiyun 	.driver = {
474*4882a593Smuzhiyun 		.name	= "aw9110",
475*4882a593Smuzhiyun 		.pm = &aw9110_pm_ops,
476*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(aw9110_of_table),
477*4882a593Smuzhiyun 	},
478*4882a593Smuzhiyun 	.probe	= aw9110_probe,
479*4882a593Smuzhiyun 	.id_table = aw9110_id,
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun 
aw9110_init(void)482*4882a593Smuzhiyun static int __init aw9110_init(void)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	return i2c_add_driver(&aw9110_driver);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun /* register after i2c postcore initcall and before
487*4882a593Smuzhiyun  * subsys initcalls that may rely on these GPIOs
488*4882a593Smuzhiyun  */
489*4882a593Smuzhiyun subsys_initcall(aw9110_init);
490*4882a593Smuzhiyun 
aw9110_exit(void)491*4882a593Smuzhiyun static void __exit aw9110_exit(void)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	i2c_del_driver(&aw9110_driver);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun module_exit(aw9110_exit);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun MODULE_LICENSE("GPL");
498*4882a593Smuzhiyun MODULE_AUTHOR("Jake Wu <jake.wu@rock-chips.com>");
499*4882a593Smuzhiyun MODULE_DESCRIPTION("AW9110 i2c expander gpio driver");
500*4882a593Smuzhiyun 
501