2 * TI Palma series PMIC's GPIO driver.
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
6 * Author: Laxman Dewangan <ldewangan@nvidia.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/gpio.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/mfd/palmas.h>
26 #include <linux/of_device.h>
27 #include <linux/platform_device.h>
30 struct gpio_chip gpio_chip
;
31 struct palmas
*palmas
;
34 struct palmas_device_data
{
38 static int palmas_gpio_get(struct gpio_chip
*gc
, unsigned offset
)
40 struct palmas_gpio
*pg
= gpiochip_get_data(gc
);
41 struct palmas
*palmas
= pg
->palmas
;
45 int gpio16
= (offset
/8);
48 reg
= (gpio16
) ? PALMAS_GPIO_DATA_DIR2
: PALMAS_GPIO_DATA_DIR
;
50 ret
= palmas_read(palmas
, PALMAS_GPIO_BASE
, reg
, &val
);
52 dev_err(gc
->parent
, "Reg 0x%02x read failed, %d\n", reg
, ret
);
56 if (val
& BIT(offset
))
57 reg
= (gpio16
) ? PALMAS_GPIO_DATA_OUT2
: PALMAS_GPIO_DATA_OUT
;
59 reg
= (gpio16
) ? PALMAS_GPIO_DATA_IN2
: PALMAS_GPIO_DATA_IN
;
61 ret
= palmas_read(palmas
, PALMAS_GPIO_BASE
, reg
, &val
);
63 dev_err(gc
->parent
, "Reg 0x%02x read failed, %d\n", reg
, ret
);
66 return !!(val
& BIT(offset
));
69 static void palmas_gpio_set(struct gpio_chip
*gc
, unsigned offset
,
72 struct palmas_gpio
*pg
= gpiochip_get_data(gc
);
73 struct palmas
*palmas
= pg
->palmas
;
76 int gpio16
= (offset
/8);
81 PALMAS_GPIO_SET_DATA_OUT2
: PALMAS_GPIO_CLEAR_DATA_OUT2
;
84 PALMAS_GPIO_SET_DATA_OUT
: PALMAS_GPIO_CLEAR_DATA_OUT
;
86 ret
= palmas_write(palmas
, PALMAS_GPIO_BASE
, reg
, BIT(offset
));
88 dev_err(gc
->parent
, "Reg 0x%02x write failed, %d\n", reg
, ret
);
91 static int palmas_gpio_output(struct gpio_chip
*gc
, unsigned offset
,
94 struct palmas_gpio
*pg
= gpiochip_get_data(gc
);
95 struct palmas
*palmas
= pg
->palmas
;
98 int gpio16
= (offset
/8);
101 reg
= (gpio16
) ? PALMAS_GPIO_DATA_DIR2
: PALMAS_GPIO_DATA_DIR
;
103 /* Set the initial value */
104 palmas_gpio_set(gc
, offset
, value
);
106 ret
= palmas_update_bits(palmas
, PALMAS_GPIO_BASE
, reg
,
107 BIT(offset
), BIT(offset
));
109 dev_err(gc
->parent
, "Reg 0x%02x update failed, %d\n", reg
,
114 static int palmas_gpio_input(struct gpio_chip
*gc
, unsigned offset
)
116 struct palmas_gpio
*pg
= gpiochip_get_data(gc
);
117 struct palmas
*palmas
= pg
->palmas
;
120 int gpio16
= (offset
/8);
123 reg
= (gpio16
) ? PALMAS_GPIO_DATA_DIR2
: PALMAS_GPIO_DATA_DIR
;
125 ret
= palmas_update_bits(palmas
, PALMAS_GPIO_BASE
, reg
, BIT(offset
), 0);
127 dev_err(gc
->parent
, "Reg 0x%02x update failed, %d\n", reg
,
132 static int palmas_gpio_to_irq(struct gpio_chip
*gc
, unsigned offset
)
134 struct palmas_gpio
*pg
= gpiochip_get_data(gc
);
135 struct palmas
*palmas
= pg
->palmas
;
137 return palmas_irq_get_virq(palmas
, PALMAS_GPIO_0_IRQ
+ offset
);
140 static const struct palmas_device_data palmas_dev_data
= {
144 static const struct palmas_device_data tps80036_dev_data
= {
148 static const struct of_device_id of_palmas_gpio_match
[] = {
149 { .compatible
= "ti,palmas-gpio", .data
= &palmas_dev_data
,},
150 { .compatible
= "ti,tps65913-gpio", .data
= &palmas_dev_data
,},
151 { .compatible
= "ti,tps65914-gpio", .data
= &palmas_dev_data
,},
152 { .compatible
= "ti,tps80036-gpio", .data
= &tps80036_dev_data
,},
155 MODULE_DEVICE_TABLE(of
, of_palmas_gpio_match
);
157 static int palmas_gpio_probe(struct platform_device
*pdev
)
159 struct palmas
*palmas
= dev_get_drvdata(pdev
->dev
.parent
);
160 struct palmas_platform_data
*palmas_pdata
;
161 struct palmas_gpio
*palmas_gpio
;
163 const struct of_device_id
*match
;
164 const struct palmas_device_data
*dev_data
;
166 match
= of_match_device(of_palmas_gpio_match
, &pdev
->dev
);
169 dev_data
= match
->data
;
171 dev_data
= &palmas_dev_data
;
173 palmas_gpio
= devm_kzalloc(&pdev
->dev
,
174 sizeof(*palmas_gpio
), GFP_KERNEL
);
178 palmas_gpio
->palmas
= palmas
;
179 palmas_gpio
->gpio_chip
.owner
= THIS_MODULE
;
180 palmas_gpio
->gpio_chip
.label
= dev_name(&pdev
->dev
);
181 palmas_gpio
->gpio_chip
.ngpio
= dev_data
->ngpio
;
182 palmas_gpio
->gpio_chip
.can_sleep
= true;
183 palmas_gpio
->gpio_chip
.direction_input
= palmas_gpio_input
;
184 palmas_gpio
->gpio_chip
.direction_output
= palmas_gpio_output
;
185 palmas_gpio
->gpio_chip
.to_irq
= palmas_gpio_to_irq
;
186 palmas_gpio
->gpio_chip
.set
= palmas_gpio_set
;
187 palmas_gpio
->gpio_chip
.get
= palmas_gpio_get
;
188 palmas_gpio
->gpio_chip
.parent
= &pdev
->dev
;
189 #ifdef CONFIG_OF_GPIO
190 palmas_gpio
->gpio_chip
.of_node
= pdev
->dev
.of_node
;
192 palmas_pdata
= dev_get_platdata(palmas
->dev
);
193 if (palmas_pdata
&& palmas_pdata
->gpio_base
)
194 palmas_gpio
->gpio_chip
.base
= palmas_pdata
->gpio_base
;
196 palmas_gpio
->gpio_chip
.base
= -1;
198 ret
= devm_gpiochip_add_data(&pdev
->dev
, &palmas_gpio
->gpio_chip
,
201 dev_err(&pdev
->dev
, "Could not register gpiochip, %d\n", ret
);
205 platform_set_drvdata(pdev
, palmas_gpio
);
209 static struct platform_driver palmas_gpio_driver
= {
210 .driver
.name
= "palmas-gpio",
211 .driver
.owner
= THIS_MODULE
,
212 .driver
.of_match_table
= of_palmas_gpio_match
,
213 .probe
= palmas_gpio_probe
,
216 static int __init
palmas_gpio_init(void)
218 return platform_driver_register(&palmas_gpio_driver
);
220 subsys_initcall(palmas_gpio_init
);
222 static void __exit
palmas_gpio_exit(void)
224 platform_driver_unregister(&palmas_gpio_driver
);
226 module_exit(palmas_gpio_exit
);
228 MODULE_ALIAS("platform:palmas-gpio");
229 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
230 MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs");
231 MODULE_LICENSE("GPL v2");