Root/target/linux/ixp4xx/patches-3.3/020-gateworks_i2c_pld.patch

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

Archive Download this file



interactive