Blame view

drivers/gpio/gpio-palmas.c 5.97 KB
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /*
   * TI Palma series PMIC's GPIO driver.
   *
   * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
   *
   * Author: Laxman Dewangan <ldewangan@nvidia.com>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms and conditions of the GNU General Public License,
   * version 2, as published by the Free Software Foundation.
   *
   * This program is distributed in the hope it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  #include <linux/gpio.h>
  #include <linux/kernel.h>
f9f2b5cba   Paul Gortmaker   gpio: palmas: mak...
23
  #include <linux/init.h>
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
24
25
26
27
28
29
30
31
32
  #include <linux/mfd/palmas.h>
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/platform_device.h>
  
  struct palmas_gpio {
  	struct gpio_chip gpio_chip;
  	struct palmas *palmas;
  };
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
33
34
35
  struct palmas_device_data {
  	int ngpio;
  };
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
36
37
  static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
  {
5b68cc2d5   Linus Walleij   gpio: palmas: use...
38
  	struct palmas_gpio *pg = gpiochip_get_data(gc);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
39
40
41
  	struct palmas *palmas = pg->palmas;
  	unsigned int val;
  	int ret;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
42
43
44
45
46
  	unsigned int reg;
  	int gpio16 = (offset/8);
  
  	offset %= 8;
  	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
47

ca6af7b96   Laxman Dewangan   gpio: palmas: add...
48
  	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
49
  	if (ret < 0) {
58383c784   Linus Walleij   gpio: change memb...
50
51
  		dev_err(gc->parent, "Reg 0x%02x read failed, %d
  ", reg, ret);
8b628c659   Andrew Chew   gpio: palmas: Fix...
52
53
  		return ret;
  	}
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
54
55
56
57
58
59
  	if (val & BIT(offset))
  		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
  	else
  		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
  
  	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
8b628c659   Andrew Chew   gpio: palmas: Fix...
60
  	if (ret < 0) {
58383c784   Linus Walleij   gpio: change memb...
61
62
  		dev_err(gc->parent, "Reg 0x%02x read failed, %d
  ", reg, ret);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
63
64
65
66
67
68
69
70
  		return ret;
  	}
  	return !!(val & BIT(offset));
  }
  
  static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
  			int value)
  {
5b68cc2d5   Linus Walleij   gpio: palmas: use...
71
  	struct palmas_gpio *pg = gpiochip_get_data(gc);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
72
73
  	struct palmas *palmas = pg->palmas;
  	int ret;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
74
75
  	unsigned int reg;
  	int gpio16 = (offset/8);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
76

ca6af7b96   Laxman Dewangan   gpio: palmas: add...
77
78
79
80
  	offset %= 8;
  	if (gpio16)
  		reg = (value) ?
  			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
81
  	else
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
82
83
84
85
  		reg = (value) ?
  			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
  
  	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
86
  	if (ret < 0)
58383c784   Linus Walleij   gpio: change memb...
87
88
  		dev_err(gc->parent, "Reg 0x%02x write failed, %d
  ", reg, ret);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
89
90
91
92
93
  }
  
  static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
  				int value)
  {
5b68cc2d5   Linus Walleij   gpio: palmas: use...
94
  	struct palmas_gpio *pg = gpiochip_get_data(gc);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
95
96
  	struct palmas *palmas = pg->palmas;
  	int ret;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
97
98
99
100
101
  	unsigned int reg;
  	int gpio16 = (offset/8);
  
  	offset %= 8;
  	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
102
103
104
  
  	/* Set the initial value */
  	palmas_gpio_set(gc, offset, value);
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
105
106
  	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
  				BIT(offset), BIT(offset));
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
107
  	if (ret < 0)
58383c784   Linus Walleij   gpio: change memb...
108
109
110
  		dev_err(gc->parent, "Reg 0x%02x update failed, %d
  ", reg,
  			ret);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
111
112
113
114
115
  	return ret;
  }
  
  static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
  {
5b68cc2d5   Linus Walleij   gpio: palmas: use...
116
  	struct palmas_gpio *pg = gpiochip_get_data(gc);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
117
118
  	struct palmas *palmas = pg->palmas;
  	int ret;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
119
120
121
122
123
  	unsigned int reg;
  	int gpio16 = (offset/8);
  
  	offset %= 8;
  	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
124

ca6af7b96   Laxman Dewangan   gpio: palmas: add...
125
  	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
126
  	if (ret < 0)
58383c784   Linus Walleij   gpio: change memb...
127
128
129
  		dev_err(gc->parent, "Reg 0x%02x update failed, %d
  ", reg,
  			ret);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
130
131
132
133
134
  	return ret;
  }
  
  static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
  {
5b68cc2d5   Linus Walleij   gpio: palmas: use...
135
  	struct palmas_gpio *pg = gpiochip_get_data(gc);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
136
137
138
139
  	struct palmas *palmas = pg->palmas;
  
  	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
  }
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
140
141
142
143
144
145
146
  static const struct palmas_device_data palmas_dev_data = {
  	.ngpio = 8,
  };
  
  static const struct palmas_device_data tps80036_dev_data = {
  	.ngpio = 16,
  };
722782fee   Jingoo Han   gpio: palmas: Mak...
147
  static const struct of_device_id of_palmas_gpio_match[] = {
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
148
149
150
151
152
153
  	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
  	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
  	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
  	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
  	{ },
  };
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
154

3d50a2785   Laxman Dewangan   gpio: palmas: Add...
155
156
157
158
159
160
  static int palmas_gpio_probe(struct platform_device *pdev)
  {
  	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
  	struct palmas_platform_data *palmas_pdata;
  	struct palmas_gpio *palmas_gpio;
  	int ret;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
161
162
163
164
  	const struct of_device_id *match;
  	const struct palmas_device_data *dev_data;
  
  	match = of_match_device(of_palmas_gpio_match, &pdev->dev);
5664de25f   LABBE Corentin   gpio: palmas: fix...
165
166
  	if (!match)
  		return -ENODEV;
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
167
168
169
  	dev_data = match->data;
  	if (!dev_data)
  		dev_data = &palmas_dev_data;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
170
171
172
  
  	palmas_gpio = devm_kzalloc(&pdev->dev,
  				sizeof(*palmas_gpio), GFP_KERNEL);
5605beb29   Jingoo Han   gpio: palmas: rem...
173
  	if (!palmas_gpio)
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
174
  		return -ENOMEM;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
175
176
177
178
  
  	palmas_gpio->palmas = palmas;
  	palmas_gpio->gpio_chip.owner = THIS_MODULE;
  	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
ca6af7b96   Laxman Dewangan   gpio: palmas: add...
179
  	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
9fb1f39eb   Linus Walleij   gpio/pinctrl: mak...
180
  	palmas_gpio->gpio_chip.can_sleep = true;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
181
182
183
184
185
  	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
  	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
  	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq;
  	palmas_gpio->gpio_chip.set	= palmas_gpio_set;
  	palmas_gpio->gpio_chip.get	= palmas_gpio_get;
58383c784   Linus Walleij   gpio: change memb...
186
  	palmas_gpio->gpio_chip.parent = &pdev->dev;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
187
  #ifdef CONFIG_OF_GPIO
5763318f5   Laxman Dewangan   gpio: palmas: add...
188
  	palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
189
190
191
192
193
194
  #endif
  	palmas_pdata = dev_get_platdata(palmas->dev);
  	if (palmas_pdata && palmas_pdata->gpio_base)
  		palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base;
  	else
  		palmas_gpio->gpio_chip.base = -1;
297bf067e   Laxman Dewangan   gpio: palmas: Use...
195
196
  	ret = devm_gpiochip_add_data(&pdev->dev, &palmas_gpio->gpio_chip,
  				     palmas_gpio);
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
197
198
199
200
201
202
203
204
205
  	if (ret < 0) {
  		dev_err(&pdev->dev, "Could not register gpiochip, %d
  ", ret);
  		return ret;
  	}
  
  	platform_set_drvdata(pdev, palmas_gpio);
  	return ret;
  }
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
206
207
  static struct platform_driver palmas_gpio_driver = {
  	.driver.name	= "palmas-gpio",
5763318f5   Laxman Dewangan   gpio: palmas: add...
208
  	.driver.of_match_table = of_palmas_gpio_match,
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
209
  	.probe		= palmas_gpio_probe,
3d50a2785   Laxman Dewangan   gpio: palmas: Add...
210
211
212
213
214
215
216
  };
  
  static int __init palmas_gpio_init(void)
  {
  	return platform_driver_register(&palmas_gpio_driver);
  }
  subsys_initcall(palmas_gpio_init);