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