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