1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * GPIO Driver for Dialog DA9052 PMICs.
5 * Copyright(c) 2011 Dialog Semiconductor Ltd.
7 * Author: David Dajun Chen <dchen@diasemi.com>
10 #include <linux/gpio/driver.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/syscalls.h>
14 #include <linux/uaccess.h>
16 #include <linux/mfd/da9052/da9052.h>
17 #include <linux/mfd/da9052/pdata.h>
18 #include <linux/mfd/da9052/reg.h>
20 #define DA9052_INPUT 1
21 #define DA9052_OUTPUT_OPENDRAIN 2
22 #define DA9052_OUTPUT_PUSHPULL 3
24 #define DA9052_SUPPLY_VDD_IO1 0
26 #define DA9052_DEBOUNCING_OFF 0
27 #define DA9052_DEBOUNCING_ON 1
29 #define DA9052_OUTPUT_LOWLEVEL 0
31 #define DA9052_ACTIVE_LOW 0
32 #define DA9052_ACTIVE_HIGH 1
34 #define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8
35 #define DA9052_GPIO_SHIFT_COUNT(no) (no%8)
36 #define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
37 #define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
38 #define DA9052_GPIO_NIBBLE_SHIFT 4
39 #define DA9052_IRQ_GPI0 16
40 #define DA9052_GPIO_ODD_SHIFT 7
41 #define DA9052_GPIO_EVEN_SHIFT 3
44 struct da9052
*da9052
;
48 static unsigned char da9052_gpio_port_odd(unsigned offset
)
53 static int da9052_gpio_get(struct gpio_chip
*gc
, unsigned offset
)
55 struct da9052_gpio
*gpio
= gpiochip_get_data(gc
);
56 int da9052_port_direction
= 0;
59 ret
= da9052_reg_read(gpio
->da9052
,
60 DA9052_GPIO_0_1_REG
+ (offset
>> 1));
64 if (da9052_gpio_port_odd(offset
)) {
65 da9052_port_direction
= ret
& DA9052_GPIO_ODD_PORT_PIN
;
66 da9052_port_direction
>>= 4;
68 da9052_port_direction
= ret
& DA9052_GPIO_EVEN_PORT_PIN
;
71 switch (da9052_port_direction
) {
73 if (offset
< DA9052_GPIO_MAX_PORTS_PER_REGISTER
)
74 ret
= da9052_reg_read(gpio
->da9052
,
77 ret
= da9052_reg_read(gpio
->da9052
,
81 return !!(ret
& (1 << DA9052_GPIO_SHIFT_COUNT(offset
)));
82 case DA9052_OUTPUT_PUSHPULL
:
83 if (da9052_gpio_port_odd(offset
))
84 return !!(ret
& DA9052_GPIO_ODD_PORT_MODE
);
86 return !!(ret
& DA9052_GPIO_EVEN_PORT_MODE
);
92 static void da9052_gpio_set(struct gpio_chip
*gc
, unsigned offset
, int value
)
94 struct da9052_gpio
*gpio
= gpiochip_get_data(gc
);
97 if (da9052_gpio_port_odd(offset
)) {
98 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
100 DA9052_GPIO_ODD_PORT_MODE
,
101 value
<< DA9052_GPIO_ODD_SHIFT
);
103 dev_err(gpio
->da9052
->dev
,
104 "Failed to updated gpio odd reg,%d",
107 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
109 DA9052_GPIO_EVEN_PORT_MODE
,
110 value
<< DA9052_GPIO_EVEN_SHIFT
);
112 dev_err(gpio
->da9052
->dev
,
113 "Failed to updated gpio even reg,%d",
118 static int da9052_gpio_direction_input(struct gpio_chip
*gc
, unsigned offset
)
120 struct da9052_gpio
*gpio
= gpiochip_get_data(gc
);
121 unsigned char register_value
;
124 /* Format: function - 2 bits type - 1 bit mode - 1 bit */
125 register_value
= DA9052_INPUT
| DA9052_ACTIVE_LOW
<< 2 |
126 DA9052_DEBOUNCING_ON
<< 3;
128 if (da9052_gpio_port_odd(offset
))
129 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
131 DA9052_GPIO_MASK_UPPER_NIBBLE
,
133 DA9052_GPIO_NIBBLE_SHIFT
));
135 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
137 DA9052_GPIO_MASK_LOWER_NIBBLE
,
143 static int da9052_gpio_direction_output(struct gpio_chip
*gc
,
144 unsigned offset
, int value
)
146 struct da9052_gpio
*gpio
= gpiochip_get_data(gc
);
147 unsigned char register_value
;
150 /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
151 register_value
= DA9052_OUTPUT_PUSHPULL
| DA9052_SUPPLY_VDD_IO1
<< 2 |
154 if (da9052_gpio_port_odd(offset
))
155 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
157 DA9052_GPIO_MASK_UPPER_NIBBLE
,
159 DA9052_GPIO_NIBBLE_SHIFT
));
161 ret
= da9052_reg_update(gpio
->da9052
, (offset
>> 1) +
163 DA9052_GPIO_MASK_LOWER_NIBBLE
,
169 static int da9052_gpio_to_irq(struct gpio_chip
*gc
, u32 offset
)
171 struct da9052_gpio
*gpio
= gpiochip_get_data(gc
);
172 struct da9052
*da9052
= gpio
->da9052
;
176 irq
= regmap_irq_get_virq(da9052
->irq_data
, DA9052_IRQ_GPI0
+ offset
);
181 static const struct gpio_chip reference_gp
= {
182 .label
= "da9052-gpio",
183 .owner
= THIS_MODULE
,
184 .get
= da9052_gpio_get
,
185 .set
= da9052_gpio_set
,
186 .direction_input
= da9052_gpio_direction_input
,
187 .direction_output
= da9052_gpio_direction_output
,
188 .to_irq
= da9052_gpio_to_irq
,
194 static int da9052_gpio_probe(struct platform_device
*pdev
)
196 struct da9052_gpio
*gpio
;
197 struct da9052_pdata
*pdata
;
199 gpio
= devm_kzalloc(&pdev
->dev
, sizeof(*gpio
), GFP_KERNEL
);
203 gpio
->da9052
= dev_get_drvdata(pdev
->dev
.parent
);
204 pdata
= dev_get_platdata(gpio
->da9052
->dev
);
206 gpio
->gp
= reference_gp
;
207 if (pdata
&& pdata
->gpio_base
)
208 gpio
->gp
.base
= pdata
->gpio_base
;
210 return devm_gpiochip_add_data(&pdev
->dev
, &gpio
->gp
, gpio
);
213 static struct platform_driver da9052_gpio_driver
= {
214 .probe
= da9052_gpio_probe
,
216 .name
= "da9052-gpio",
220 module_platform_driver(da9052_gpio_driver
);
222 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
223 MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
224 MODULE_LICENSE("GPL");
225 MODULE_ALIAS("platform:da9052-gpio");