uboot-sunxi: disable AXP209 on Olimex A13 Olinuxino
[oweals/openwrt.git] / target / linux / ixp4xx / patches-4.9 / 020-gateworks_i2c_pld.patch
1 --- a/drivers/gpio/Kconfig
2 +++ b/drivers/gpio/Kconfig
3 @@ -656,6 +656,14 @@ config GPIO_WS16C48
4           parameter. The interrupt line numbers for the devices may be
5           configured via the irq module parameter.
6  
7 +config GPIO_GW_I2C_PLD
8 +       tristate "Gateworks I2C PLD GPIO Expander"
9 +       depends on I2C
10 +       help
11 +               Say yes here to provide access to the Gateworks I2C PLD GPIO
12 +               Expander. This is used at least on the GW2358-4.
13 +
14 +
15  endmenu
16  
17  menu "I2C GPIO expanders"
18 --- a/drivers/gpio/Makefile
19 +++ b/drivers/gpio/Makefile
20 @@ -48,6 +48,7 @@ obj-$(CONFIG_GPIO_F7188X)     += gpio-f7188x
21  obj-$(CONFIG_GPIO_GE_FPGA)     += gpio-ge.o
22  obj-$(CONFIG_GPIO_GPIO_MM)     += gpio-gpio-mm.o
23  obj-$(CONFIG_GPIO_GRGPIO)      += gpio-grgpio.o
24 +obj-$(CONFIG_GPIO_GW_I2C_PLD)  += gw_i2c_pld.o
25  obj-$(CONFIG_HTC_EGPIO)                += gpio-htc-egpio.o
26  obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
27  obj-$(CONFIG_GPIO_IOP)         += gpio-iop.o
28 --- /dev/null
29 +++ b/drivers/gpio/gw_i2c_pld.c
30 @@ -0,0 +1,371 @@
31 +/*
32 + * Gateworks I2C PLD GPIO expander
33 + *
34 + * Copyright (C) 2009 Gateworks Corporation
35 + *
36 + * This program is free software; you can redistribute it and/or modify
37 + * it under the terms of the GNU General Public License as published by
38 + * the Free Software Foundation; either version 2 of the License, or
39 + * (at your option) any later version.
40 + *
41 + * This program is distributed in the hope that it will be useful,
42 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44 + * GNU General Public License for more details.
45 + *
46 + * You should have received a copy of the GNU General Public License
47 + * along with this program; if not, write to the Free Software
48 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
49 + */
50 +
51 +#include <linux/kernel.h>
52 +#include <linux/slab.h>
53 +#include <linux/hardirq.h>
54 +#include <linux/i2c.h>
55 +#include <linux/i2c/gw_i2c_pld.h>
56 +#include <linux/module.h>
57 +#include <linux/export.h>
58 +#include <asm/gpio.h>
59 +#include <mach/hardware.h>
60 +
61 +static const struct i2c_device_id gw_i2c_pld_id[] = {
62 +       { "gw_i2c_pld", 8 },
63 +       { }
64 +};
65 +MODULE_DEVICE_TABLE(i2c, gw_i2c_pld_id);
66 +
67 +/*
68 + * The Gateworks I2C PLD chip only expose one read and one
69 + * write register.  Writing a "one" bit (to match the reset state) lets
70 + * that pin be used as an input. It is an open-drain model.
71 + */
72 +
73 +struct gw_i2c_pld {
74 +       struct gpio_chip        chip;
75 +       struct i2c_client       *client;
76 +       unsigned                out;            /* software latch */
77 +};
78 +
79 +/*-------------------------------------------------------------------------*/
80 +
81 +/*
82 + * The Gateworks I2C PLD chip does not properly send the acknowledge bit
83 + * thus we cannot use standard i2c_smbus functions. We have recreated
84 + * our own here, but we still use the rt_mutex_lock to lock the i2c_bus
85 + * as the device still exists on the I2C bus.
86 +*/
87 +
88 +#define PLD_SCL_GPIO 6
89 +#define PLD_SDA_GPIO 7
90 +
91 +#define SCL_LO()  gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_LOW)
92 +#define SCL_HI()  gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_HIGH)
93 +#define SCL_EN()  gpio_line_config(PLD_SCL_GPIO, IXP4XX_GPIO_OUT)
94 +#define SDA_LO()  gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_LOW)
95 +#define SDA_HI()  gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_HIGH)
96 +#define SDA_EN()  gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_OUT)
97 +#define SDA_DIS() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_IN)
98 +#define SDA_IN(x) gpio_line_get(PLD_SDA_GPIO, &x);
99 +
100 +static int i2c_pld_write_byte(int address, int byte)
101 +{
102 +       int i;
103 +
104 +       address = (address << 1) & ~0x1;
105 +
106 +       SDA_HI();
107 +       SDA_EN();
108 +       SCL_EN();
109 +       SCL_HI();
110 +       SDA_LO();
111 +       SCL_LO();
112 +
113 +       for (i = 7; i >= 0; i--)
114 +       {
115 +               if (address & (1 << i))
116 +                       SDA_HI();
117 +               else
118 +                       SDA_LO();
119 +
120 +               SCL_HI();
121 +               SCL_LO();
122 +       }
123 +
124 +       SDA_DIS();
125 +       SCL_HI();
126 +       SDA_IN(i);
127 +       SCL_LO();
128 +       SDA_EN();
129 +
130 +       for (i = 7; i >= 0; i--)
131 +       {
132 +               if (byte & (1 << i))
133 +      SDA_HI();
134 +               else
135 +                       SDA_LO();
136 +               SCL_HI();
137 +               SCL_LO();
138 +       }
139 +
140 +       SDA_DIS();
141 +       SCL_HI();
142 +       SDA_IN(i);
143 +       SCL_LO();
144 +
145 +       SDA_HI();
146 +       SDA_EN();
147 +
148 +       SDA_LO();
149 +       SCL_HI();
150 +       SDA_HI();
151 +       SCL_LO();
152 +       SCL_HI();
153 +
154 +       return 0;
155 +}
156 +
157 +static unsigned int i2c_pld_read_byte(int address)
158 +{
159 +       int i = 0, byte = 0;
160 +       int bit;
161 +
162 +       address = (address << 1) | 0x1;
163 +
164 +       SDA_HI();
165 +       SDA_EN();
166 +       SCL_EN();
167 +       SCL_HI();
168 +       SDA_LO();
169 +       SCL_LO();
170 +
171 +       for (i = 7; i >= 0; i--)
172 +       {
173 +               if (address & (1 << i))
174 +                       SDA_HI();
175 +               else
176 +                       SDA_LO();
177 +
178 +               SCL_HI();
179 +               SCL_LO();
180 +       }
181 +
182 +       SDA_DIS();
183 +       SCL_HI();
184 +       SDA_IN(i);
185 +       SCL_LO();
186 +       SDA_EN();
187 +
188 +       SDA_DIS();
189 +       for (i = 7; i >= 0; i--)
190 +       {
191 +               SCL_HI();
192 +               SDA_IN(bit);
193 +               byte |= bit << i;
194 +               SCL_LO();
195 +       }
196 +
197 +       SDA_LO();
198 +       SCL_HI();
199 +       SDA_HI();
200 +       SCL_LO();
201 +       SCL_HI();
202 +
203 +       return byte;
204 +}
205 +
206 +
207 +static int gw_i2c_pld_input8(struct gpio_chip *chip, unsigned offset)
208 +{
209 +       int ret;
210 +       struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
211 +       struct i2c_adapter *adap = gpio->client->adapter;
212 +
213 +       if (in_atomic() || irqs_disabled()) {
214 +               ret = rt_mutex_trylock(&adap->bus_lock);
215 +               if (!ret)
216 +                       /* I2C activity is ongoing. */
217 +                       return -EAGAIN;
218 +       } else {
219 +               rt_mutex_lock(&adap->bus_lock);
220 +       }
221 +
222 +       gpio->out |= (1 << offset);
223 +
224 +       ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
225 +
226 +       rt_mutex_unlock(&adap->bus_lock);
227 +
228 +       return ret;
229 +}
230 +
231 +static int gw_i2c_pld_get8(struct gpio_chip *chip, unsigned offset)
232 +{
233 +       int ret;
234 +       s32     value;
235 +       struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
236 +       struct i2c_adapter *adap = gpio->client->adapter;
237 +
238 +       if (in_atomic() || irqs_disabled()) {
239 +               ret = rt_mutex_trylock(&adap->bus_lock);
240 +               if (!ret)
241 +                       /* I2C activity is ongoing. */
242 +                       return -EAGAIN;
243 +       } else {
244 +               rt_mutex_lock(&adap->bus_lock);
245 +       }
246 +
247 +       value = i2c_pld_read_byte(gpio->client->addr);
248 +
249 +       rt_mutex_unlock(&adap->bus_lock);
250 +
251 +       return (value < 0) ? 0 : (value & (1 << offset));
252 +}
253 +
254 +static int gw_i2c_pld_output8(struct gpio_chip *chip, unsigned offset, int value)
255 +{
256 +       int ret;
257 +
258 +       struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
259 +       struct i2c_adapter *adap = gpio->client->adapter;
260 +
261 +       unsigned bit = 1 << offset;
262 +
263 +       if (in_atomic() || irqs_disabled()) {
264 +               ret = rt_mutex_trylock(&adap->bus_lock);
265 +               if (!ret)
266 +                       /* I2C activity is ongoing. */
267 +                       return -EAGAIN;
268 +       } else {
269 +               rt_mutex_lock(&adap->bus_lock);
270 +       }
271 +
272 +
273 +       if (value)
274 +               gpio->out |= bit;
275 +       else
276 +               gpio->out &= ~bit;
277 +
278 +       ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
279 +
280 +       rt_mutex_unlock(&adap->bus_lock);
281 +
282 +       return ret;
283 +}
284 +
285 +static void gw_i2c_pld_set8(struct gpio_chip *chip, unsigned offset, int value)
286 +{
287 +       gw_i2c_pld_output8(chip, offset, value);
288 +}
289 +
290 +/*-------------------------------------------------------------------------*/
291 +
292 +static int gw_i2c_pld_probe(struct i2c_client *client,
293 +                        const struct i2c_device_id *id)
294 +{
295 +       struct gw_i2c_pld_platform_data *pdata;
296 +       struct gw_i2c_pld *gpio;
297 +       int status;
298 +
299 +       pdata = client->dev.platform_data;
300 +       if (!pdata)
301 +               return -ENODEV;
302 +
303 +       /* Allocate, initialize, and register this gpio_chip. */
304 +       gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
305 +       if (!gpio)
306 +               return -ENOMEM;
307 +
308 +       gpio->chip.base = pdata->gpio_base;
309 +       gpio->chip.can_sleep = 1;
310 +       gpio->chip.dev = &client->dev;
311 +       gpio->chip.owner = THIS_MODULE;
312 +
313 +       gpio->chip.ngpio = pdata->nr_gpio;
314 +       gpio->chip.direction_input = gw_i2c_pld_input8;
315 +       gpio->chip.get = gw_i2c_pld_get8;
316 +       gpio->chip.direction_output = gw_i2c_pld_output8;
317 +       gpio->chip.set = gw_i2c_pld_set8;
318 +
319 +       gpio->chip.label = client->name;
320 +
321 +       gpio->client = client;
322 +       i2c_set_clientdata(client, gpio);
323 +
324 +       gpio->out = 0xFF;
325 +
326 +       status = gpiochip_add(&gpio->chip);
327 +       if (status < 0)
328 +               goto fail;
329 +
330 +       dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
331 +                       gpio->chip.base,
332 +                       gpio->chip.base + gpio->chip.ngpio - 1,
333 +                       client->name,
334 +                       client->irq ? " (irq ignored)" : "");
335 +
336 +       /* Let platform code set up the GPIOs and their users.
337 +        * Now is the first time anyone could use them.
338 +        */
339 +       if (pdata->setup) {
340 +               status = pdata->setup(client,
341 +                               gpio->chip.base, gpio->chip.ngpio,
342 +                               pdata->context);
343 +               if (status < 0)
344 +                       dev_warn(&client->dev, "setup --> %d\n", status);
345 +       }
346 +
347 +       return 0;
348 +
349 +fail:
350 +       dev_dbg(&client->dev, "probe error %d for '%s'\n",
351 +                       status, client->name);
352 +       kfree(gpio);
353 +       return status;
354 +}
355 +
356 +static int gw_i2c_pld_remove(struct i2c_client *client)
357 +{
358 +       struct gw_i2c_pld_platform_data *pdata = client->dev.platform_data;
359 +       struct gw_i2c_pld *gpio = i2c_get_clientdata(client);
360 +       int                             status = 0;
361 +
362 +       if (pdata->teardown) {
363 +               status = pdata->teardown(client,
364 +                               gpio->chip.base, gpio->chip.ngpio,
365 +                               pdata->context);
366 +               if (status < 0) {
367 +                       dev_err(&client->dev, "%s --> %d\n",
368 +                                       "teardown", status);
369 +                       return status;
370 +               }
371 +       }
372 +
373 +       gpiochip_remove(&gpio->chip);
374 +       kfree(gpio);
375 +       return 0;
376 +}
377 +
378 +static struct i2c_driver gw_i2c_pld_driver = {
379 +       .driver = {
380 +               .name   = "gw_i2c_pld",
381 +               .owner  = THIS_MODULE,
382 +       },
383 +       .probe  = gw_i2c_pld_probe,
384 +       .remove = gw_i2c_pld_remove,
385 +       .id_table = gw_i2c_pld_id,
386 +};
387 +
388 +static int __init gw_i2c_pld_init(void)
389 +{
390 +       return i2c_add_driver(&gw_i2c_pld_driver);
391 +}
392 +module_init(gw_i2c_pld_init);
393 +
394 +static void __exit gw_i2c_pld_exit(void)
395 +{
396 +       i2c_del_driver(&gw_i2c_pld_driver);
397 +}
398 +module_exit(gw_i2c_pld_exit);
399 +
400 +MODULE_LICENSE("GPL");
401 +MODULE_AUTHOR("Chris Lang");
402 --- /dev/null
403 +++ b/include/linux/i2c/gw_i2c_pld.h
404 @@ -0,0 +1,20 @@
405 +#ifndef __LINUX_GW_I2C_PLD_H
406 +#define __LINUX_GW_I2C_PLD_H
407 +
408 +/**
409 + * The Gateworks I2C PLD Implements an additional 8 bits of GPIO through the PLD
410 + */
411 +
412 +struct gw_i2c_pld_platform_data {
413 +       unsigned gpio_base;
414 +       unsigned nr_gpio;
415 +       int             (*setup)(struct i2c_client *client,
416 +                                       int gpio, unsigned ngpio,
417 +                                       void *context);
418 +       int             (*teardown)(struct i2c_client *client,
419 +                                       int gpio, unsigned ngpio,
420 +                                       void *context);
421 +       void            *context;
422 +};
423 +
424 +#endif /* __LINUX_GW_I2C_PLD_H */