summaryrefslogtreecommitdiffstats
path: root/meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch6095
1 files changed, 6095 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch b/meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch
new file mode 100644
index 0000000000..c36e5ba4ad
--- /dev/null
+++ b/meta-moblin/packages/linux/linux-moblin-2.6.29.1/linux-2.6.29-timberdale.patch
@@ -0,0 +1,6095 @@
1Patch provided by Mocean in order to enable the timberdale subsystem of the Russelville board.
2
3Signed-off-by: Joel Clark <joel.clark@intel.com>
4Acked-by: Arjan van de Ven <arjan@infradead.org>
5Signed-off-by: Todd Brandt todd.e.brandt@intel.com
6
7
8diff -uNr linux-2.6.29-clean/drivers/gpio/Kconfig linux-2.6.29/drivers/gpio/Kconfig
9--- linux-2.6.29-clean/drivers/gpio/Kconfig 2009-04-01 09:20:23.000000000 -0700
10+++ linux-2.6.29/drivers/gpio/Kconfig 2009-04-06 13:51:47.000000000 -0700
11@@ -161,6 +161,12 @@
12
13 If unsure, say N.
14
15+config GPIO_TIMBERDALE
16+ tristate "Support for timberdale GPIO"
17+ depends on MFD_TIMBERDALE && GPIOLIB
18+ ---help---
19+ Add support for GPIO usage of some pins of the timberdale FPGA.
20+
21 comment "SPI GPIO expanders:"
22
23 config GPIO_MAX7301
24diff -uNr linux-2.6.29-clean/drivers/gpio/Makefile linux-2.6.29/drivers/gpio/Makefile
25--- linux-2.6.29-clean/drivers/gpio/Makefile 2009-04-01 09:20:23.000000000 -0700
26+++ linux-2.6.29/drivers/gpio/Makefile 2009-04-06 13:51:47.000000000 -0700
27@@ -12,3 +12,4 @@
28 obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
29 obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
30 obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
31+obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
32diff -uNr linux-2.6.29-clean/drivers/gpio/timbgpio.c linux-2.6.29/drivers/gpio/timbgpio.c
33--- linux-2.6.29-clean/drivers/gpio/timbgpio.c 1969-12-31 16:00:00.000000000 -0800
34+++ linux-2.6.29/drivers/gpio/timbgpio.c 2009-04-06 13:51:47.000000000 -0700
35@@ -0,0 +1,275 @@
36+/*
37+ * timbgpio.c timberdale FPGA GPIO driver
38+ * Copyright (c) 2009 Intel Corporation
39+ *
40+ * This program is free software; you can redistribute it and/or modify
41+ * it under the terms of the GNU General Public License version 2 as
42+ * published by the Free Software Foundation.
43+ *
44+ * This program is distributed in the hope that it will be useful,
45+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
46+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47+ * GNU General Public License for more details.
48+ *
49+ * You should have received a copy of the GNU General Public License
50+ * along with this program; if not, write to the Free Software
51+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
52+ */
53+
54+/* Supports:
55+ * Timberdale FPGA GPIO
56+ */
57+
58+#include <linux/module.h>
59+#include <linux/gpio.h>
60+#include <linux/pci.h>
61+#include <linux/platform_device.h>
62+#include <linux/interrupt.h>
63+
64+#include "timbgpio.h"
65+
66+static u32 timbgpio_configure(struct gpio_chip *gpio, unsigned nr,
67+ unsigned off, unsigned val)
68+{
69+ struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
70+
71+ u32 config, oldconfig, wconfig;
72+
73+ mutex_lock(&tgpio->lock);
74+ config = ioread32(tgpio->membase + off);
75+ oldconfig = config;
76+
77+ if (val)
78+ config |= (1 << nr);
79+ else
80+ config &= ~(1 << nr);
81+
82+ iowrite32(config, tgpio->membase + off);
83+ wconfig = ioread32(tgpio->membase + off);
84+ mutex_unlock(&tgpio->lock);
85+
86+ return oldconfig;
87+}
88+
89+static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
90+{
91+ timbgpio_configure(gpio, nr, TGPIODIR, 1);
92+ return 0;
93+}
94+
95+static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
96+{
97+ struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
98+ u32 value;
99+
100+ value = ioread32(tgpio->membase + TGPIOVAL);
101+ return (value & (1 << nr)) ? 1 : 0;
102+}
103+
104+static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
105+ unsigned nr, int val)
106+{
107+ timbgpio_configure(gpio, nr, TGPIODIR, 0);
108+ return 0;
109+}
110+
111+
112+
113+static void timbgpio_gpio_set(struct gpio_chip *gpio,
114+ unsigned nr, int val)
115+{
116+ timbgpio_configure(gpio, nr, TGPIOVAL, val);
117+}
118+
119+/*
120+ * Function to control flank or level triggered GPIO pin
121+ * @nr - pin
122+ * @ val - 1: flank, 0: level
123+ *
124+ */
125+static void timbgpio_gpio_flnk_lvl_ctrl(struct gpio_chip *gpio,
126+ unsigned nr, int val)
127+{
128+ timbgpio_configure(gpio, nr, TGPIOFLK, val);
129+}
130+EXPORT_SYMBOL(timbgpio_gpio_flnk_lvl_ctrl);
131+
132+/*
133+ * Enable or disable interrupt
134+ *
135+ */
136+static void timbgpio_gpio_int_ctrl(struct gpio_chip *gpio,
137+ unsigned nr, int val)
138+{
139+ timbgpio_configure(gpio, nr, TGPIOINT, val);
140+}
141+EXPORT_SYMBOL(timbgpio_gpio_int_ctrl);
142+
143+/*
144+ * @val - 1: Asserted high or on positive flank, 0: Asserted low or on negative flank
145+ *
146+ */
147+static void timbgpio_gpio_lvl_ctrl(struct gpio_chip *gpio,
148+ unsigned nr, int val)
149+{
150+ timbgpio_configure(gpio, nr, TGPIOLVL, val);
151+}
152+EXPORT_SYMBOL(timbgpio_gpio_lvl_ctrl);
153+
154+static void timbgpio_gpio_int_clr(struct gpio_chip *gpio,
155+ unsigned nr, int val)
156+{
157+ timbgpio_configure(gpio, nr, TGPIOINT_CLR, val);
158+}
159+EXPORT_SYMBOL(timbgpio_gpio_int_clr);
160+
161+
162+static irqreturn_t timbgpio_handleinterrupt(int irq, void *devid)
163+{
164+ struct timbgpio *tgpio = (struct timbgpio *)devid;
165+
166+ iowrite32(0xffffffff, tgpio->membase + TGPIOINT_CLR);
167+
168+ return IRQ_HANDLED;
169+}
170+
171+static int timbgpio_probe(struct platform_device *dev)
172+{
173+ int err, irq;
174+ struct gpio_chip *gc;
175+ struct timbgpio *tgpio;
176+ struct resource *iomem, *rscr;
177+
178+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
179+ if (!iomem) {
180+ err = -EINVAL;
181+ goto err_mem;
182+ }
183+
184+ tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
185+ if (!tgpio) {
186+ err = -EINVAL;
187+ goto err_mem;
188+ }
189+
190+ mutex_init(&tgpio->lock);
191+
192+ rscr = &tgpio->rscr;
193+ rscr->name = "timb-gpio";
194+ rscr->start = iomem->start;
195+ rscr->end = iomem->end;
196+ rscr->flags = IORESOURCE_MEM;
197+
198+ err = request_resource(iomem, rscr);
199+ if (err)
200+ goto err_request;
201+
202+ tgpio->membase = ioremap(rscr->start, resource_size(rscr));
203+ if (!tgpio->membase) {
204+ err = -ENOMEM;
205+ goto err_ioremap;
206+ }
207+
208+ gc = &tgpio->gpio;
209+
210+ gc->label = "timbgpio";
211+ gc->owner = THIS_MODULE;
212+ gc->direction_input = timbgpio_gpio_direction_input;
213+ gc->get = timbgpio_gpio_get;
214+ gc->direction_output = timbgpio_gpio_direction_output;
215+ gc->set = timbgpio_gpio_set;
216+ gc->dbg_show = NULL;
217+ gc->base = 0;
218+ gc->ngpio = TIMB_NR_GPIOS;
219+ gc->can_sleep = 0;
220+
221+ err = gpiochip_add(gc);
222+ if (err)
223+ goto err_chipadd;
224+
225+ platform_set_drvdata(dev, tgpio);
226+
227+ /* register interrupt */
228+ irq = platform_get_irq(dev, 0);
229+ if (irq < 0)
230+ goto err_get_irq;
231+
232+ /* clear pending interrupts */
233+ iowrite32(0xffffffff, tgpio->membase + TGPIOINT_CLR);
234+ iowrite32(0x0, tgpio->membase + TGPIOINT);
235+
236+ /* request IRQ */
237+ err = request_irq(irq, timbgpio_handleinterrupt, IRQF_SHARED,
238+ "timb-gpio", tgpio);
239+ if (err) {
240+ printk(KERN_ERR "timbgpio: Failed to request IRQ\n");
241+ goto err_get_irq;
242+ }
243+
244+ return err;
245+
246+err_get_irq:
247+ err = gpiochip_remove(&tgpio->gpio);
248+ if (err)
249+ printk(KERN_ERR "timbgpio: failed to remove gpio_chip\n");
250+err_chipadd:
251+ iounmap(tgpio->membase);
252+err_ioremap:
253+ release_resource(&tgpio->rscr);
254+err_request:
255+ kfree(tgpio);
256+err_mem:
257+ printk(KERN_ERR "timberdale: Failed to register GPIOs: %d\n", err);
258+
259+ return err;
260+}
261+
262+static int timbgpio_remove(struct platform_device *dev)
263+{
264+ int err;
265+ struct timbgpio *tgpio = platform_get_drvdata(dev);
266+
267+ /* disable interrupts */
268+ iowrite32(0x0, tgpio->membase + TGPIOINT);
269+
270+ free_irq(platform_get_irq(dev, 0), tgpio);
271+ err = gpiochip_remove(&tgpio->gpio);
272+ if (err)
273+ printk(KERN_ERR "timbgpio: failed to remove gpio_chip\n");
274+
275+ iounmap(tgpio->membase);
276+ release_resource(&tgpio->rscr);
277+ kfree(tgpio);
278+
279+ return 0;
280+}
281+
282+static struct platform_driver timbgpio_platform_driver = {
283+ .driver = {
284+ .name = "timb-gpio",
285+ .owner = THIS_MODULE,
286+ },
287+ .probe = timbgpio_probe,
288+ .remove = timbgpio_remove,
289+};
290+
291+/*--------------------------------------------------------------------------*/
292+
293+static int __init timbgpio_init(void)
294+{
295+ return platform_driver_register(&timbgpio_platform_driver);
296+}
297+
298+static void __exit timbgpio_exit(void)
299+{
300+ platform_driver_unregister(&timbgpio_platform_driver);
301+}
302+
303+module_init(timbgpio_init);
304+module_exit(timbgpio_exit);
305+
306+MODULE_DESCRIPTION("Timberdale GPIO driver");
307+MODULE_LICENSE("GPL v2");
308+MODULE_AUTHOR("Mocean Laboratories");
309+MODULE_ALIAS("platform:timb-gpio");
310+
311diff -uNr linux-2.6.29-clean/drivers/gpio/timbgpio.h linux-2.6.29/drivers/gpio/timbgpio.h
312--- linux-2.6.29-clean/drivers/gpio/timbgpio.h 1969-12-31 16:00:00.000000000 -0800
313+++ linux-2.6.29/drivers/gpio/timbgpio.h 2009-04-06 13:51:47.000000000 -0700
314@@ -0,0 +1,48 @@
315+/*
316+ * timbgpio.h timberdale FPGA GPIO driver defines
317+ * Copyright (c) 2009 Intel Corporation
318+ *
319+ * This program is free software; you can redistribute it and/or modify
320+ * it under the terms of the GNU General Public License version 2 as
321+ * published by the Free Software Foundation.
322+ *
323+ * This program is distributed in the hope that it will be useful,
324+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
325+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
326+ * GNU General Public License for more details.
327+ *
328+ * You should have received a copy of the GNU General Public License
329+ * along with this program; if not, write to the Free Software
330+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
331+ */
332+
333+/* Supports:
334+ * Timberdale FPGA GPIO
335+ */
336+
337+#ifndef _TIMBGPIO_H_
338+#define _TIMBGPIO_H_
339+
340+#include <linux/mutex.h>
341+#include <linux/gpio.h>
342+
343+#define TIMB_NR_GPIOS 16
344+
345+#define TGPIOVAL 0
346+#define TGPIODIR 0x04
347+#define TGPIOINT 0x08
348+#define TGPIOINT_STATUS 0x0c
349+#define TGPIOINT_PENDING 0x10
350+#define TGPIOINT_CLR 0x14
351+#define TGPIOFLK 0x18
352+#define TGPIOLVL 0x1c
353+
354+struct timbgpio {
355+ void __iomem *membase;
356+ struct resource rscr;
357+ struct mutex lock; /* mutual exclusion */
358+ struct pci_dev *pdev;
359+ struct gpio_chip gpio;
360+};
361+
362+#endif
363diff -uNr linux-2.6.29-clean/drivers/i2c/busses/i2c-ocores.c linux-2.6.29/drivers/i2c/busses/i2c-ocores.c
364--- linux-2.6.29-clean/drivers/i2c/busses/i2c-ocores.c 2009-04-01 09:20:24.000000000 -0700
365+++ linux-2.6.29/drivers/i2c/busses/i2c-ocores.c 2009-04-06 13:51:47.000000000 -0700
366@@ -216,6 +216,7 @@
367 struct ocores_i2c_platform_data *pdata;
368 struct resource *res, *res2;
369 int ret;
370+ u8 i;
371
372 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
373 if (!res)
374@@ -271,6 +272,10 @@
375 goto add_adapter_failed;
376 }
377
378+ /* add in known devices to the bus */
379+ for (i = 0; i < pdata->num_devices; i++)
380+ i2c_new_device(&i2c->adap, pdata->devices + i);
381+
382 return 0;
383
384 add_adapter_failed:
385diff -uNr linux-2.6.29-clean/drivers/input/touchscreen/Kconfig linux-2.6.29/drivers/input/touchscreen/Kconfig
386--- linux-2.6.29-clean/drivers/input/touchscreen/Kconfig 2009-04-01 09:20:23.000000000 -0700
387+++ linux-2.6.29/drivers/input/touchscreen/Kconfig 2009-04-06 13:51:47.000000000 -0700
388@@ -397,6 +397,17 @@
389 To compile this driver as a module, choose M here: the
390 module will be called touchit213.
391
392+config TOUCHSCREEN_TSC2003
393+ tristate "TSC2003 based touchscreens"
394+ depends on I2C
395+ help
396+ Say Y here if you have a TSC2003 based touchscreen.
397+
398+ If unsure, say N.
399+
400+ To compile this driver as a module, choose M here: the
401+ module will be called tsc2003.
402+
403 config TOUCHSCREEN_TSC2007
404 tristate "TSC2007 based touchscreens"
405 depends on I2C
406diff -uNr linux-2.6.29-clean/drivers/input/touchscreen/Makefile linux-2.6.29/drivers/input/touchscreen/Makefile
407--- linux-2.6.29-clean/drivers/input/touchscreen/Makefile 2009-04-01 09:20:23.000000000 -0700
408+++ linux-2.6.29/drivers/input/touchscreen/Makefile 2009-04-06 13:51:47.000000000 -0700
409@@ -25,6 +25,7 @@
410 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
411 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
412 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
413+obj-$(CONFIG_TOUCHSCREEN_TSC2003) += tsc2003.o
414 obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
415 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
416 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
417diff -uNr linux-2.6.29-clean/drivers/input/touchscreen/tsc2003.c linux-2.6.29/drivers/input/touchscreen/tsc2003.c
418--- linux-2.6.29-clean/drivers/input/touchscreen/tsc2003.c 1969-12-31 16:00:00.000000000 -0800
419+++ linux-2.6.29/drivers/input/touchscreen/tsc2003.c 2009-04-06 13:51:47.000000000 -0700
420@@ -0,0 +1,387 @@
421+/*
422+ * tsc2003.c Driver for TI TSC2003 touch screen controller
423+ * Copyright (c) 2009 Intel Corporation
424+ *
425+ * This program is free software; you can redistribute it and/or modify
426+ * it under the terms of the GNU General Public License version 2 as
427+ * published by the Free Software Foundation.
428+ *
429+ * This program is distributed in the hope that it will be useful,
430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432+ * GNU General Public License for more details.
433+ *
434+ * You should have received a copy of the GNU General Public License
435+ * along with this program; if not, write to the Free Software
436+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
437+ */
438+
439+/* Supports:
440+ * TI TSC2003
441+ *
442+ * Inspired by tsc2007, Copyright (c) 2008 MtekVision Co., Ltd.
443+ */
444+#include <linux/module.h>
445+#include <linux/input.h>
446+#include <linux/interrupt.h>
447+#include <linux/i2c.h>
448+#include <linux/i2c/tsc2007.h>
449+#include <linux/kthread.h>
450+#include <linux/semaphore.h>
451+
452+#define TSC2003_DRIVER_NAME "tsc2003"
453+
454+#define TS_POLL_PERIOD 20 /* ms delay between samples */
455+
456+#define TSC2003_MEASURE_TEMP0 (0x0 << 4)
457+#define TSC2003_MEASURE_AUX (0x2 << 4)
458+#define TSC2003_MEASURE_TEMP1 (0x4 << 4)
459+#define TSC2003_ACTIVATE_XN (0x8 << 4)
460+#define TSC2003_ACTIVATE_YN (0x9 << 4)
461+#define TSC2003_ACTIVATE_YP_XN (0xa << 4)
462+#define TSC2003_SETUP (0xb << 4)
463+#define TSC2003_MEASURE_X (0xc << 4)
464+#define TSC2003_MEASURE_Y (0xd << 4)
465+#define TSC2003_MEASURE_Z1 (0xe << 4)
466+#define TSC2003_MEASURE_Z2 (0xf << 4)
467+
468+#define TSC2003_POWER_OFF_IRQ_EN (0x0 << 2)
469+#define TSC2003_ADC_ON_IRQ_DIS0 (0x1 << 2)
470+#define TSC2003_ADC_OFF_IRQ_EN (0x2 << 2)
471+#define TSC2003_ADC_ON_IRQ_DIS1 (0x3 << 2)
472+
473+#define TSC2003_12BIT (0x0 << 1)
474+#define TSC2003_8BIT (0x1 << 1)
475+
476+#define MAX_12BIT ((1 << 12) - 1)
477+
478+#define ADC_ON_12BIT (TSC2003_12BIT | TSC2003_ADC_ON_IRQ_DIS0)
479+
480+#define READ_Y (ADC_ON_12BIT | TSC2003_MEASURE_Y)
481+#define READ_Z1 (ADC_ON_12BIT | TSC2003_MEASURE_Z1)
482+#define READ_Z2 (ADC_ON_12BIT | TSC2003_MEASURE_Z2)
483+#define READ_X (ADC_ON_12BIT | TSC2003_MEASURE_X)
484+#define PWRDOWN (TSC2003_12BIT | TSC2003_POWER_OFF_IRQ_EN)
485+
486+struct ts_event {
487+ int x;
488+ int y;
489+ int z1, z2;
490+};
491+
492+struct tsc2003 {
493+ struct input_dev *input;
494+ char phys[32];
495+ struct task_struct *task;
496+ struct ts_event tc;
497+ struct completion penirq_completion;
498+
499+ struct i2c_client *client;
500+
501+ u16 model;
502+ u16 x_plate_ohms;
503+
504+ unsigned pendown;
505+};
506+
507+static inline int tsc2003_xfer(struct tsc2003 *tsc, u8 cmd)
508+{
509+ s32 data;
510+ u16 val;
511+
512+ data = i2c_smbus_read_word_data(tsc->client, cmd);
513+ if (data < 0) {
514+ dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
515+ return data;
516+ }
517+
518+ /* The protocol and raw data format from i2c interface:
519+ * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
520+ * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
521+ */
522+ val = swab16(data) >> 4;
523+
524+ dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
525+
526+ return val;
527+}
528+
529+static void tsc2003_send_event(void *tsc)
530+{
531+ struct tsc2003 *ts = tsc;
532+ struct input_dev *input = ts->input;
533+ u32 rt = 0;
534+ u16 x, y, z1, z2;
535+
536+ x = ts->tc.x;
537+ y = ts->tc.y;
538+ z1 = ts->tc.z1;
539+ z2 = ts->tc.z2;
540+
541+ /* range filtering */
542+ if (x == MAX_12BIT)
543+ x = 0;
544+
545+ if (likely(x && z1)) {
546+ /* compute touch pressure resistance using equation #1 */
547+ rt = z2;
548+ rt -= z1;
549+ rt *= x;
550+ rt *= ts->x_plate_ohms;
551+ rt /= z1;
552+ rt = (rt + 2047) >> 12;
553+ }
554+
555+ /* Sample found inconsistent by debouncing or pressure is beyond
556+ * the maximum. Don't report it to user space, repeat at least
557+ * once more the measurement
558+ */
559+ if (rt > MAX_12BIT)
560+ return;
561+
562+ /* NOTE: We can't rely on the pressure to determine the pen down
563+ * state, even this controller has a pressure sensor. The pressure
564+ * value can fluctuate for quite a while after lifting the pen and
565+ * in some cases may not even settle at the expected value.
566+ *
567+ * The only safe way to check for the pen up condition is in the
568+ * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
569+ */
570+ if (rt) {
571+ if (!ts->pendown) {
572+ dev_dbg(&ts->client->dev, "DOWN\n");
573+
574+ input_report_key(input, BTN_TOUCH, 1);
575+ ts->pendown = 1;
576+ }
577+
578+ input_report_abs(input, ABS_X, x);
579+ input_report_abs(input, ABS_Y, y);
580+ input_report_abs(input, ABS_PRESSURE, rt);
581+
582+ input_sync(input);
583+
584+ dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
585+ x, y, rt);
586+ } else if (ts->pendown) {
587+ /* pen up */
588+ dev_dbg(&ts->client->dev, "UP\n");
589+ input_report_key(input, BTN_TOUCH, 0);
590+ input_report_abs(input, ABS_PRESSURE, 0);
591+ input_sync(input);
592+
593+ ts->pendown = 0;
594+ }
595+}
596+
597+static int tsc2003_power_off_irq_en(struct tsc2003 *tsc)
598+{
599+ /* power down */
600+ return tsc2003_xfer(tsc, PWRDOWN);
601+}
602+
603+static int tsc2003_read_values(struct tsc2003 *tsc)
604+{
605+ /* y- still on; turn on only y+ (and ADC) */
606+ tsc->tc.y = tsc2003_xfer(tsc, READ_Y);
607+ if (tsc->tc.y < 0)
608+ return tsc->tc.y;
609+
610+ /* turn y- off, x+ on, then leave in lowpower */
611+ tsc->tc.x = tsc2003_xfer(tsc, READ_X);
612+ if (tsc->tc.x < 0)
613+ return tsc->tc.x;
614+
615+ /* turn y+ off, x- on; we'll use formula #1 */
616+ tsc->tc.z1 = tsc2003_xfer(tsc, READ_Z1);
617+ if (tsc->tc.z1 < 0)
618+ return tsc->tc.z1;
619+
620+ tsc->tc.z2 = tsc2003_xfer(tsc, READ_Z2);
621+ if (tsc->tc.z2 < 0)
622+ return tsc->tc.z2;
623+
624+ return 0;
625+}
626+
627+
628+static irqreturn_t tsc2003_irq(int irq, void *handle)
629+{
630+ struct tsc2003 *ts = handle;
631+
632+ /* do not call the synced version -> deadlock */
633+ disable_irq_nosync(irq);
634+ /* signal the thread to continue */
635+ complete(&ts->penirq_completion);
636+
637+ return IRQ_HANDLED;
638+}
639+
640+static int tsc2003_thread(void *d)
641+{
642+ struct tsc2003 *ts = (struct tsc2003 *)d;
643+ int ret;
644+
645+ allow_signal(SIGKILL);
646+
647+ while (!signal_pending(current)) {
648+ /* power down and wait for interrupt */
649+ do {
650+ /* loop because the I2C bus might be busy */
651+ ret = msleep_interruptible(TS_POLL_PERIOD);
652+ if (!ret)
653+ ret = tsc2003_power_off_irq_en(ts);
654+ } while (ret == -EAGAIN && !signal_pending(current));
655+
656+ if (signal_pending(current))
657+ break;
658+
659+ ret = wait_for_completion_interruptible(&ts->penirq_completion);
660+ if (!ret) {
661+ int first = 1;
662+ /* got IRQ, start poll, until pen is up */
663+ while (!ret && !signal_pending(current)
664+ && (first || ts->pendown)) {
665+ ret = tsc2003_read_values(ts);
666+ if (!ret)
667+ tsc2003_send_event(ts);
668+ ret = msleep_interruptible(TS_POLL_PERIOD);
669+ first = 0;
670+ }
671+
672+ /* we re enable the interrupt */
673+ if (!signal_pending(current))
674+ enable_irq(ts->client->irq);
675+ }
676+ }
677+
678+ return 0;
679+}
680+
681+static int tsc2003_probe(struct i2c_client *client,
682+ const struct i2c_device_id *id)
683+{
684+ struct tsc2003 *ts;
685+ struct tsc2007_platform_data *pdata = client->dev.platform_data;
686+ struct input_dev *input_dev;
687+ int err;
688+
689+ if (!pdata) {
690+ dev_err(&client->dev, "platform data is required!\n");
691+ return -EINVAL;
692+ }
693+
694+ if (!i2c_check_functionality(client->adapter,
695+ I2C_FUNC_SMBUS_READ_WORD_DATA))
696+ return -EIO;
697+
698+ ts = kzalloc(sizeof(struct tsc2003), GFP_KERNEL);
699+ input_dev = input_allocate_device();
700+ if (!ts || !input_dev) {
701+ err = -ENOMEM;
702+ goto err_free_mem;
703+ }
704+
705+ ts->client = client;
706+ i2c_set_clientdata(client, ts);
707+
708+ ts->input = input_dev;
709+
710+ ts->model = pdata->model;
711+ ts->x_plate_ohms = pdata->x_plate_ohms;
712+
713+ snprintf(ts->phys, sizeof(ts->phys),
714+ "%s/input0", dev_name(&client->dev));
715+
716+ input_dev->name = TSC2003_DRIVER_NAME" Touchscreen";
717+ input_dev->phys = ts->phys;
718+ input_dev->id.bustype = BUS_I2C;
719+
720+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
721+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
722+
723+ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
724+ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
725+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
726+
727+ init_completion(&ts->penirq_completion);
728+
729+ ts->task = kthread_run(tsc2003_thread, ts, TSC2003_DRIVER_NAME);
730+ if (IS_ERR(ts->task)) {
731+ err = PTR_ERR(ts->task);
732+ goto err_free_mem;
733+ }
734+
735+ err = request_irq(client->irq, tsc2003_irq, 0,
736+ client->dev.driver->name, ts);
737+ if (err < 0) {
738+ dev_err(&client->dev, "irq %d busy?\n", client->irq);
739+ goto err_free_thread;
740+ }
741+
742+ err = input_register_device(input_dev);
743+ if (err)
744+ goto err_free_irq;
745+
746+ dev_info(&client->dev, "registered with irq (%d)\n", client->irq);
747+
748+ return 0;
749+
750+ err_free_irq:
751+ free_irq(client->irq, ts);
752+ err_free_thread:
753+ kthread_stop(ts->task);
754+ err_free_mem:
755+ input_free_device(input_dev);
756+ kfree(ts);
757+ return err;
758+}
759+
760+static int tsc2003_remove(struct i2c_client *client)
761+{
762+ struct tsc2003 *ts = i2c_get_clientdata(client);
763+
764+ free_irq(client->irq, ts);
765+ send_sig(SIGKILL, ts->task, 1);
766+ kthread_stop(ts->task);
767+ input_unregister_device(ts->input);
768+ kfree(ts);
769+
770+ return 0;
771+}
772+
773+static struct i2c_device_id tsc2003_idtable[] = {
774+ { TSC2003_DRIVER_NAME, 0 },
775+ { }
776+};
777+
778+MODULE_DEVICE_TABLE(i2c, tsc2003_idtable);
779+
780+static struct i2c_driver tsc2003_driver = {
781+ .driver = {
782+ .owner = THIS_MODULE,
783+ .name = TSC2003_DRIVER_NAME,
784+ .bus = &i2c_bus_type,
785+ },
786+ .id_table = tsc2003_idtable,
787+ .probe = tsc2003_probe,
788+ .remove = tsc2003_remove,
789+};
790+
791+static int __init tsc2003_init(void)
792+{
793+ return i2c_add_driver(&tsc2003_driver);
794+}
795+
796+static void __exit tsc2003_exit(void)
797+{
798+ i2c_del_driver(&tsc2003_driver);
799+}
800+
801+module_init(tsc2003_init);
802+module_exit(tsc2003_exit);
803+
804+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
805+MODULE_DESCRIPTION("TSC2003 TouchScreen Driver");
806+MODULE_LICENSE("GPL v2");
807+
808diff -uNr linux-2.6.29-clean/drivers/media/video/adv7180.c linux-2.6.29/drivers/media/video/adv7180.c
809--- linux-2.6.29-clean/drivers/media/video/adv7180.c 1969-12-31 16:00:00.000000000 -0800
810+++ linux-2.6.29/drivers/media/video/adv7180.c 2009-04-06 13:51:47.000000000 -0700
811@@ -0,0 +1,361 @@
812+/*
813+ * adv7180.c Analog Devices ADV7180 video decoder driver
814+ * Copyright (c) 2009 Intel Corporation
815+ *
816+ * This program is free software; you can redistribute it and/or modify
817+ * it under the terms of the GNU General Public License version 2 as
818+ * published by the Free Software Foundation.
819+ *
820+ * This program is distributed in the hope that it will be useful,
821+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
822+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
823+ * GNU General Public License for more details.
824+ *
825+ * You should have received a copy of the GNU General Public License
826+ * along with this program; if not, write to the Free Software
827+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
828+ */
829+
830+#include <linux/module.h>
831+#include <linux/init.h>
832+#include <linux/interrupt.h>
833+#include <linux/delay.h>
834+#include <linux/errno.h>
835+#include <linux/fs.h>
836+#include <linux/kernel.h>
837+#include <linux/major.h>
838+#include <linux/slab.h>
839+#include <linux/mm.h>
840+#include <linux/signal.h>
841+#include <linux/types.h>
842+#include <linux/io.h>
843+#include <asm/pgtable.h>
844+#include <asm/page.h>
845+#include <linux/uaccess.h>
846+
847+#include <linux/i2c-ocores.h>
848+#include <linux/platform_device.h>
849+#include <linux/i2c.h>
850+#include <linux/i2c-id.h>
851+#include <linux/videodev.h>
852+#include <linux/video_decoder.h>
853+#include <media/v4l2-ioctl.h>
854+#include <media/adv7180.h>
855+
856+
857+MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
858+MODULE_AUTHOR("Mocean Laboratories");
859+MODULE_LICENSE("GPL v2");
860+
861+static inline int adv7180_write(struct i2c_client *client,
862+ u8 reg, u8 value)
863+{
864+ struct adv7180 *decoder = i2c_get_clientdata(client);
865+
866+ decoder->reg[reg] = value;
867+ return i2c_smbus_write_byte_data(client, reg, value);
868+}
869+
870+static inline int adv7180_read(struct i2c_client *client, u8 reg)
871+{
872+ return i2c_smbus_read_byte_data(client, reg);
873+}
874+
875+static int adv7180_write_block(struct i2c_client *client,
876+ const u8 *data, unsigned int len)
877+{
878+ int ret = -1;
879+ u8 reg;
880+
881+ /* the adv7180 has an autoincrement function, use it if
882+ * the adapter understands raw I2C */
883+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
884+ /* do raw I2C, not smbus compatible */
885+ struct adv7180 *decoder = i2c_get_clientdata(client);
886+ u8 block_data[32];
887+ int block_len;
888+
889+ while (len >= 2) {
890+ block_len = 0;
891+ reg = data[0];
892+ block_data[block_len++] = reg;
893+ do {
894+ block_data[block_len++] =
895+ decoder->reg[reg++] = data[1];
896+ len -= 2;
897+ data += 2;
898+ } while (len >= 2 && data[0] == reg &&
899+ block_len < 32);
900+
901+ ret = i2c_master_send(client, block_data, block_len);
902+ if (ret < 0)
903+ break;
904+ }
905+ } else {
906+ /* do some slow I2C emulation kind of thing */
907+ while (len >= 2) {
908+ reg = *data++;
909+ ret = adv7180_write(client, reg, *data++);
910+ if (ret < 0)
911+ break;
912+
913+ len -= 2;
914+ }
915+ }
916+
917+ return ret;
918+}
919+#ifdef CONFIG_MFD_TIMBERDALE
920+static irqreturn_t adv7180_irq(int irq, void *dev_id)
921+{
922+ struct adv7180 *decoder = (struct adv7180 *) dev_id;
923+
924+ /* Activate access to sub-regs */
925+ adv7180_write(decoder->client, ADV7180_ADI_CTRL, ADI_ENABLE);
926+
927+ /* TODO: implement a real interrupt handler
928+ * for now just
929+ * clear all four regs
930+ */
931+ adv7180_write_block(decoder->client, reset_icr, sizeof(reset_icr));
932+
933+ return IRQ_HANDLED;
934+}
935+#endif
936+static int adv7180_command(struct i2c_client *client,
937+ unsigned int cmd, void *arg)
938+{
939+ struct adv7180 *decoder = i2c_get_clientdata(client);
940+ int *iarg = (int *)arg;
941+ int status;
942+
943+ switch (cmd) {
944+
945+ case DECODER_INIT:
946+ adv7180_write(client, 0x0f, 0x80); /* Reset */
947+ break;
948+
949+ case DECODER_GET_CAPABILITIES:
950+ {
951+ struct video_decoder_capability *cap = arg;
952+ cap->flags = VIDEO_DECODER_PAL |
953+ VIDEO_DECODER_NTSC |
954+ VIDEO_DECODER_SECAM |
955+ VIDEO_DECODER_AUTO;
956+ cap->inputs = 3;
957+ cap->outputs = 1;
958+ }
959+ break;
960+
961+ case DECODER_GET_STATUS:
962+ {
963+ *iarg = 0;
964+ status = adv7180_read(client, ADV7180_SR);
965+ if ((status & ADV7180_STATUS_PAL))
966+ *iarg = (*iarg | DECODER_STATUS_PAL);
967+
968+ if ((status & ADV7180_STATUS_NTSC))
969+ *iarg = (*iarg | DECODER_STATUS_NTSC);
970+
971+ if ((status & ADV7180_STATUS_SECAM))
972+ *iarg = (*iarg | DECODER_STATUS_SECAM);
973+ }
974+ break;
975+
976+ case DECODER_SET_NORM:
977+ {
978+ int v = *(int *) arg;
979+ if (decoder->norm != v) {
980+ decoder->norm = v;
981+ switch (v) {
982+ case VIDEO_MODE_NTSC:
983+ adv7180_write(client, ADV7180_IN_CTRL, 0x40);
984+ break;
985+ case VIDEO_MODE_PAL:
986+ adv7180_write(client, ADV7180_IN_CTRL, 0x70);
987+ break;
988+ case VIDEO_MODE_SECAM:
989+ adv7180_write(client, ADV7180_IN_CTRL, 0x90);
990+ break;
991+ case VIDEO_MODE_AUTO:
992+ adv7180_write(client, ADV7180_IN_CTRL, 0x00);
993+ break;
994+ default:
995+ return -EPERM;
996+ }
997+ }
998+ }
999+ break;
1000+
1001+ case DECODER_SET_INPUT:
1002+ {
1003+ int v = *(int *) arg;
1004+ if (decoder->input != v) {
1005+ decoder->input = v;
1006+
1007+ switch (v) {
1008+ case CVBS:
1009+ adv7180_write_block(client, init_cvbs_64,
1010+ sizeof(init_cvbs_64));
1011+ break;
1012+ case SVIDEO:
1013+ adv7180_write_block(client, init_svideo_64,
1014+ sizeof(init_svideo_64));
1015+ break;
1016+ case YPbPr:
1017+ adv7180_write_block(client, init_ypbpr_64,
1018+ sizeof(init_ypbpr_64));
1019+ break;
1020+ default:
1021+ return -EINVAL;
1022+ }
1023+ }
1024+ }
1025+ break;
1026+
1027+ case DECODER_SET_OUTPUT:
1028+ {
1029+ }
1030+ break;
1031+
1032+ case DECODER_ENABLE_OUTPUT:
1033+ {
1034+ }
1035+ break;
1036+
1037+ case DECODER_SET_PICTURE:
1038+ {
1039+ }
1040+ break;
1041+
1042+ case DECODER_DUMP:
1043+ {
1044+ adv7180_write(client, 1, 0x88);
1045+ }
1046+ break;
1047+
1048+ default:
1049+ return -EINVAL;
1050+ }
1051+ return 0;
1052+}
1053+
1054+/* ----------------------------------------------------------------------- */
1055+
1056+/*
1057+ * Generic i2c probe
1058+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
1059+ */
1060+static unsigned short normal_i2c[] = {
1061+ 0x40 >> 1, 0x41 >> 1,
1062+ I2C_ADV7180 >> 1, 0x43 >> 1,
1063+ I2C_CLIENT_END
1064+};
1065+
1066+I2C_CLIENT_INSMOD;
1067+
1068+static int adv7180_detect(struct i2c_client *client, int kind,
1069+ struct i2c_board_info *info)
1070+{
1071+ struct i2c_adapter *adapter = client->adapter;
1072+
1073+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
1074+ | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
1075+ return -ENODEV;
1076+
1077+ /* Is chip alive ? */
1078+ if (adv7180_read(client, 0x11) != 0x1b)
1079+ return -ENODEV;
1080+
1081+ strlcpy(info->type, DRIVER_NAME, I2C_NAME_SIZE);
1082+
1083+ return 0;
1084+}
1085+
1086+static int adv7180_probe(struct i2c_client *client,
1087+ const struct i2c_device_id *id)
1088+{
1089+ int err = 0;
1090+ struct adv7180 *decoder;
1091+
1092+ printk(KERN_INFO DRIVER_NAME" chip found @ 0x%x (%s)\n",
1093+ client->addr << 1, client->adapter->name);
1094+
1095+ decoder = kzalloc(sizeof(struct adv7180), GFP_KERNEL);
1096+ if (decoder == NULL)
1097+ return -ENOMEM;
1098+
1099+ decoder->norm = VIDEO_MODE_PAL | VIDEO_MODE_NTSC |
1100+ VIDEO_MODE_SECAM |
1101+ VIDEO_MODE_AUTO;
1102+ decoder->input = CVBS;
1103+ decoder->enable = 1;
1104+ decoder->client = client;
1105+ i2c_set_clientdata(client, decoder);
1106+#ifdef CONFIG_MFD_TIMBERDALE
1107+ err = request_irq(client->irq, adv7180_irq, 0,
1108+ client->dev.driver->name, decoder);
1109+ if (err < 0) {
1110+ dev_err(&client->dev, "irq %d busy?\n", client->irq);
1111+ goto err_free_dec;
1112+ }
1113+ dev_info(&client->dev, "registered with irq (%d)\n", client->irq);
1114+#endif
1115+ adv7180_command(client, DECODER_INIT, NULL); /* Reset */
1116+
1117+ return 0;
1118+#ifdef CONFIG_MFD_TIMBERDALE
1119+err_free_dec:
1120+ kfree(decoder);
1121+
1122+ return err;
1123+#endif
1124+}
1125+
1126+static int adv7180_remove(struct i2c_client *client)
1127+{
1128+ struct adv7180 *decoder = i2c_get_clientdata(client);
1129+#ifdef CONFIG_MFD_TIMBERDALE
1130+ free_irq(client->irq, decoder);
1131+#endif
1132+ kfree(decoder);
1133+ return 0;
1134+}
1135+
1136+/* ----------------------------------------------------------------------- */
1137+static const struct i2c_device_id adv7180_id[] = {
1138+ { DRIVER_NAME, 0 },
1139+ { }
1140+};
1141+MODULE_DEVICE_TABLE(i2c, adv7180_id);
1142+
1143+static struct i2c_driver i2c_driver_adv7180 = {
1144+ .driver = {
1145+ .owner = THIS_MODULE,
1146+ .name = DRIVER_NAME,
1147+ .bus = &i2c_bus_type,
1148+ },
1149+
1150+ .id_table = adv7180_id,
1151+ .probe = adv7180_probe,
1152+ .remove = adv7180_remove,
1153+
1154+ .class = 0xffffffff,
1155+ .detect = adv7180_detect,
1156+ .address_data = &addr_data,
1157+
1158+ .command = adv7180_command,
1159+};
1160+
1161+static int __init adv7180_init(void)
1162+{
1163+ return i2c_add_driver(&i2c_driver_adv7180);
1164+}
1165+
1166+static void __exit adv7180_exit(void)
1167+{
1168+ i2c_del_driver(&i2c_driver_adv7180);
1169+}
1170+
1171+module_init(adv7180_init);
1172+module_exit(adv7180_exit);
1173diff -uNr linux-2.6.29-clean/drivers/media/video/Kconfig linux-2.6.29/drivers/media/video/Kconfig
1174--- linux-2.6.29-clean/drivers/media/video/Kconfig 2009-04-01 09:20:24.000000000 -0700
1175+++ linux-2.6.29/drivers/media/video/Kconfig 2009-04-06 13:51:47.000000000 -0700
1176@@ -251,6 +251,15 @@
1177
1178 comment "Video decoders"
1179
1180+config VIDEO_ADV7180
1181+ tristate "Analog Devices ADV7180 decoder"
1182+ depends on VIDEO_V4L1 && I2C
1183+ ---help---
1184+ Support for the Analog Devices ADV7180 video decoder.
1185+
1186+ To compile this driver as a module, choose M here: the
1187+ module will be called adv7180.
1188+
1189 config VIDEO_BT819
1190 tristate "BT819A VideoStream decoder"
1191 depends on VIDEO_V4L1 && I2C
1192@@ -800,6 +809,12 @@
1193 ---help---
1194 This is a v4l2 driver for the TI OMAP2 camera capture interface
1195
1196+config VIDEO_TIMBERDALE
1197+ tristate "Support for timberdale Video In/LogiWIN"
1198+ depends on VIDEO_V4L2 && MFD_TIMBERDALE_DMA
1199+ ---help---
1200+ Add support for the Video In peripherial of the timberdale FPGA.
1201+
1202 #
1203 # USB Multimedia device configuration
1204 #
1205diff -uNr linux-2.6.29-clean/drivers/media/video/Makefile linux-2.6.29/drivers/media/video/Makefile
1206--- linux-2.6.29-clean/drivers/media/video/Makefile 2009-04-01 09:20:24.000000000 -0700
1207+++ linux-2.6.29/drivers/media/video/Makefile 2009-04-06 13:51:47.000000000 -0700
1208@@ -52,6 +52,7 @@
1209 obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
1210 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
1211 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
1212+obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
1213 obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
1214 obj-$(CONFIG_VIDEO_BT819) += bt819.o
1215 obj-$(CONFIG_VIDEO_BT856) += bt856.o
1216@@ -148,6 +149,8 @@
1217
1218 obj-$(CONFIG_VIDEO_AU0828) += au0828/
1219
1220+obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
1221+
1222 obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
1223
1224 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
1225diff -uNr linux-2.6.29-clean/drivers/media/video/timblogiw.c linux-2.6.29/drivers/media/video/timblogiw.c
1226--- linux-2.6.29-clean/drivers/media/video/timblogiw.c 1969-12-31 16:00:00.000000000 -0800
1227+++ linux-2.6.29/drivers/media/video/timblogiw.c 2009-04-06 13:51:47.000000000 -0700
1228@@ -0,0 +1,930 @@
1229+/*
1230+ * timblogiw.c timberdale FPGA LogiWin Video In driver
1231+ * Copyright (c) 2009 Intel Corporation
1232+ *
1233+ * This program is free software; you can redistribute it and/or modify
1234+ * it under the terms of the GNU General Public License version 2 as
1235+ * published by the Free Software Foundation.
1236+ *
1237+ * This program is distributed in the hope that it will be useful,
1238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1240+ * GNU General Public License for more details.
1241+ *
1242+ * You should have received a copy of the GNU General Public License
1243+ * along with this program; if not, write to the Free Software
1244+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1245+ */
1246+
1247+/* Supports:
1248+ * Timberdale FPGA LogiWin Video In
1249+ */
1250+
1251+#include <linux/list.h>
1252+#include <linux/version.h>
1253+#include <linux/module.h>
1254+#include <linux/pci.h>
1255+#include <linux/dma-mapping.h>
1256+#include <media/v4l2-common.h>
1257+#include <media/v4l2-ioctl.h>
1258+#include <linux/platform_device.h>
1259+#include <linux/interrupt.h>
1260+#include "timblogiw.h"
1261+#include <linux/mfd/timbdma.h>
1262+
1263+
1264+#define TIMBLOGIW_CTRL 0x40
1265+
1266+#define TIMBLOGIW_H_SCALE 0x20
1267+#define TIMBLOGIW_V_SCALE 0x28
1268+
1269+#define TIMBLOGIW_X_CROP 0x58
1270+#define TIMBLOGIW_Y_CROP 0x60
1271+
1272+#define TIMBLOGIW_W_CROP 0x00
1273+#define TIMBLOGIW_H_CROP 0x08
1274+
1275+#define TIMBLOGIW_VERSION_CODE 0x02
1276+
1277+#define TIMBLOGIW_FRAME 0x10
1278+#define TIMBLOGIW_DROP 0x20
1279+
1280+#define TIMBLOGIW_BUF 0x04
1281+#define TIMBLOGIW_TBI 0x2c
1282+#define TIMBLOGIW_BPL 0x30
1283+
1284+#define dbg(...)
1285+
1286+const struct timblogiw_tvnorm timblogiw_tvnorms[] = {
1287+ {
1288+ .v4l2_id = V4L2_STD_PAL,
1289+ .name = "PAL",
1290+ .swidth = 720,
1291+ .sheight = 576
1292+ },
1293+ {
1294+ .v4l2_id = V4L2_STD_NTSC_M,
1295+ .name = "NTSC",
1296+ .swidth = 720,
1297+ .sheight = 480
1298+ }
1299+};
1300+
1301+static void timblogiw_handleframe(unsigned long arg)
1302+{
1303+ struct timblogiw_frame *f;
1304+ struct timblogiw *lw = (struct timblogiw *)arg;
1305+
1306+ spin_lock_bh(&lw->queue_lock);
1307+ if (!list_empty(&lw->inqueue)) {
1308+ /* put the entry in the outqueue */
1309+ f = list_entry(lw->inqueue.next, struct timblogiw_frame, frame);
1310+
1311+ /* copy data from the DMA buffer */
1312+ memcpy(f->bufmem, lw->dma.filled->buf, f->buf.length);
1313+ /* buffer consumed */
1314+ lw->dma.filled = NULL;
1315+
1316+ do_gettimeofday(&f->buf.timestamp);
1317+ f->buf.sequence = ++lw->frame_count;
1318+ f->buf.field = V4L2_FIELD_NONE;
1319+ f->state = F_DONE;
1320+ f->buf.bytesused = lw->frame_size;
1321+ list_move_tail(&f->frame, &lw->outqueue);
1322+ /* wake up any waiter */
1323+ wake_up(&lw->wait_frame);
1324+ }
1325+ spin_unlock_bh(&lw->queue_lock);
1326+}
1327+
1328+static int timblogiw_isr(u32 flag, void *pdev)
1329+{
1330+ struct timblogiw *lw = (struct timblogiw *)pdev;
1331+
1332+ if (!lw->dma.filled) {
1333+ /* no stored transfer so far, store this, and flip to next */
1334+ lw->dma.filled = lw->dma.transfer + lw->dma.curr;
1335+ lw->dma.curr = !lw->dma.curr;
1336+ }
1337+
1338+ if (lw->stream == STREAM_ON)
1339+ timb_start_dma(DMA_IRQ_VIDEO_RX,
1340+ lw->dma.transfer[lw->dma.curr].handle, lw->frame_size,
1341+ lw->bytesperline);
1342+
1343+ if (flag & DMA_IRQ_VIDEO_DROP)
1344+ dbg("%s: frame dropped\n", __func__);
1345+ if (flag & DMA_IRQ_VIDEO_RX) {
1346+ dbg("%s: frame RX\n", __func__);
1347+ tasklet_schedule(&lw->tasklet);
1348+ }
1349+ return 0;
1350+}
1351+
1352+static void timblogiw_empty_framequeues(struct timblogiw *lw)
1353+{
1354+ u32 i;
1355+
1356+ dbg("%s\n", __func__);
1357+
1358+ INIT_LIST_HEAD(&lw->inqueue);
1359+ INIT_LIST_HEAD(&lw->outqueue);
1360+
1361+ for (i = 0; i < lw->num_frames; i++) {
1362+ lw->frame[i].state = F_UNUSED;
1363+ lw->frame[i].buf.bytesused = 0;
1364+ }
1365+}
1366+
1367+u32 timblogiw_request_buffers(struct timblogiw *lw, u32 count)
1368+{
1369+ /* needs to be page aligned cause the */
1370+ /* buffers can be mapped individually! */
1371+ const size_t imagesize = PAGE_ALIGN(lw->frame_size);
1372+ void *buff = NULL;
1373+ u32 i;
1374+
1375+ dbg("%s - request of %i buffers of size %zi\n",
1376+ __func__, count, lw->frame_size);
1377+
1378+ lw->dma.transfer[0].buf = pci_alloc_consistent(lw->dev, imagesize,
1379+ &lw->dma.transfer[0].handle);
1380+ lw->dma.transfer[1].buf = pci_alloc_consistent(lw->dev, imagesize,
1381+ &lw->dma.transfer[1].handle);
1382+ if ((lw->dma.transfer[0].buf == NULL) ||
1383+ (lw->dma.transfer[1].buf == NULL)) {
1384+ printk(KERN_ALERT "alloc failed\n");
1385+ if (lw->dma.transfer[0].buf != NULL)
1386+ pci_free_consistent(lw->dev, imagesize,
1387+ lw->dma.transfer[0].buf,
1388+ lw->dma.transfer[0].handle);
1389+ if (lw->dma.transfer[1].buf != NULL)
1390+ pci_free_consistent(lw->dev, imagesize,
1391+ lw->dma.transfer[1].buf,
1392+ lw->dma.transfer[1].handle);
1393+ return 0;
1394+ }
1395+
1396+ if (count > TIMBLOGIW_NUM_FRAMES)
1397+ count = TIMBLOGIW_NUM_FRAMES;
1398+
1399+ lw->num_frames = count;
1400+ while (lw->num_frames > 0) {
1401+ buff = vmalloc_32(lw->num_frames * imagesize);
1402+ if (buff) {
1403+ memset(buff, 0, lw->num_frames * imagesize);
1404+ break;
1405+ }
1406+ lw->num_frames--;
1407+ }
1408+
1409+ for (i = 0; i < lw->num_frames; i++) {
1410+ lw->frame[i].bufmem = buff + i * imagesize;
1411+ lw->frame[i].buf.index = i;
1412+ lw->frame[i].buf.m.offset = i * imagesize;
1413+ lw->frame[i].buf.length = lw->frame_size;
1414+ lw->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1415+ lw->frame[i].buf.sequence = 0;
1416+ lw->frame[i].buf.field = V4L2_FIELD_NONE;
1417+ lw->frame[i].buf.memory = V4L2_MEMORY_MMAP;
1418+ lw->frame[i].buf.flags = 0;
1419+ }
1420+
1421+ lw->dma.curr = 0;
1422+ lw->dma.filled = NULL;
1423+ return lw->num_frames;
1424+}
1425+
1426+void timblogiw_release_buffers(struct timblogiw *lw)
1427+{
1428+ dbg("%s\n", __func__);
1429+
1430+ if (lw->frame[0].bufmem != NULL) {
1431+ vfree(lw->frame[0].bufmem);
1432+ lw->frame[0].bufmem = NULL;
1433+ lw->num_frames = TIMBLOGIW_NUM_FRAMES;
1434+ pci_free_consistent(lw->dev, lw->frame_size,
1435+ lw->dma.transfer[0].buf, lw->dma.transfer[0].handle);
1436+ pci_free_consistent(lw->dev, lw->frame_size,
1437+ lw->dma.transfer[1].buf, lw->dma.transfer[1].handle);
1438+ }
1439+}
1440+
1441+/* IOCTL functions */
1442+
1443+static int timblogiw_g_fmt(struct timblogiw *lw, struct v4l2_format *format)
1444+{
1445+ dbg("%s -\n", __func__);
1446+
1447+ if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1448+ return -EINVAL;
1449+
1450+ format->fmt.pix.width = lw->width;
1451+ format->fmt.pix.height = lw->height;
1452+ format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1453+ format->fmt.pix.bytesperline = lw->bytesperline;
1454+ format->fmt.pix.sizeimage = lw->frame_size;
1455+ format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1456+ format->fmt.pix.field = V4L2_FIELD_NONE;
1457+ return 0;
1458+}
1459+
1460+static int timblogiw_s_fmt(struct timblogiw *lw, struct v4l2_format *format)
1461+{
1462+ struct v4l2_pix_format *pix = &format->fmt.pix;
1463+ dbg("%s - type: %d\n", __func__, format->type);
1464+
1465+ if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1466+ return -EINVAL;
1467+
1468+ if ((lw->height != pix->height) || (lw->width != lw->width))
1469+ return -EINVAL;
1470+
1471+ if (format->fmt.pix.field != V4L2_FIELD_NONE)
1472+ return -EINVAL;
1473+
1474+ dbg("%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
1475+ "bytes per line %d, size image: %d, colorspace: %d\n",
1476+ __func__,
1477+ pix->width, pix->height, pix->pixelformat, pix->field,
1478+ pix->bytesperline, pix->sizeimage, pix->colorspace);
1479+
1480+ return 0;
1481+}
1482+
1483+static int timblogiw_querycap(struct timblogiw *lw,
1484+ struct v4l2_capability *cap)
1485+{
1486+ memset(cap, 0, sizeof(*cap));
1487+ strncpy(cap->card, "Timberdale Video", sizeof(cap->card)-1);
1488+ strncpy(cap->driver, "Timblogiw", sizeof(cap->card)-1);
1489+ cap->version = TIMBLOGIW_VERSION_CODE;
1490+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
1491+ V4L2_CAP_STREAMING;
1492+
1493+ return 0;
1494+}
1495+
1496+static int timblogiw_enum_fmt(struct timblogiw *lw, struct v4l2_fmtdesc *fmt)
1497+{
1498+ dbg("%s - VIDIOC_ENUM_FMT\n", __func__);
1499+
1500+ if (fmt->index != 0)
1501+ return -EINVAL;
1502+ memset(fmt, 0, sizeof(*fmt));
1503+ fmt->index = 0;
1504+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1505+ strncpy(fmt->description, "4:2:2, packed, YUYV",
1506+ sizeof(fmt->description)-1);
1507+ fmt->pixelformat = V4L2_PIX_FMT_YUYV;
1508+ memset(fmt->reserved, 0, sizeof(fmt->reserved));
1509+
1510+ return 0;
1511+}
1512+
1513+static int timblogiw_reqbufs(struct timblogiw *lw,
1514+ struct v4l2_requestbuffers *rb)
1515+{
1516+ if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1517+ rb->memory != V4L2_MEMORY_MMAP)
1518+ return -EINVAL;
1519+
1520+ timblogiw_empty_framequeues(lw);
1521+
1522+ timblogiw_release_buffers(lw);
1523+ if (rb->count)
1524+ rb->count = timblogiw_request_buffers(lw, rb->count);
1525+
1526+ dbg("%s - VIDIOC_REQBUFS: io method is mmap. num bufs %i\n",
1527+ __func__, rb->count);
1528+
1529+ return 0;
1530+}
1531+
1532+static int timblogiw_querybuf(struct timblogiw *lw, struct v4l2_buffer *b)
1533+{
1534+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1535+ b->index >= lw->num_frames)
1536+ return -EINVAL;
1537+
1538+ memcpy(b, &lw->frame[b->index].buf, sizeof(*b));
1539+
1540+ if (lw->frame[b->index].vma_use_count)
1541+ b->flags |= V4L2_BUF_FLAG_MAPPED;
1542+
1543+ if (lw->frame[b->index].state == F_DONE)
1544+ b->flags |= V4L2_BUF_FLAG_DONE;
1545+ else if (lw->frame[b->index].state != F_UNUSED)
1546+ b->flags |= V4L2_BUF_FLAG_QUEUED;
1547+
1548+ return 0;
1549+}
1550+
1551+static int timblogiw_qbuf(struct timblogiw *lw, struct v4l2_buffer *b)
1552+{
1553+ unsigned long lock_flags;
1554+
1555+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1556+ b->index >= lw->num_frames)
1557+ return -EINVAL;
1558+
1559+ if (lw->frame[b->index].state != F_UNUSED)
1560+ return -EAGAIN;
1561+
1562+ if (b->memory != V4L2_MEMORY_MMAP)
1563+ return -EINVAL;
1564+
1565+ lw->frame[b->index].state = F_QUEUED;
1566+
1567+ spin_lock_irqsave(&lw->queue_lock, lock_flags);
1568+ list_add_tail(&lw->frame[b->index].frame, &lw->inqueue);
1569+ spin_unlock_irqrestore(&lw->queue_lock, lock_flags);
1570+
1571+ return 0;
1572+}
1573+
1574+static int timblogiw_dqbuf(struct timblogiw *lw, struct file *file,
1575+ struct v4l2_buffer *b)
1576+{
1577+ struct timblogiw_frame *f;
1578+ unsigned long lock_flags;
1579+ int ret = 0;
1580+
1581+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1582+ dbg("%s - VIDIOC_DQBUF, illegal buf type!\n",
1583+ __func__);
1584+ return -EINVAL;
1585+ }
1586+
1587+ if (list_empty(&lw->outqueue)) {
1588+ if (file->f_flags & O_NONBLOCK)
1589+ return -EAGAIN;
1590+
1591+ ret = wait_event_interruptible(lw->wait_frame,
1592+ !list_empty(&lw->outqueue));
1593+ if (ret)
1594+ return ret;
1595+ }
1596+
1597+ spin_lock_irqsave(&lw->queue_lock, lock_flags);
1598+ f = list_entry(lw->outqueue.next,
1599+ struct timblogiw_frame, frame);
1600+ list_del(lw->outqueue.next);
1601+ spin_unlock_irqrestore(&lw->queue_lock, lock_flags);
1602+
1603+ f->state = F_UNUSED;
1604+ memcpy(b, &f->buf, sizeof(*b));
1605+
1606+ if (f->vma_use_count)
1607+ b->flags |= V4L2_BUF_FLAG_MAPPED;
1608+
1609+ return 0;
1610+}
1611+
1612+static int timblogiw_enumstd(struct timblogiw *lw, struct v4l2_standard *std)
1613+{
1614+ if (std->index != 0)
1615+ return -EINVAL;
1616+
1617+ memset(std, 0, sizeof(*std));
1618+ std->index = 0;
1619+
1620+ std->id = V4L2_STD_PAL;
1621+ strncpy(std->name, "PAL", sizeof(std->name)-1);
1622+
1623+ return 0;
1624+}
1625+
1626+static int timblogiw_g_std(struct timblogiw *lw, v4l2_std_id *std)
1627+{
1628+ *std = V4L2_STD_PAL;
1629+ return 0;
1630+}
1631+
1632+static int timblogiw_s_std(struct timblogiw *lw, v4l2_std_id *std)
1633+{
1634+ if (!(*std & V4L2_STD_PAL))
1635+ return -EINVAL;
1636+ return 0;
1637+}
1638+
1639+static int timblogiw_enuminput(struct timblogiw *lw, struct v4l2_input *inp)
1640+{
1641+ if (inp->index != 0)
1642+ return -EINVAL;
1643+
1644+ memset(inp, 0, sizeof(*inp));
1645+ inp->index = 0;
1646+
1647+ strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
1648+ inp->type = V4L2_INPUT_TYPE_CAMERA;
1649+ inp->std = V4L2_STD_ALL;
1650+
1651+ return 0;
1652+}
1653+
1654+static int timblogiw_g_input(struct timblogiw *lw, int *input)
1655+{
1656+ *input = 0;
1657+
1658+ return 0;
1659+}
1660+
1661+static int timblogiw_s_input(struct timblogiw *lw, int *input)
1662+{
1663+ if (*input != 0)
1664+ return -EINVAL;
1665+ return 0;
1666+}
1667+
1668+static int timblogiw_streamon(struct timblogiw *lw, int *type)
1669+{
1670+ struct timblogiw_frame *f;
1671+
1672+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1673+ dbg("%s - No capture device\n", __func__);
1674+ return -EINVAL;
1675+ }
1676+
1677+ if (list_empty(&lw->inqueue)) {
1678+ dbg("%s - inqueue is empty\n", __func__);
1679+ return -EINVAL;
1680+ }
1681+
1682+ if (lw->stream == STREAM_ON)
1683+ return 0;
1684+
1685+ lw->stream = STREAM_ON;
1686+
1687+ f = list_entry(lw->inqueue.next,
1688+ struct timblogiw_frame, frame);
1689+
1690+ dbg("%s - f size: %d, bpr: %d, dma addr: %x\n", __func__,
1691+ lw->frame_size, lw->bytesperline,
1692+ (unsigned int)lw->dma.transfer[lw->dma.curr].handle);
1693+ timb_start_dma(DMA_IRQ_VIDEO_RX,
1694+ lw->dma.transfer[lw->dma.curr].handle,
1695+ lw->frame_size, lw->bytesperline);
1696+
1697+ return 0;
1698+}
1699+
1700+static int timblogiw_streamoff(struct timblogiw *lw, int *type)
1701+{
1702+ if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1703+ return -EINVAL;
1704+
1705+ if (lw->stream == STREAM_ON) {
1706+ unsigned long lock_flags;
1707+ spin_lock_irqsave(&lw->queue_lock, lock_flags);
1708+ timb_stop_dma(DMA_IRQ_VIDEO_RX);
1709+ lw->stream = STREAM_OFF;
1710+ spin_unlock_irqrestore(&lw->queue_lock, lock_flags);
1711+ }
1712+ timblogiw_empty_framequeues(lw);
1713+
1714+ return 0;
1715+}
1716+
1717+static int timblogiw_querystd(struct timblogiw *lw, v4l2_std_id *std)
1718+{
1719+ /* TODO: Ask encoder */
1720+ *std = V4L2_STD_PAL;
1721+ return 0;
1722+}
1723+
1724+static int timblogiw_enum_framsizes(struct timblogiw *lw,
1725+ struct v4l2_frmsizeenum *fsize)
1726+{
1727+ if ((fsize->index != 0) ||
1728+ (fsize->pixel_format != V4L2_PIX_FMT_YUYV))
1729+ return -EINVAL;
1730+
1731+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1732+ fsize->discrete.width = lw->width;
1733+ fsize->discrete.height = lw->height;
1734+
1735+ return 0;
1736+}
1737+
1738+static int timblogiw_g_parm(struct timblogiw *lw, struct v4l2_streamparm *sp)
1739+{
1740+ if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1741+ return -EINVAL;
1742+
1743+ sp->parm.capture.extendedmode = 0;
1744+ sp->parm.capture.readbuffers = lw->num_frames;
1745+ return 0;
1746+}
1747+
1748+/*******************************
1749+ * Device Operations functions *
1750+ *******************************/
1751+
1752+static int timblogiw_open(struct file *file)
1753+{
1754+ struct video_device *vdev = video_devdata(file);
1755+ struct timblogiw *lw = video_get_drvdata(vdev);
1756+
1757+ dbg("%s -\n", __func__);
1758+
1759+ mutex_init(&lw->fileop_lock);
1760+ spin_lock_init(&lw->queue_lock);
1761+ init_waitqueue_head(&lw->wait_frame);
1762+
1763+ mutex_lock(&lw->lock);
1764+
1765+ lw->width = 720; /* TODO: Should depend on tv norm */
1766+ lw->height = 576;
1767+ lw->frame_size = lw->width * lw->height * 2;
1768+ lw->bytesperline = lw->width * 2;
1769+
1770+ file->private_data = lw;
1771+ lw->stream = STREAM_OFF;
1772+ lw->num_frames = TIMBLOGIW_NUM_FRAMES;
1773+
1774+ timblogiw_empty_framequeues(lw);
1775+
1776+ timb_set_dma_interruptcb(DMA_IRQ_VIDEO_RX | DMA_IRQ_VIDEO_DROP,
1777+ timblogiw_isr, (void *)lw);
1778+
1779+ mutex_unlock(&lw->lock);
1780+
1781+ return 0;
1782+}
1783+
1784+static int timblogiw_close(struct file *file)
1785+{
1786+ struct timblogiw *lw = file->private_data;
1787+
1788+ dbg("%s - entry\n", __func__);
1789+
1790+ mutex_lock(&lw->lock);
1791+
1792+ timb_stop_dma(DMA_IRQ_VIDEO_RX);
1793+ timb_set_dma_interruptcb(DMA_IRQ_VIDEO_RX | DMA_IRQ_VIDEO_DROP, NULL,
1794+ NULL);
1795+ timblogiw_release_buffers(lw);
1796+
1797+ mutex_unlock(&lw->lock);
1798+ return 0;
1799+}
1800+
1801+static ssize_t timblogiw_read(struct file *file, char __user *data,
1802+ size_t count, loff_t *ppos)
1803+{
1804+ dbg("%s - read request\n", __func__);
1805+ return -EINVAL;
1806+}
1807+
1808+static void timblogiw_vm_open(struct vm_area_struct *vma)
1809+{
1810+ struct timblogiw_frame *f = vma->vm_private_data;
1811+ f->vma_use_count++;
1812+}
1813+
1814+static void timblogiw_vm_close(struct vm_area_struct *vma)
1815+{
1816+ struct timblogiw_frame *f = vma->vm_private_data;
1817+ f->vma_use_count--;
1818+}
1819+
1820+static struct vm_operations_struct timblogiw_vm_ops = {
1821+ .open = timblogiw_vm_open,
1822+ .close = timblogiw_vm_close,
1823+};
1824+
1825+static int timblogiw_mmap(struct file *filp, struct vm_area_struct *vma)
1826+{
1827+ unsigned long size = vma->vm_end - vma->vm_start, start = vma->vm_start;
1828+ void *pos;
1829+ u32 i;
1830+ int ret = -EINVAL;
1831+
1832+ struct timblogiw *lw = filp->private_data;
1833+ dbg("%s\n", __func__);
1834+
1835+ if (mutex_lock_interruptible(&lw->fileop_lock))
1836+ return -ERESTARTSYS;
1837+
1838+ if (!(vma->vm_flags & VM_WRITE) ||
1839+ size != PAGE_ALIGN(lw->frame[0].buf.length))
1840+ goto error_unlock;
1841+
1842+ for (i = 0; i < lw->num_frames; i++)
1843+ if ((lw->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
1844+ break;
1845+
1846+ if (i == lw->num_frames) {
1847+ dbg("%s - user supplied mapping address is out of range\n",
1848+ __func__);
1849+ goto error_unlock;
1850+ }
1851+
1852+ vma->vm_flags |= VM_IO;
1853+ vma->vm_flags |= VM_RESERVED; /* Do not swap out this VMA */
1854+
1855+ pos = lw->frame[i].bufmem;
1856+ while (size > 0) { /* size is page-aligned */
1857+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
1858+ dbg("%s - vm_insert_page failed\n", __func__);
1859+ ret = -EAGAIN;
1860+ goto error_unlock;
1861+ }
1862+ start += PAGE_SIZE;
1863+ pos += PAGE_SIZE;
1864+ size -= PAGE_SIZE;
1865+ }
1866+
1867+ vma->vm_ops = &timblogiw_vm_ops;
1868+ vma->vm_private_data = &lw->frame[i];
1869+ timblogiw_vm_open(vma);
1870+ ret = 0;
1871+
1872+error_unlock:
1873+ mutex_unlock(&lw->fileop_lock);
1874+ return ret;
1875+}
1876+
1877+static long
1878+timblogiw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1879+{
1880+ struct timblogiw *lw = file->private_data;
1881+
1882+ switch (cmd) {
1883+
1884+ case VIDIOC_QUERYCAP:
1885+ {
1886+ dbg("%s - VIDIOC_QUERYCAP\n", __func__);
1887+ return timblogiw_querycap(lw, (struct v4l2_capability *)arg);
1888+ }
1889+
1890+ case VIDIOC_ENUM_FMT:
1891+ {
1892+ dbg("%s - VIDIOC_ENUM_FMT\n", __func__);
1893+ return timblogiw_enum_fmt(lw, (struct v4l2_fmtdesc *)arg);
1894+ }
1895+
1896+ case VIDIOC_G_FMT:
1897+ {
1898+ dbg("%s - VIDIOC_G_FMT\n", __func__);
1899+ return timblogiw_g_fmt(lw, (struct v4l2_format *) arg);
1900+ }
1901+
1902+ case VIDIOC_TRY_FMT:
1903+ case VIDIOC_S_FMT:
1904+ {
1905+ dbg("%s - VIDIOC_S_FMT\n", __func__);
1906+ return timblogiw_s_fmt(lw, (struct v4l2_format *)arg);
1907+ }
1908+
1909+ case VIDIOC_REQBUFS:
1910+ {
1911+ dbg("%s - VIDIOC_REQBUFS\n", __func__);
1912+ return timblogiw_reqbufs(lw, (struct v4l2_requestbuffers *)arg);
1913+ }
1914+
1915+ case VIDIOC_QUERYBUF:
1916+ {
1917+ dbg("%s - VIDIOC_QUERYBUF\n", __func__);
1918+ return timblogiw_querybuf(lw, (struct v4l2_buffer *)arg);
1919+ }
1920+
1921+ case VIDIOC_QBUF:
1922+ {
1923+ return timblogiw_qbuf(lw, (struct v4l2_buffer *)arg);
1924+ }
1925+
1926+ case VIDIOC_DQBUF:
1927+ {
1928+ return timblogiw_dqbuf(lw, file, (struct v4l2_buffer *)arg);
1929+ }
1930+
1931+ case VIDIOC_ENUMSTD:
1932+ {
1933+ dbg("%s - VIDIOC_ENUMSTD\n", __func__);
1934+ return timblogiw_enumstd(lw, (struct v4l2_standard *)arg);
1935+ }
1936+
1937+ case VIDIOC_G_STD:
1938+ {
1939+ dbg("%s - VIDIOC_G_STD\n", __func__);
1940+ return timblogiw_g_std(lw, (v4l2_std_id *)arg);
1941+ }
1942+
1943+ case VIDIOC_S_STD:
1944+ {
1945+ dbg("%s - VIDIOC_S_STD\n", __func__);
1946+ return timblogiw_s_std(lw, (v4l2_std_id *)arg);
1947+ }
1948+
1949+ case VIDIOC_ENUMINPUT:
1950+ {
1951+ dbg("%s - VIDIOC_ENUMINPUT\n", __func__);
1952+ return timblogiw_enuminput(lw, (struct v4l2_input *)arg);
1953+ }
1954+
1955+ case VIDIOC_G_INPUT:
1956+ {
1957+ dbg("%s - VIDIOC_G_INPUT\n", __func__);
1958+ return timblogiw_g_input(lw, (int *)arg);
1959+ }
1960+
1961+ case VIDIOC_S_INPUT:
1962+ {
1963+ dbg("%s - VIDIOC_S_INPUT\n", __func__);
1964+ return timblogiw_s_input(lw, (int *)arg);
1965+ }
1966+
1967+ case VIDIOC_STREAMON:
1968+ {
1969+ dbg("%s - VIDIOC_STREAMON\n", __func__);
1970+ return timblogiw_streamon(lw, (int *)arg);
1971+ }
1972+
1973+ case VIDIOC_STREAMOFF:
1974+ {
1975+ dbg("%s - VIDIOC_STREAMOFF\n", __func__);
1976+ return timblogiw_streamoff(lw, (int *)arg);
1977+ }
1978+
1979+ case VIDIOC_QUERYSTD:
1980+ {
1981+ dbg("%s - VIDIOC_QUERYSTD\n", __func__);
1982+ return timblogiw_querystd(lw, (v4l2_std_id *)arg);
1983+ }
1984+
1985+ case VIDIOC_ENUM_FRAMESIZES:
1986+ {
1987+ dbg("%s - VIDIOC_ENUM_FRAMESIZES\n", __func__);
1988+ return timblogiw_enum_framsizes(lw,
1989+ (struct v4l2_frmsizeenum *)arg);
1990+ }
1991+
1992+ case VIDIOC_G_PARM:
1993+ {
1994+ dbg("%s - VIDIOC_G_PARM\n", __func__);
1995+ return timblogiw_g_parm(lw, (struct v4l2_streamparm *)arg);
1996+ }
1997+
1998+ default:
1999+ {
2000+ dbg("%s Unknown command, dir: %x, type: %x, nr: %x, size: %x\n",
2001+ __func__,
2002+ _IOC_DIR(cmd),
2003+ _IOC_TYPE(cmd),
2004+ _IOC_NR(cmd),
2005+ _IOC_SIZE(cmd));
2006+ break;
2007+ }
2008+ }
2009+
2010+ return -EINVAL;
2011+}
2012+
2013+void timblogiw_vdev_release(struct video_device *vdev)
2014+{
2015+ kfree(vdev);
2016+}
2017+
2018+static const struct v4l2_file_operations timblogiw_fops = {
2019+ .owner = THIS_MODULE,
2020+ .open = timblogiw_open,
2021+ .release = timblogiw_close,
2022+ .ioctl = timblogiw_ioctl,
2023+ .mmap = timblogiw_mmap,
2024+ .read = timblogiw_read,
2025+};
2026+
2027+static const struct video_device timblogiw_template = {
2028+ .name = TIMBLOGIWIN_NAME,
2029+ .fops = &timblogiw_fops,
2030+ .release = &timblogiw_vdev_release,
2031+ .minor = -1
2032+};
2033+
2034+static int timblogiw_probe(struct platform_device *dev)
2035+{
2036+ int err;
2037+ struct timblogiw *lw;
2038+ struct resource *iomem;
2039+
2040+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
2041+ if (!iomem) {
2042+ err = -EINVAL;
2043+ goto err_mem;
2044+ }
2045+
2046+ lw = kzalloc(sizeof(*lw), GFP_KERNEL);
2047+ if (!lw) {
2048+ err = -EINVAL;
2049+ goto err_mem;
2050+ }
2051+
2052+ /* find the PCI device from the parent... */
2053+ if (!dev->dev.parent) {
2054+ printk(KERN_ERR "timblogwi: No parent device found??\n");
2055+ err = -ENODEV;
2056+ goto err_mem;
2057+ }
2058+
2059+ lw->dev = container_of(dev->dev.parent, struct pci_dev, dev);
2060+
2061+ mutex_init(&lw->lock);
2062+
2063+ lw->video_dev = video_device_alloc();
2064+ if (!lw->video_dev) {
2065+ err = -ENOMEM;
2066+ goto err_video_req;
2067+ }
2068+ *lw->video_dev = timblogiw_template;
2069+
2070+ err = video_register_device(lw->video_dev, VFL_TYPE_GRABBER, 0);
2071+ if (err) {
2072+ video_device_release(lw->video_dev);
2073+ printk(KERN_ALERT "Error reg video\n");
2074+ goto err_video_req;
2075+ }
2076+
2077+ tasklet_init(&lw->tasklet, timblogiw_handleframe, (unsigned long)lw);
2078+
2079+ if (!request_mem_region(iomem->start, resource_size(iomem),
2080+ "timb-video")) {
2081+ err = -EBUSY;
2082+ goto err_request;
2083+ }
2084+
2085+ lw->membase = ioremap(iomem->start, resource_size(iomem));
2086+ if (!lw->membase) {
2087+ err = -ENOMEM;
2088+ goto err_ioremap;
2089+ }
2090+
2091+ platform_set_drvdata(dev, lw);
2092+ video_set_drvdata(lw->video_dev, lw);
2093+
2094+ return 0;
2095+
2096+err_ioremap:
2097+ release_mem_region(iomem->start, resource_size(iomem));
2098+err_request:
2099+ if (-1 != lw->video_dev->minor)
2100+ video_unregister_device(lw->video_dev);
2101+ else
2102+ video_device_release(lw->video_dev);
2103+err_video_req:
2104+ kfree(lw);
2105+err_mem:
2106+ printk(KERN_ERR
2107+ "timberdale: Failed to register Timberdale Video In: %d\n",
2108+ err);
2109+
2110+ return err;
2111+}
2112+
2113+static int timblogiw_remove(struct platform_device *dev)
2114+{
2115+ struct timblogiw *lw = platform_get_drvdata(dev);
2116+ struct resource *iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
2117+
2118+ if (-1 != lw->video_dev->minor)
2119+ video_unregister_device(lw->video_dev);
2120+ else
2121+ video_device_release(lw->video_dev);
2122+
2123+ tasklet_kill(&lw->tasklet);
2124+ iounmap(lw->membase);
2125+ release_mem_region(iomem->start, resource_size(iomem));
2126+ kfree(lw);
2127+
2128+ return 0;
2129+}
2130+
2131+static struct platform_driver timblogiw_platform_driver = {
2132+ .driver = {
2133+ .name = "timb-video",
2134+ .owner = THIS_MODULE,
2135+ },
2136+ .probe = timblogiw_probe,
2137+ .remove = timblogiw_remove,
2138+};
2139+
2140+/*--------------------------------------------------------------------------*/
2141+
2142+static int __init timblogiw_init(void)
2143+{
2144+ return platform_driver_register(&timblogiw_platform_driver);
2145+}
2146+
2147+static void __exit timblogiw_exit(void)
2148+{
2149+ platform_driver_unregister(&timblogiw_platform_driver);
2150+}
2151+
2152+module_init(timblogiw_init);
2153+module_exit(timblogiw_exit);
2154+
2155+MODULE_DESCRIPTION("Timberdale Video In driver");
2156+MODULE_LICENSE("GPL v2");
2157+MODULE_ALIAS("platform:timb-video");
2158+
2159diff -uNr linux-2.6.29-clean/drivers/media/video/timblogiw.h linux-2.6.29/drivers/media/video/timblogiw.h
2160--- linux-2.6.29-clean/drivers/media/video/timblogiw.h 1969-12-31 16:00:00.000000000 -0800
2161+++ linux-2.6.29/drivers/media/video/timblogiw.h 2009-04-06 13:51:47.000000000 -0700
2162@@ -0,0 +1,95 @@
2163+/*
2164+ * timblogiw.h timberdale FPGA LogiWin Video In driver defines
2165+ * Copyright (c) 2009 Intel Corporation
2166+ *
2167+ * This program is free software; you can redistribute it and/or modify
2168+ * it under the terms of the GNU General Public License version 2 as
2169+ * published by the Free Software Foundation.
2170+ *
2171+ * This program is distributed in the hope that it will be useful,
2172+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2173+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2174+ * GNU General Public License for more details.
2175+ *
2176+ * You should have received a copy of the GNU General Public License
2177+ * along with this program; if not, write to the Free Software
2178+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2179+ */
2180+
2181+/* Supports:
2182+ * Timberdale FPGA LogiWin Video In
2183+ */
2184+
2185+#ifndef _TIMBLOGIW_H
2186+#define _TIMBLOGIW_H
2187+
2188+#include <linux/interrupt.h>
2189+
2190+#define TIMBLOGIWIN_NAME "Timberdale Video-In"
2191+
2192+#define TIMBLOGIW_NUM_FRAMES 10
2193+
2194+
2195+enum timblogiw_stream_state {
2196+ STREAM_OFF,
2197+ STREAM_ON,
2198+};
2199+
2200+enum timblogiw_frame_state {
2201+ F_UNUSED = 0,
2202+ F_QUEUED,
2203+ F_GRABBING,
2204+ F_DONE,
2205+ F_ERROR,
2206+};
2207+
2208+struct timblogiw_frame {
2209+ void *bufmem;
2210+ struct v4l2_buffer buf;
2211+ enum timblogiw_frame_state state;
2212+ struct list_head frame;
2213+ unsigned long vma_use_count;
2214+};
2215+
2216+struct timblogiw_tvnorm {
2217+ int v4l2_id;
2218+ char *name;
2219+ u16 swidth;
2220+ u16 sheight;
2221+};
2222+
2223+
2224+struct timbdma_transfer {
2225+ dma_addr_t handle;
2226+ void *buf;
2227+};
2228+
2229+struct timbdma_control {
2230+ struct timbdma_transfer transfer[2];
2231+ struct timbdma_transfer *filled;
2232+ int curr;
2233+};
2234+
2235+struct timblogiw {
2236+ struct i2c_client *decoder;
2237+ struct timblogiw_frame frame[TIMBLOGIW_NUM_FRAMES];
2238+ int num_frames;
2239+ unsigned int frame_count;
2240+ struct list_head inqueue, outqueue;
2241+ spinlock_t queue_lock; /* mutual exclusion */
2242+ enum timblogiw_stream_state stream;
2243+ struct video_device *video_dev;
2244+ struct mutex lock, fileop_lock;
2245+ wait_queue_head_t wait_frame;
2246+ int width;
2247+ int height;
2248+ u32 frame_size;
2249+ int bytesperline;
2250+ struct pci_dev *dev;
2251+ struct timbdma_control dma;
2252+ void __iomem *membase;
2253+ struct tasklet_struct tasklet;
2254+};
2255+
2256+#endif /* _TIMBLOGIW_H */
2257+
2258diff -uNr linux-2.6.29-clean/drivers/mfd/Kconfig linux-2.6.29/drivers/mfd/Kconfig
2259--- linux-2.6.29-clean/drivers/mfd/Kconfig 2009-04-01 09:20:24.000000000 -0700
2260+++ linux-2.6.29/drivers/mfd/Kconfig 2009-04-06 13:51:47.000000000 -0700
2261@@ -240,6 +240,27 @@
2262 Say yes here if you want to include support GPIO for pins on
2263 the PCF50633 chip.
2264
2265+config MFD_TIMBERDALE
2266+ bool "Support for Timberdale"
2267+ select MFD_CORE
2268+ ---help---
2269+ This is the core driver for the timberdale FPGA. This device is a
2270+ multifunctioanl device which may provide numerous interfaces.
2271+
2272+config MFD_TIMBERDALE_DMA
2273+ tristate "Support for timberdale DMA"
2274+ depends on MFD_TIMBERDALE
2275+ ---help---
2276+ Add support the DMA block inside the timberdale FPGA. This to be able
2277+ to do DMA transfers directly to some of the blocks inside the FPGA
2278+
2279+config MFD_TIMBERDALE_I2S
2280+ tristate "Support for timberdale I2S bus"
2281+ depends on MFD_TIMBERDALE
2282+ ---help---
2283+ Add support for the I2S bus handled by timberdale FPGA.
2284+ I2S RX and TX instances are then available for other devices to make use of.
2285+
2286 endmenu
2287
2288 menu "Multimedia Capabilities Port drivers"
2289diff -uNr linux-2.6.29-clean/drivers/mfd/Makefile linux-2.6.29/drivers/mfd/Makefile
2290--- linux-2.6.29-clean/drivers/mfd/Makefile 2009-04-01 09:20:24.000000000 -0700
2291+++ linux-2.6.29/drivers/mfd/Makefile 2009-04-06 13:51:47.000000000 -0700
2292@@ -40,4 +40,8 @@
2293
2294 obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
2295 obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
2296-obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
2297\ No newline at end of file
2298+obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
2299+
2300+obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
2301+obj-$(CONFIG_MFD_TIMBERDALE_DMA) += timbdma.o
2302+obj-$(CONFIG_MFD_TIMBERDALE_I2S) += timbi2s.o
2303diff -uNr linux-2.6.29-clean/drivers/mfd/timbdma.c linux-2.6.29/drivers/mfd/timbdma.c
2304--- linux-2.6.29-clean/drivers/mfd/timbdma.c 1969-12-31 16:00:00.000000000 -0800
2305+++ linux-2.6.29/drivers/mfd/timbdma.c 2009-04-06 13:51:47.000000000 -0700
2306@@ -0,0 +1,301 @@
2307+/*
2308+ * timbdma.c timberdale FPGA DMA driver
2309+ * Copyright (c) 2009 Intel Corporation
2310+ *
2311+ * This program is free software; you can redistribute it and/or modify
2312+ * it under the terms of the GNU General Public License version 2 as
2313+ * published by the Free Software Foundation.
2314+ *
2315+ * This program is distributed in the hope that it will be useful,
2316+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2317+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2318+ * GNU General Public License for more details.
2319+ *
2320+ * You should have received a copy of the GNU General Public License
2321+ * along with this program; if not, write to the Free Software
2322+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2323+ */
2324+
2325+/* Supports:
2326+ * Timberdale FPGA DMA engine
2327+ */
2328+
2329+#include <linux/version.h>
2330+#include <linux/module.h>
2331+#include <linux/pci.h>
2332+#include <linux/interrupt.h>
2333+#include <linux/platform_device.h>
2334+
2335+#include <linux/mfd/timbdma.h>
2336+
2337+static struct timbdma_dev *self_g;
2338+
2339+static irqreturn_t timbdma_handleinterrupt(int irq, void *devid)
2340+{
2341+ struct timbdma_dev *dev = (struct timbdma_dev *)devid;
2342+ int ipr;
2343+ int i;
2344+
2345+ ipr = ioread32(dev->membase + timbdma_ctrlmap_TIMBPEND);
2346+
2347+ /* ack */
2348+ iowrite32(ipr, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
2349+
2350+ /* call the callbacks */
2351+ for (i = 0; i < DMA_IRQS; i++) {
2352+ int mask = 1 << i;
2353+ if ((ipr & mask) && dev->callbacks[i])
2354+ dev->callbacks[i](mask, dev->callback_data[i]);
2355+ }
2356+
2357+ if (ipr)
2358+ return IRQ_HANDLED;
2359+ else
2360+ return IRQ_NONE;
2361+}
2362+
2363+
2364+void timb_start_dma(u32 flag, unsigned long buf, int len, int bytes_per_row)
2365+{
2366+ int i;
2367+ unsigned long irqflags;
2368+ struct timbdma_dev *dev = self_g;
2369+
2370+ spin_lock_irqsave(&dev->lock, irqflags);
2371+
2372+ /* now enable the DMA transfer */
2373+ for (i = 0; i < DMA_IRQS; i++)
2374+ if (flag & (1 << i)) {
2375+ u32 offset = i / 2 * 0x40;
2376+
2377+ if (!(i % 2)) {
2378+ /* RX */
2379+ /* bytes per row */
2380+ iowrite32(bytes_per_row, dev->membase + offset +
2381+ timbdma_dmacfg_BPERROW);
2382+ /* address high */
2383+ iowrite32(0, dev->membase + offset +
2384+ timbdma_dmacfg_RXSTARTH);
2385+ /* address low */
2386+ iowrite32(buf, dev->membase + offset +
2387+ timbdma_dmacfg_RXSTARTL);
2388+ /* Length */
2389+ iowrite32(len, dev->membase + offset +
2390+ timbdma_dmacfg_RXLENGTH);
2391+ /* Clear rx sw read pointer */
2392+ iowrite32(0, dev->membase + offset +
2393+ timbdma_dmacfg_RXSWRP);
2394+ /* enable the transfer */
2395+ iowrite32(1, dev->membase + offset +
2396+ timbdma_dmacfg_RXENABLE);
2397+ } else {
2398+ /* TX */
2399+ /* address high */
2400+ iowrite32(0, dev->membase + offset +
2401+ timbdma_dmacfg_TXSTARTH);
2402+ /* address low */
2403+ iowrite32(buf, dev->membase + offset +
2404+ timbdma_dmacfg_TXSTARTL);
2405+ /* Length */
2406+ iowrite32(len, dev->membase + offset +
2407+ timbdma_dmacfg_TXLENGTH);
2408+ /* Set tx sw write pointer */
2409+ iowrite32(len, dev->membase + offset +
2410+ timbdma_dmacfg_TXSWWP);
2411+ }
2412+
2413+ /* only allow one bit in the flag field */
2414+ break;
2415+ }
2416+ spin_unlock_irqrestore(&dev->lock, irqflags);
2417+}
2418+EXPORT_SYMBOL(timb_start_dma);
2419+
2420+void *timb_stop_dma(u32 flags)
2421+{
2422+ int i;
2423+ unsigned long irqflags;
2424+ struct timbdma_dev *dev = self_g;
2425+ void *result = 0;
2426+
2427+ spin_lock_irqsave(&dev->lock, irqflags);
2428+
2429+ /* now disable the DMA transfers */
2430+ for (i = 0; i < DMA_IRQS; i++)
2431+ if (flags & (1 << i)) {
2432+ /*
2433+ RX enable registers are located at:
2434+ 0x14
2435+ 0x54
2436+ 0x94
2437+
2438+ TX SW pointer registers are located at:
2439+ 0x24
2440+ 0x64
2441+ */
2442+ u32 offset = i / 2 * 0x40;
2443+ u32 result_offset = offset;
2444+ if (!(i % 2)) {
2445+ /* even -> RX enable */
2446+ offset += timbdma_dmacfg_RXENABLE;
2447+ result_offset += timbdma_dmacfg_RXFPGAWP;
2448+ } else {
2449+ /* odd -> TX SW pointer reg */
2450+ offset += timbdma_dmacfg_TXSWWP;
2451+ result_offset = timbdma_dmacfg_TXFPGARP;
2452+ }
2453+
2454+ iowrite32(0, dev->membase + offset);
2455+ /* check how far the FPGA has written/read */
2456+ result = (void *)ioread32(dev->membase + result_offset);
2457+ }
2458+
2459+ /* ack any pending IRQs */
2460+ iowrite32(flags, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
2461+
2462+ spin_unlock_irqrestore(&dev->lock, irqflags);
2463+
2464+ return result;
2465+}
2466+EXPORT_SYMBOL(timb_stop_dma);
2467+
2468+void timb_set_dma_interruptcb(u32 flags, timbdma_interruptcb icb, void *data)
2469+{
2470+ int i;
2471+ unsigned long irqflags;
2472+ struct timbdma_dev *dev = self_g;
2473+ u32 ier;
2474+
2475+ spin_lock_irqsave(&dev->lock, irqflags);
2476+
2477+ for (i = 0; i < DMA_IRQS; i++)
2478+ if (flags & (1 << i)) {
2479+ dev->callbacks[i] = icb;
2480+ dev->callback_data[i] = data;
2481+ }
2482+
2483+ /* Ack any pending IRQ */
2484+ iowrite32(flags, dev->membase + timbdma_ctrlmap_TIMBSTATUS);
2485+
2486+ /* if a null callback is given -> clear interrupt, else -> enable */
2487+ ier = ioread32(dev->membase + timbdma_ctrlmap_TIMBENABLE);
2488+ if (icb != NULL)
2489+ ier |= flags;
2490+ else
2491+ ier &= ~flags;
2492+ iowrite32(ier, dev->membase + timbdma_ctrlmap_TIMBENABLE);
2493+
2494+ spin_unlock_irqrestore(&dev->lock, irqflags);
2495+}
2496+EXPORT_SYMBOL(timb_set_dma_interruptcb);
2497+
2498+static int timbdma_probe(struct platform_device *dev)
2499+{
2500+ int err, irq;
2501+ struct timbdma_dev *self;
2502+ struct resource *iomem;
2503+
2504+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
2505+ if (!iomem) {
2506+ err = -EINVAL;
2507+ goto err_mem;
2508+ }
2509+
2510+ self = kzalloc(sizeof(*self), GFP_KERNEL);
2511+ if (!self) {
2512+ err = -EINVAL;
2513+ goto err_mem;
2514+ }
2515+
2516+ spin_lock_init(&self->lock);
2517+
2518+ if (!request_mem_region(iomem->start,
2519+ resource_size(iomem), "timb-dma")) {
2520+ err = -EBUSY;
2521+ goto err_request;
2522+ }
2523+
2524+ self->membase = ioremap(iomem->start, resource_size(iomem));
2525+ if (!self->membase) {
2526+ printk(KERN_ERR "timbdma: Failed to remap I/O memory\n");
2527+ err = -ENOMEM;
2528+ goto err_ioremap;
2529+ }
2530+
2531+ /* register interrupt */
2532+ irq = platform_get_irq(dev, 0);
2533+ if (irq < 0) {
2534+ err = irq;
2535+ goto err_get_irq;
2536+ }
2537+
2538+ /* request IRQ */
2539+ err = request_irq(irq, timbdma_handleinterrupt, IRQF_SHARED,
2540+ "timb-dma", self);
2541+ if (err) {
2542+ printk(KERN_ERR "timbdma: Failed to request IRQ\n");
2543+ goto err_get_irq;
2544+ }
2545+
2546+ platform_set_drvdata(dev, self);
2547+
2548+ /* assign the global pointer */
2549+ self_g = self;
2550+
2551+ return 0;
2552+
2553+err_get_irq:
2554+ iounmap(self->membase);
2555+err_ioremap:
2556+ release_mem_region(iomem->start, resource_size(iomem));
2557+err_request:
2558+ kfree(self);
2559+err_mem:
2560+ printk(KERN_ERR "timberdale: Failed to register Timberdale DMA: %d\n",
2561+ err);
2562+
2563+ return err;
2564+}
2565+
2566+static int timbdma_remove(struct platform_device *dev)
2567+{
2568+ struct timbdma_dev *self = platform_get_drvdata(dev);
2569+ struct resource *iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
2570+
2571+ free_irq(platform_get_irq(dev, 0), self);
2572+ iounmap(self->membase);
2573+ release_mem_region(iomem->start, resource_size(iomem));
2574+ kfree(self);
2575+ self_g = NULL;
2576+ return 0;
2577+}
2578+
2579+static struct platform_driver timbdma_platform_driver = {
2580+ .driver = {
2581+ .name = "timb-dma",
2582+ .owner = THIS_MODULE,
2583+ },
2584+ .probe = timbdma_probe,
2585+ .remove = timbdma_remove,
2586+};
2587+
2588+/*--------------------------------------------------------------------------*/
2589+
2590+static int __init timbdma_init(void)
2591+{
2592+ self_g = NULL;
2593+ return platform_driver_register(&timbdma_platform_driver);
2594+}
2595+
2596+static void __exit timbdma_exit(void)
2597+{
2598+ platform_driver_unregister(&timbdma_platform_driver);
2599+}
2600+
2601+module_init(timbdma_init);
2602+module_exit(timbdma_exit);
2603+
2604+MODULE_DESCRIPTION("Timberdale DMA driver");
2605+MODULE_LICENSE("GPL v2");
2606+MODULE_ALIAS("platform:timb-dma");
2607+
2608diff -uNr linux-2.6.29-clean/drivers/mfd/timberdale.c linux-2.6.29/drivers/mfd/timberdale.c
2609--- linux-2.6.29-clean/drivers/mfd/timberdale.c 1969-12-31 16:00:00.000000000 -0800
2610+++ linux-2.6.29/drivers/mfd/timberdale.c 2009-04-06 13:51:47.000000000 -0700
2611@@ -0,0 +1,599 @@
2612+/*
2613+ * timberdale.c timberdale FPGA mfd shim driver
2614+ * Copyright (c) 2009 Intel Corporation
2615+ *
2616+ * This program is free software; you can redistribute it and/or modify
2617+ * it under the terms of the GNU General Public License version 2 as
2618+ * published by the Free Software Foundation.
2619+ *
2620+ * This program is distributed in the hope that it will be useful,
2621+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2622+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2623+ * GNU General Public License for more details.
2624+ *
2625+ * You should have received a copy of the GNU General Public License
2626+ * along with this program; if not, write to the Free Software
2627+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2628+ */
2629+
2630+/* Supports:
2631+ * Timberdale FPGA
2632+ */
2633+
2634+#include <linux/kernel.h>
2635+#include <linux/module.h>
2636+#include <linux/pci.h>
2637+#include <linux/msi.h>
2638+#include <linux/init.h>
2639+#include <linux/interrupt.h>
2640+#include <linux/platform_device.h>
2641+#include <linux/mfd/core.h>
2642+#include <linux/irq.h>
2643+
2644+#include <linux/i2c.h>
2645+#include <linux/i2c-ocores.h>
2646+#include <linux/i2c/tsc2007.h>
2647+#include <linux/spi/xilinx_spi.h>
2648+#include "timberdale.h"
2649+
2650+struct timberdale_device {
2651+ resource_size_t intc_mapbase;
2652+ resource_size_t ctl_mapbase;
2653+ unsigned char __iomem *intc_membase;
2654+ unsigned char __iomem *ctl_membase;
2655+ int irq_base;
2656+ u32 irq_ack_mask;
2657+ /* locking from interrupts while modifiying registers */
2658+ spinlock_t lock;
2659+};
2660+
2661+/*--------------------------------------------------------------------------*/
2662+
2663+struct tsc2007_platform_data timberdale_tsc2007_platform_data = {
2664+ .model = 2003,
2665+ .x_plate_ohms = 100
2666+};
2667+
2668+struct i2c_board_info timberdale_i2c_board_info[] = {
2669+ {
2670+ I2C_BOARD_INFO("tsc2003", 0x48),
2671+ .platform_data = &timberdale_tsc2007_platform_data,
2672+ .irq = IRQ_TIMBERDALE_TSC_INT
2673+ },
2674+ {
2675+ I2C_BOARD_INFO("adv7180", 0x42 >> 1),
2676+ .irq = IRQ_TIMBERDALE_ADV7180
2677+ }
2678+};
2679+
2680+static __devinitdata struct ocores_i2c_platform_data
2681+timberdale_i2c_platform_data = {
2682+ .regstep = 4,
2683+ .clock_khz = 62500,
2684+ .devices = timberdale_i2c_board_info,
2685+ .num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
2686+};
2687+
2688+const static __devinitconst struct resource timberdale_i2c_resources[] = {
2689+ {
2690+ .start = I2COFFSET,
2691+ .end = I2CEND,
2692+ .flags = IORESOURCE_MEM,
2693+ },
2694+ {
2695+ .start = IRQ_TIMBERDALE_I2C,
2696+ .end = IRQ_TIMBERDALE_I2C,
2697+ .flags = IORESOURCE_IRQ,
2698+ },
2699+};
2700+
2701+static __devinitdata struct xspi_platform_data timberdale_xspi_platorm_data = {
2702+ .bus_num = -1,
2703+ /* according to spec. we can have up to 32 slaves however,
2704+ * as of current(2009-03-06) revision of
2705+ * Timberdale we can only handle 3 right now
2706+ */
2707+ .num_chipselect = 3,
2708+ .speed_hz = 1953125, /* hardcoded value in IP, for now */
2709+ .cr_offset = 0x60,
2710+ .sr_offset = 0x64,
2711+ .txd_offset = 0x68,
2712+ .rxd_offset = 0x6c,
2713+ .ssr_offset = 0x70
2714+};
2715+
2716+const static __devinitconst struct resource timberdale_spi_resources[] = {
2717+ {
2718+ .start = SPIOFFSET,
2719+ .end = SPIEND,
2720+ .flags = IORESOURCE_MEM,
2721+ },
2722+ {
2723+ .start = IRQ_TIMBERDALE_SPI,
2724+ .end = IRQ_TIMBERDALE_SPI,
2725+ .flags = IORESOURCE_IRQ,
2726+ },
2727+};
2728+
2729+const static __devinitconst struct resource timberdale_eth_resources[] = {
2730+ {
2731+ .start = ETHOFFSET,
2732+ .end = ETHEND,
2733+ .flags = IORESOURCE_MEM,
2734+ },
2735+ {
2736+ .start = IRQ_TIMBERDALE_ETHSW_IF,
2737+ .end = IRQ_TIMBERDALE_ETHSW_IF,
2738+ .flags = IORESOURCE_IRQ,
2739+ },
2740+};
2741+
2742+const static __devinitconst struct resource timberdale_gpio_resources[] = {
2743+ {
2744+ .start = GPIOOFFSET,
2745+ .end = GPIOEND,
2746+ .flags = IORESOURCE_MEM,
2747+ },
2748+ {
2749+ .start = IRQ_TIMBERDALE_GPIO,
2750+ .end = IRQ_TIMBERDALE_GPIO,
2751+ .flags = IORESOURCE_IRQ,
2752+ },
2753+};
2754+
2755+
2756+const static __devinitconst struct resource timberdale_most_resources[] = {
2757+ {
2758+ .start = MOSTOFFSET,
2759+ .end = MOSTEND,
2760+ .flags = IORESOURCE_MEM,
2761+ },
2762+ {
2763+ .start = IRQ_TIMBERDALE_MLB,
2764+ .end = IRQ_TIMBERDALE_MLB,
2765+ .flags = IORESOURCE_IRQ,
2766+ },
2767+};
2768+
2769+const static __devinitconst struct resource timberdale_uart_resources[] = {
2770+ {
2771+ .start = UARTOFFSET,
2772+ .end = UARTEND,
2773+ .flags = IORESOURCE_MEM,
2774+ },
2775+ {
2776+ .start = IRQ_TIMBERDALE_UART,
2777+ .end = IRQ_TIMBERDALE_UART,
2778+ .flags = IORESOURCE_IRQ,
2779+ },
2780+};
2781+
2782+const static __devinitconst struct resource timberdale_i2s_resources[] = {
2783+ {
2784+ .start = I2SOFFSET,
2785+ .end = I2SEND,
2786+ .flags = IORESOURCE_MEM,
2787+ },
2788+ {
2789+ .start = IRQ_TIMBERDALE_I2S,
2790+ .end = IRQ_TIMBERDALE_I2S,
2791+ .flags = IORESOURCE_IRQ,
2792+ },
2793+};
2794+
2795+const static __devinitconst struct resource timberdale_video_resources[] = {
2796+ {
2797+ .start = LOGIWOFFSET,
2798+ .end = LOGIWEND,
2799+ .flags = IORESOURCE_MEM,
2800+ },
2801+ /*
2802+ note that the "frame buffer" is located in DMA area
2803+ starting at 0x1200000
2804+ */
2805+};
2806+
2807+const static __devinitconst struct resource timberdale_dma_resources[] = {
2808+ {
2809+ .start = DMAOFFSET,
2810+ .end = DMAEND,
2811+ .flags = IORESOURCE_MEM,
2812+ },
2813+ {
2814+ .start = IRQ_TIMBERDALE_DMA,
2815+ .end = IRQ_TIMBERDALE_DMA,
2816+ .flags = IORESOURCE_IRQ,
2817+ },
2818+};
2819+
2820+static __devinitdata struct mfd_cell timberdale_cells_bar0[] = {
2821+ {
2822+ .name = "timb-uart",
2823+ .num_resources = ARRAY_SIZE(timberdale_uart_resources),
2824+ .resources = timberdale_uart_resources,
2825+ },
2826+ {
2827+ .name = "ocores-i2c",
2828+ .num_resources = ARRAY_SIZE(timberdale_i2c_resources),
2829+ .resources = timberdale_i2c_resources,
2830+ .platform_data = &timberdale_i2c_platform_data,
2831+ .data_size = sizeof(timberdale_i2c_platform_data),
2832+ },
2833+ {
2834+ .name = "timb-gpio",
2835+ .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
2836+ .resources = timberdale_gpio_resources,
2837+ },
2838+ {
2839+ .name = "timb-i2s",
2840+ .num_resources = ARRAY_SIZE(timberdale_i2s_resources),
2841+ .resources = timberdale_i2s_resources,
2842+ },
2843+ {
2844+ .name = "timb-most",
2845+ .num_resources = ARRAY_SIZE(timberdale_most_resources),
2846+ .resources = timberdale_most_resources,
2847+ },
2848+ {
2849+ .name = "timb-video",
2850+ .num_resources = ARRAY_SIZE(timberdale_video_resources),
2851+ .resources = timberdale_video_resources,
2852+ },
2853+ {
2854+ .name = "xilinx_spi",
2855+ .num_resources = ARRAY_SIZE(timberdale_spi_resources),
2856+ .resources = timberdale_spi_resources,
2857+ .platform_data = &timberdale_xspi_platorm_data,
2858+ .data_size = sizeof(timberdale_xspi_platorm_data),
2859+ },
2860+ {
2861+ .name = "ks884x",
2862+ .num_resources = ARRAY_SIZE(timberdale_eth_resources),
2863+ .resources = timberdale_eth_resources,
2864+ },
2865+ {
2866+ .name = "timb-dma",
2867+ .num_resources = ARRAY_SIZE(timberdale_dma_resources),
2868+ .resources = timberdale_dma_resources,
2869+ },
2870+};
2871+
2872+static const __devinitconst struct resource timberdale_sdhc_resources_bar1[] = {
2873+ {
2874+ .start = SDHC0OFFSET,
2875+ .end = SDHC0END,
2876+ .flags = IORESOURCE_MEM,
2877+ },
2878+ {
2879+ .start = IRQ_TIMBERDALE_SDHC,
2880+ .end = IRQ_TIMBERDALE_SDHC,
2881+ .flags = IORESOURCE_IRQ,
2882+ },
2883+};
2884+
2885+static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
2886+ {
2887+ .name = "sdhci",
2888+ .num_resources = ARRAY_SIZE(timberdale_sdhc_resources_bar1),
2889+ .resources = timberdale_sdhc_resources_bar1,
2890+ },
2891+};
2892+
2893+/*--------------------------------------------------------------------------*/
2894+
2895+
2896+/* Handle the timberdale interrupt mux */
2897+static void timberdale_irq(unsigned int irq, struct irq_desc *desc)
2898+{
2899+ struct timberdale_device *priv = get_irq_data(irq);
2900+ unsigned int i, ipr;
2901+
2902+ desc->chip->ack(irq);
2903+
2904+ while ((ipr = ioread32(priv->intc_membase + IPR))) {
2905+ priv->irq_ack_mask = 0;
2906+ for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
2907+ if (ipr & (1 << i))
2908+ generic_handle_irq(priv->irq_base + i);
2909+ if (priv->irq_ack_mask)
2910+ iowrite32(priv->irq_ack_mask, priv->intc_membase + IAR);
2911+ }
2912+}
2913+
2914+static void timberdale_irq_mask(unsigned int irq)
2915+{
2916+ struct timberdale_device *priv = get_irq_chip_data(irq);
2917+ unsigned long flags;
2918+
2919+ spin_lock_irqsave(&priv->lock, flags);
2920+ iowrite32(1 << (irq - priv->irq_base), priv->intc_membase + CIE);
2921+ spin_unlock_irqrestore(&priv->lock, flags);
2922+}
2923+
2924+static void timberdale_irq_unmask(unsigned int irq)
2925+{
2926+ struct timberdale_device *priv = get_irq_chip_data(irq);
2927+ unsigned long flags;
2928+
2929+ spin_lock_irqsave(&priv->lock, flags);
2930+ iowrite32(1 << (irq - priv->irq_base), priv->intc_membase + SIE);
2931+ spin_unlock_irqrestore(&priv->lock, flags);
2932+}
2933+
2934+static void timberdale_irq_ack(unsigned int irq)
2935+{
2936+ struct timberdale_device *priv = get_irq_chip_data(irq);
2937+ unsigned long flags;
2938+ u32 ack_mask = 1 << (irq - priv->irq_base);
2939+
2940+ spin_lock_irqsave(&priv->lock, flags);
2941+ /* if edge triggered, ack directly. Otherwhise ack in the end of
2942+ * irq handler
2943+ */
2944+ if (ack_mask & IRQ_TIMBERDALE_EDGE_MASK)
2945+ iowrite32(ack_mask, priv->intc_membase + IAR);
2946+ else
2947+ priv->irq_ack_mask |= ack_mask;
2948+ spin_unlock_irqrestore(&priv->lock, flags);
2949+}
2950+
2951+static struct irq_chip timberdale_chip = {
2952+ .name = "timberdale",
2953+ .ack = timberdale_irq_ack,
2954+ .mask = timberdale_irq_mask,
2955+ .unmask = timberdale_irq_unmask,
2956+ .disable = timberdale_irq_mask,
2957+ .enable = timberdale_irq_unmask,
2958+};
2959+
2960+/*--------------------------------------------------------------------------*/
2961+
2962+/* Install the IRQ handler */
2963+static void timberdale_attach_irq(struct pci_dev *dev)
2964+{
2965+ struct timberdale_device *priv = pci_get_drvdata(dev);
2966+ unsigned int irq, irq_base;
2967+
2968+ irq_base = priv->irq_base;
2969+ for (irq = irq_base; irq < irq_base + TIMBERDALE_NR_IRQS; irq++) {
2970+ set_irq_chip_and_handler_name(irq, &timberdale_chip,
2971+ handle_edge_irq, "mux");
2972+
2973+ set_irq_chip_data(irq, priv);
2974+
2975+#ifdef CONFIG_ARM
2976+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
2977+#endif
2978+ }
2979+
2980+ set_irq_data(dev->irq, priv);
2981+ set_irq_chained_handler(dev->irq, timberdale_irq);
2982+}
2983+
2984+static void timberdale_detach_irq(struct pci_dev *dev)
2985+{
2986+ struct timberdale_device *priv = pci_get_drvdata(dev);
2987+ unsigned int irq, irq_base;
2988+
2989+ irq_base = priv->irq_base;
2990+
2991+ set_irq_chained_handler(dev->irq, NULL);
2992+ set_irq_data(dev->irq, NULL);
2993+
2994+ for (irq = irq_base; irq < irq_base + TIMBERDALE_NR_IRQS; irq++) {
2995+#ifdef CONFIG_ARM
2996+ set_irq_flags(irq, 0);
2997+#endif
2998+ set_irq_chip(irq, NULL);
2999+ set_irq_chip_data(irq, NULL);
3000+ }
3001+}
3002+
3003+static int __devinit timb_probe(struct pci_dev *dev,
3004+ const struct pci_device_id *id)
3005+{
3006+ struct timberdale_device *priv;
3007+ int err, i;
3008+ u16 ver;
3009+ resource_size_t mapbase;
3010+
3011+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
3012+ if (!priv)
3013+ return -ENOMEM;
3014+
3015+ spin_lock_init(&priv->lock);
3016+ pci_set_drvdata(dev, priv);
3017+
3018+ err = pci_enable_device(dev);
3019+ if (err)
3020+ goto err_enable;
3021+
3022+ mapbase = pci_resource_start(dev, 0);
3023+ if (!mapbase) {
3024+ printk(KERN_ERR "timberdale: No resource\n");
3025+ goto err_start;
3026+ }
3027+
3028+ /* create a resource for the Interrupt controller registers */
3029+ priv->intc_mapbase = mapbase + INTCOFFSET;
3030+ if (!request_mem_region(priv->intc_mapbase, INTCSIZE, "timb-intc")) {
3031+ printk(KERN_ERR "timberdale: Failed to request intc mem\n");
3032+ goto err_request;
3033+ }
3034+
3035+ /* create a resource for the PCI master register */
3036+ priv->ctl_mapbase = mapbase + CHIPCTLOFFSET;
3037+ if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-intc")) {
3038+ printk(KERN_ERR "timberdale: Failed to request ctl mem\n");
3039+ goto err_request_ctl;
3040+ }
3041+
3042+ priv->intc_membase = ioremap(priv->intc_mapbase, INTCSIZE);
3043+ if (!priv->intc_membase) {
3044+ printk(KERN_ALERT "timberdale: Map error, intc\n");
3045+ goto err_ioremap;
3046+ }
3047+
3048+ priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE);
3049+ if (!priv->ctl_membase) {
3050+ printk(KERN_ALERT "timberdale: Map error, ctl\n");
3051+ goto err_ioremap_ctl;
3052+ }
3053+
3054+ err = pci_enable_msi(dev);
3055+ if (err) {
3056+ printk(KERN_WARNING "timberdale: MSI init failed: %d\n", err);
3057+ goto err_msi;
3058+ }
3059+
3060+ /* Reset all FPGA PLB peripherals */
3061+ iowrite32(0x1, priv->ctl_membase + MAYSVILLERST);
3062+
3063+ /* at this stage the FPGA does not generate a
3064+ * unique interrupt per function, to emulate real interrupts
3065+ * we assign them a faked interrupt which we issue in the
3066+ * interrupt handler. For now just hard code a base number
3067+ */
3068+ priv->irq_base = NR_IRQS - TIMBERDALE_NR_IRQS - 1;
3069+ if (priv->irq_base < dev->irq)
3070+ /* ops the device itself got the IRQ in the end... */
3071+ priv->irq_base = 400;
3072+
3073+ timberdale_attach_irq(dev);
3074+
3075+ /* update IRQ offsets in I2C board info */
3076+ for (i = 0; i < ARRAY_SIZE(timberdale_i2c_board_info); i++)
3077+ timberdale_i2c_board_info[i].irq += priv->irq_base;
3078+
3079+ /* don't leave platform_data empty on any device */
3080+ for (i = 0; i < ARRAY_SIZE(timberdale_cells_bar0); i++)
3081+ if (timberdale_cells_bar0[i].platform_data == NULL) {
3082+ timberdale_cells_bar0[i].platform_data =
3083+ timberdale_cells_bar0 + i;
3084+ timberdale_cells_bar0[i].data_size =
3085+ sizeof(timberdale_cells_bar0[i]);
3086+ }
3087+
3088+ err = mfd_add_devices(&dev->dev, -1,
3089+ timberdale_cells_bar0, ARRAY_SIZE(timberdale_cells_bar0),
3090+ &dev->resource[0], priv->irq_base);
3091+ if (err)
3092+ printk(KERN_WARNING
3093+ "timberdale: mfd_add_devices failed: %d\n", err);
3094+ else {
3095+ err = mfd_add_devices(&dev->dev, -1,
3096+ timberdale_cells_bar1,
3097+ ARRAY_SIZE(timberdale_cells_bar1),
3098+ &dev->resource[1], priv->irq_base);
3099+
3100+ if (err)
3101+ printk(KERN_WARNING
3102+ "timberdale: timb_add_sdhci failed: %d\n", err);
3103+ }
3104+
3105+ if (err)
3106+ goto err_mfd;
3107+
3108+ ver = ioread16(priv->ctl_membase + TIMB_REV);
3109+
3110+ printk(KERN_INFO "Found Maysville Card. Rev: %d\n", ver);
3111+
3112+ /* Enable interrupts and wire the hardware interrupts */
3113+ iowrite32(0x3, priv->intc_membase + MER);
3114+
3115+ return 0;
3116+err_mfd:
3117+ timberdale_detach_irq(dev);
3118+ pci_disable_msi(dev);
3119+err_msi:
3120+ iounmap(priv->ctl_membase);
3121+err_ioremap_ctl:
3122+ iounmap(priv->intc_membase);
3123+err_ioremap:
3124+ release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
3125+err_request_ctl:
3126+ release_mem_region(priv->intc_mapbase, INTCSIZE);
3127+err_request:
3128+ pci_set_drvdata(dev, NULL);
3129+err_start:
3130+ pci_disable_device(dev);
3131+err_enable:
3132+ kfree(priv);
3133+ pci_set_drvdata(dev, NULL);
3134+ return -ENODEV;
3135+}
3136+
3137+static void __devexit timb_remove(struct pci_dev *dev)
3138+{
3139+ /* clean up any allocated resources and stuff here.
3140+ * like call release_region();
3141+ */
3142+ struct timberdale_device *priv;
3143+
3144+ priv = pci_get_drvdata(dev);
3145+
3146+ mfd_remove_devices(&dev->dev);
3147+
3148+ timberdale_detach_irq(dev);
3149+
3150+ iowrite32(0xffffffff, priv->intc_membase + IAR);
3151+ iowrite32(0, priv->intc_membase + MER);
3152+ iowrite32(0, priv->intc_membase + IER);
3153+
3154+ iounmap(priv->ctl_membase);
3155+ iounmap(priv->intc_membase);
3156+ release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
3157+ release_mem_region(priv->intc_mapbase, INTCSIZE);
3158+
3159+ pci_disable_msi(dev);
3160+ pci_disable_device(dev);
3161+ pci_set_drvdata(dev, NULL);
3162+ kfree(priv);
3163+}
3164+
3165+static struct pci_device_id timberdale_pci_tbl[] = {
3166+ { PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
3167+ { 0 }
3168+};
3169+MODULE_DEVICE_TABLE(pci, timberdale_pci_tbl);
3170+
3171+static struct pci_driver timberdale_pci_driver = {
3172+ .name = "timberdale",
3173+ .id_table = timberdale_pci_tbl,
3174+ .probe = timb_probe,
3175+ .remove = timb_remove,
3176+};
3177+
3178+static int __init timberdale_init(void)
3179+{
3180+ int err;
3181+
3182+ err = pci_register_driver(&timberdale_pci_driver);
3183+ if (err < 0) {
3184+ printk(KERN_ERR
3185+ "Failed to register PCI driver for %s device.\n",
3186+ timberdale_pci_driver.name);
3187+ return -ENODEV;
3188+ }
3189+
3190+ printk(KERN_INFO "Driver for %s has been successfully registered.\n",
3191+ timberdale_pci_driver.name);
3192+
3193+ return 0;
3194+}
3195+
3196+static void __exit timberdale_exit(void)
3197+{
3198+ pci_unregister_driver(&timberdale_pci_driver);
3199+
3200+ printk(KERN_INFO "Driver for %s has been successfully unregistered.\n",
3201+ timberdale_pci_driver.name);
3202+}
3203+
3204+MODULE_LICENSE("GPL v2");
3205+MODULE_VERSION(DRV_VERSION);
3206+MODULE_AUTHOR("Richard Rojfors");
3207+
3208+module_init(timberdale_init);
3209+module_exit(timberdale_exit);
3210+
3211diff -uNr linux-2.6.29-clean/drivers/mfd/timberdale.h linux-2.6.29/drivers/mfd/timberdale.h
3212--- linux-2.6.29-clean/drivers/mfd/timberdale.h 1969-12-31 16:00:00.000000000 -0800
3213+++ linux-2.6.29/drivers/mfd/timberdale.h 2009-04-06 13:51:47.000000000 -0700
3214@@ -0,0 +1,114 @@
3215+/*
3216+ * timberdale.h timberdale FPGA mfd shim driver defines
3217+ * Copyright (c) 2009 Intel Corporation
3218+ *
3219+ * This program is free software; you can redistribute it and/or modify
3220+ * it under the terms of the GNU General Public License version 2 as
3221+ * published by the Free Software Foundation.
3222+ *
3223+ * This program is distributed in the hope that it will be useful,
3224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3226+ * GNU General Public License for more details.
3227+ *
3228+ * You should have received a copy of the GNU General Public License
3229+ * along with this program; if not, write to the Free Software
3230+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3231+ */
3232+
3233+/* Supports:
3234+ * Timberdale FPGA
3235+ */
3236+
3237+#ifndef MFD_TIMBERDALE_H
3238+#define MFD_TIMBERDALE_H
3239+
3240+/* Registers of the interrupt controller */
3241+#define ISR 0x00
3242+#define IPR 0x04
3243+#define IER 0x08
3244+#define IAR 0x0c
3245+#define SIE 0x10
3246+#define CIE 0x14
3247+#define MER 0x1c
3248+
3249+/* Registers of the control area */
3250+#define TIMB_REV 0x00
3251+#define MAYSVILLERST 0x40
3252+
3253+
3254+#define I2COFFSET 0x0
3255+#define I2CEND 0x1f
3256+
3257+#define SPIOFFSET 0x80
3258+#define SPIEND 0xff
3259+
3260+#define ETHOFFSET 0x300
3261+#define ETHEND 0x30f
3262+
3263+#define GPIOOFFSET 0x400
3264+#define GPIOEND 0x7ff
3265+
3266+#define CHIPCTLOFFSET 0x800
3267+#define CHIPCTLEND 0x8ff
3268+#define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET)
3269+
3270+#define INTCOFFSET 0xc00
3271+#define INTCEND 0xfff
3272+#define INTCSIZE (INTCEND - INTCOFFSET)
3273+
3274+#define MOSTOFFSET 0x1000
3275+#define MOSTEND 0x13ff
3276+
3277+#define UARTOFFSET 0x1400
3278+#define UARTEND 0x17ff
3279+
3280+#define I2SOFFSET 0x1C00
3281+#define I2SEND 0x1fff
3282+
3283+#define LOGIWOFFSET 0x30000
3284+#define LOGIWEND 0x37fff
3285+
3286+#define DMAOFFSET 0x01000000
3287+#define DMAEND 0x013fffff
3288+
3289+/* SDHC0 is placed in PCI bar 1 */
3290+#define SDHC0OFFSET 0x00
3291+#define SDHC0END 0xff
3292+
3293+/* SDHC1 is placed in PCI bar 2 */
3294+#define SDHC1OFFSET 0x00
3295+#define SDHC1END 0xff
3296+
3297+#define PCI_VENDOR_ID_TIMB 0x10ee
3298+#define PCI_DEVICE_ID_TIMB 0xa123
3299+#define DRV_VERSION "0.1"
3300+
3301+
3302+#define IRQ_TIMBERDALE_INIC 0
3303+#define IRQ_TIMBERDALE_MLB 1
3304+#define IRQ_TIMBERDALE_GPIO 2
3305+#define IRQ_TIMBERDALE_I2C 3
3306+#define IRQ_TIMBERDALE_UART 4
3307+#define IRQ_TIMBERDALE_DMA 5
3308+#define IRQ_TIMBERDALE_I2S 6
3309+#define IRQ_TIMBERDALE_TSC_INT 7
3310+#define IRQ_TIMBERDALE_SDHC 8
3311+#define IRQ_TIMBERDALE_ADV7180 9
3312+#define IRQ_TIMBERDALE_ETHSW_IF 10
3313+#define IRQ_TIMBERDALE_SPI 11
3314+
3315+#define TIMBERDALE_NR_IRQS 12
3316+
3317+/* Some of the interrupts are level triggered, some are edge triggered */
3318+#define IRQ_TIMBERDALE_EDGE_MASK ((1 << IRQ_TIMBERDALE_ADV7180) | \
3319+ (1 << IRQ_TIMBERDALE_TSC_INT) | (1 << IRQ_TIMBERDALE_DMA) | \
3320+ (1 << IRQ_TIMBERDALE_MLB) | (1 << IRQ_TIMBERDALE_INIC))
3321+
3322+#define IRQ_TIMBERDALE_LEVEL_MASK ((1 << IRQ_TIMBERDALE_SPI) | \
3323+ (1 << IRQ_TIMBERDALE_ETHSW_IF) | (1 << IRQ_TIMBERDALE_SDHC) | \
3324+ (1 << IRQ_TIMBERDALE_I2S) | (1 << IRQ_TIMBERDALE_UART) | \
3325+ (1 << IRQ_TIMBERDALE_I2C) | (1 << IRQ_TIMBERDALE_GPIO))
3326+
3327+#endif
3328+
3329diff -uNr linux-2.6.29-clean/drivers/mfd/timbi2s.c linux-2.6.29/drivers/mfd/timbi2s.c
3330--- linux-2.6.29-clean/drivers/mfd/timbi2s.c 1969-12-31 16:00:00.000000000 -0800
3331+++ linux-2.6.29/drivers/mfd/timbi2s.c 2009-04-06 13:51:47.000000000 -0700
3332@@ -0,0 +1,597 @@
3333+/*
3334+ * timbi2s.c timberdale FPGA I2S driver
3335+ * Copyright (c) 2009 Intel Corporation
3336+ *
3337+ * This program is free software; you can redistribute it and/or modify
3338+ * it under the terms of the GNU General Public License version 2 as
3339+ * published by the Free Software Foundation.
3340+ *
3341+ * This program is distributed in the hope that it will be useful,
3342+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3343+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3344+ * GNU General Public License for more details.
3345+ *
3346+ * You should have received a copy of the GNU General Public License
3347+ * along with this program; if not, write to the Free Software
3348+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3349+ */
3350+
3351+/* Supports:
3352+ * Timberdale FPGA I2S
3353+ *
3354+ * As of 2009-03-23 I2S instances
3355+ * are not configured as masters
3356+ *
3357+ * TODO: implement switching between master and slave
3358+ */
3359+
3360+#include <linux/io.h>
3361+#include <linux/fs.h>
3362+#include <linux/module.h>
3363+#include <linux/circ_buf.h>
3364+#include <linux/spinlock.h>
3365+#include <linux/workqueue.h>
3366+#include <linux/interrupt.h>
3367+#include <linux/platform_device.h>
3368+
3369+#include <linux/mfd/timbi2s.h>
3370+
3371+#define DRIVER_NAME "timb-i2s"
3372+
3373+#define I2S_CLOCK_SPEED 62500000 /* 62,5MHz */
3374+
3375+#define FIFO_FILL_SIZE 127
3376+#define I2S_BUFFER_SIZE PAGE_SIZE
3377+
3378+#define ALMOST_FULL 170
3379+#define ALMOST_EMPTY 85
3380+
3381+/* As of 2009-03-16, IP can instanciate max. 4 RX and 4 TX */
3382+#define MAX_TX_NR 4
3383+#define MAX_RX_NR 4
3384+/* and actually up and running only 4.
3385+ * 1 TX and 3 RX
3386+ */
3387+#define IP_I2S_NR 4
3388+#define REGSTEP 0x04
3389+
3390+#define VERSION 0x00
3391+#define I2S_UIR 0x04 /* Unit Interrupt Register */
3392+
3393+/* Registers for all possible I2S IP instances
3394+ * are the same as for first one (from 0x08 to 0x20)
3395+ */
3396+#define I2S_PRESCALE 0x08 /* Holds prescale value, if clock master */
3397+#define I2S_ICR 0x0c /* Interrupt Clear Register */
3398+# define ICR_F 0x01 /* Full */
3399+# define ICR_AF 0x02 /* Almost full */
3400+# define ICR_AE 0x04 /* Almost empty */
3401+# define ICR_RX_D 0x08 /* Data present, RX only */
3402+# define ICR_TX_E 0x08 /* Epmty, TX only */
3403+
3404+#define I2S_IPR 0x10 /* Interrupt Pending Register */
3405+#define I2S_ISR 0x14 /* Interrupt Status Register */
3406+
3407+#define I2S_IER 0x18 /* Interrupt Enable Register */
3408+# define IER_FF 0x01 /* RX/TX FIFO Full */
3409+# define IER_FAF 0x02 /* RX/TX FIFO Almost Full */
3410+# define IER_FAE 0x04 /* RX/TX FIFO Almost Empty */
3411+# define IER_RX_DATA 0x08 /* RX. Data Present */
3412+# define IER_TX_FE 0x08 /* TX. FIFO Empty */
3413+
3414+#define I2S_CTRL 0x1c /* Control Register */
3415+# define CTRL_TX_ENABLE 0x01 /* Enable TX */
3416+# define CTRL_RX_ENABLE 0x02 /* Enable RX */
3417+# define CTRL_NONE 0x04 /* Not used */
3418+# define CTRL_FIFO_CLR 0x08 /* FIFO Clear */
3419+# define CTRL_SWR 0x10 /* Soft reset */
3420+# define CTRL_CLKMASTER 0x1000 /* IP I2S instance is master */
3421+# define CTRL_IS_TX 0x40000000 /* IP I2S is an TX-instance */
3422+# define CTRL_IS_RX 0x20000000 /* IP I2S is an RX-instance */
3423+
3424+#define I2S_FIFO 0x20 /* read/write FIFO */
3425+
3426+#define INC_HEAD(buf, size) \
3427+ (buf->head = (buf->head + 1) & (size-1))
3428+
3429+#define INC_TAIL(buf, size) \
3430+ (buf->tail = (buf->tail + 1) & (size-1))
3431+
3432+
3433+/* circular buffer */
3434+static struct circ_buf *timbi2s_buf_alloc(void);
3435+static void timbi2s_buf_free(struct circ_buf *cb);
3436+static void timbi2s_buf_clear(struct circ_buf *cb);
3437+
3438+static int timbi2s_fifo_read(struct circ_buf *cb, ssize_t count, long add);
3439+static int timbi2s_fifo_write(struct circ_buf *cb, ssize_t count, long add);
3440+
3441+static int timbi2s_ioctrl(struct timbi2s_dev *);
3442+
3443+static struct timbi2s_bus *bus_p;
3444+
3445+static int timbi2s_is_tx(struct timbi2s_dev *i2sdev)
3446+{
3447+ return (ioread32(i2sdev->membase + i2sdev->ctrl_offset)
3448+ & CTRL_IS_TX) ? 1 : 0;
3449+}
3450+
3451+static int timbi2s_is_rx(struct timbi2s_dev *i2sdev)
3452+{
3453+ return (ioread32(i2sdev->membase + i2sdev->ctrl_offset)
3454+ & CTRL_IS_RX) ? 1 : 0;
3455+}
3456+
3457+/* Return unused TX-instance */
3458+static struct timbi2s_dev *timbi2s_get_tx(void)
3459+{
3460+ struct timbi2s_dev *tdev, *tmp;
3461+
3462+ if (bus_p == NULL)
3463+ return NULL;
3464+
3465+ list_for_each_entry_safe(tdev, tmp, &bus_p->control->list, item) {
3466+ if (!tdev->in_use && timbi2s_is_tx(tdev)) {
3467+ tdev->in_use = 1;
3468+ return tdev;
3469+ }
3470+
3471+ }
3472+ return NULL;
3473+}
3474+EXPORT_SYMBOL_GPL(timbi2s_get_tx);
3475+
3476+/* Return unused RX-instance */
3477+static struct timbi2s_dev *timbi2s_get_rx(void)
3478+{
3479+ struct timbi2s_dev *tdev, *tmp;
3480+
3481+ if (bus_p == NULL)
3482+ return NULL;
3483+
3484+ list_for_each_entry_safe(tdev, tmp, &bus_p->control->list, item) {
3485+ if (!tdev->in_use && timbi2s_is_rx(tdev)) {
3486+ tdev->in_use = 1;
3487+ return tdev;
3488+ }
3489+
3490+ }
3491+ return NULL;
3492+}
3493+EXPORT_SYMBOL_GPL(timbi2s_get_rx);
3494+
3495+/* Flag TX/RX as unused and reset it */
3496+static void timbi2s_put(struct timbi2s_dev *tdev)
3497+{
3498+ if (tdev->in_use) {
3499+ tdev->in_use = 0;
3500+ timbi2s_ioctrl(tdev);
3501+ }
3502+}
3503+EXPORT_SYMBOL_GPL(timbi2s_put);
3504+
3505+/*
3506+ * Write data to the FIFO
3507+ */
3508+static void timbi2s_tx_handler(struct timbi2s_dev *i2sdev)
3509+{
3510+ u32 pend;
3511+
3512+ pend = ioread32(i2sdev->membase + i2sdev->ipr_offset);
3513+
3514+ if (pend & IER_FAE) {
3515+ timbi2s_fifo_write(i2sdev->buffer,
3516+ ALMOST_FULL - ALMOST_EMPTY,
3517+ (unsigned long)i2sdev->membase +
3518+ i2sdev->fifo);
3519+ /* clear interrupt */
3520+ iowrite32(ICR_AE, i2sdev->membase + i2sdev->icr_offset);
3521+ }
3522+}
3523+
3524+/*
3525+ * Read data from the FIFO
3526+ */
3527+static void timbi2s_rx_handler(struct timbi2s_dev *i2sdev)
3528+{
3529+ u32 pend;
3530+ pend = ioread32(i2sdev->membase + i2sdev->ipr_offset);
3531+
3532+ if (pend & IER_FAE) {
3533+ timbi2s_fifo_read(i2sdev->buffer,
3534+ ALMOST_EMPTY,
3535+ (unsigned long)i2sdev->membase +
3536+ i2sdev->fifo);
3537+
3538+ /* clear interrupt */
3539+ iowrite32(ICR_AE | ICR_AF,
3540+ i2sdev->membase + i2sdev->icr_offset);
3541+ }
3542+}
3543+
3544+void timbi2s_int_handler(struct work_struct *workp)
3545+{
3546+ u32 pend, stat, i2stype;
3547+ unsigned long flags;
3548+ struct timbi2s_dev *i2sdev = container_of(workp,
3549+ struct timbi2s_dev,
3550+ work);
3551+
3552+ pend = ioread32(i2sdev->membase + i2sdev->ipr_offset);
3553+ stat = ioread32(i2sdev->membase + i2sdev->isr_offset);
3554+ i2stype = ioread32(i2sdev->membase + i2sdev->ctrl_offset);
3555+
3556+ spin_lock_irqsave(&i2sdev->lock, flags);
3557+
3558+ if (i2stype & CTRL_IS_RX) {
3559+ /* Enable Almost Empty Almost Full interrupt */
3560+ iowrite32(IER_FAE | IER_FAF,
3561+ i2sdev->membase + i2sdev->ier_offset);
3562+ /* Enable RX */
3563+ iowrite32(CTRL_RX_ENABLE,
3564+ i2sdev->membase + i2sdev->ctrl_offset);
3565+ timbi2s_rx_handler(i2sdev);
3566+ } else if (i2stype & CTRL_IS_TX) {
3567+ /* Enable Almost Empty interrupt */
3568+ iowrite32(IER_FAE, i2sdev->membase + i2sdev->ier_offset);
3569+ /* Enable TX */
3570+ iowrite32(CTRL_TX_ENABLE,
3571+ i2sdev->membase + i2sdev->ctrl_offset);
3572+ timbi2s_tx_handler(i2sdev);
3573+ }
3574+
3575+ spin_unlock_irqrestore(&i2sdev->lock, flags);
3576+}
3577+
3578+static int timbi2s_ioctrl(struct timbi2s_dev *i2sdev)
3579+{
3580+ u32 i2stype;
3581+
3582+ /* Reset */
3583+ iowrite8(CTRL_SWR, i2sdev->membase + i2sdev->ctrl_offset);
3584+ /* Clear IER */
3585+ iowrite32(0x00000000, i2sdev->membase + i2sdev->ier_offset);
3586+ /* Clear ICR */
3587+ iowrite32(0xffffffff, i2sdev->membase + i2sdev->icr_offset);
3588+
3589+ i2stype = ioread32(i2sdev->membase + i2sdev->ctrl_offset);
3590+
3591+ if (i2stype & CTRL_IS_TX)
3592+ printk(KERN_INFO DRIVER_NAME": found active I2S Transmitter\n");
3593+ else if (i2stype & CTRL_IS_RX)
3594+ printk(KERN_INFO DRIVER_NAME": found active I2S Receiver\n");
3595+
3596+ return 1;
3597+}
3598+EXPORT_SYMBOL_GPL(timbi2s_ioctrl);
3599+
3600+static struct circ_buf *timbi2s_buf_alloc(void)
3601+{
3602+ struct circ_buf *cb;
3603+
3604+ cb = kzalloc(sizeof(*cb), GFP_KERNEL);
3605+ if (cb == NULL)
3606+ return NULL;
3607+
3608+ cb->buf = kzalloc(I2S_BUFFER_SIZE, GFP_KERNEL);
3609+ if (cb->buf == NULL) {
3610+ kfree(cb);
3611+ return NULL;
3612+ }
3613+
3614+ timbi2s_buf_clear(cb);
3615+
3616+ return cb;
3617+}
3618+
3619+static void timbi2s_buf_free(struct circ_buf *cb)
3620+{
3621+ kfree(cb->buf);
3622+ kfree(cb);
3623+}
3624+
3625+static void timbi2s_buf_clear(struct circ_buf *cb)
3626+{
3627+ cb->head = 0;
3628+ cb->tail = cb->head;
3629+}
3630+
3631+/*
3632+ * Read data from the FIFO and write it to the given circular buffer
3633+ */
3634+static int timbi2s_fifo_read(struct circ_buf *cb, ssize_t count, long add)
3635+{
3636+ int c, ret = 0;
3637+
3638+ unsigned char *hi = (unsigned char *)ioread32((void *)(add >> 16));
3639+ unsigned char *lo = (unsigned char *)ioread32((void *)(add & 0xFFFF));
3640+
3641+ c = CIRC_SPACE_TO_END(cb->head, cb->tail, I2S_BUFFER_SIZE);
3642+ if (count < c)
3643+ c = count;
3644+
3645+ if (c <= 0)
3646+ return 1;
3647+
3648+ while (c >= 0) {
3649+ memcpy(cb->buf + cb->head, hi, 2);
3650+ INC_HEAD(cb, I2S_BUFFER_SIZE);
3651+
3652+ memcpy(cb->buf + cb->head, lo, 2);
3653+ INC_HEAD(cb, I2S_BUFFER_SIZE);
3654+ count -= 4;
3655+ }
3656+ return ret;
3657+}
3658+
3659+/*
3660+ * Get data from the circular buffer and write it to the given FIFO address
3661+ */
3662+static int timbi2s_fifo_write(struct circ_buf *cb, ssize_t count, long add)
3663+{
3664+ int c, ret = 0;
3665+
3666+ c = CIRC_CNT_TO_END(cb->head, cb->tail, I2S_BUFFER_SIZE);
3667+ if (count < c)
3668+ c = count;
3669+
3670+ if (c <= 0)
3671+ return 1;
3672+
3673+ while (c >= 0) {
3674+ iowrite32(*(s16 *)(cb->buf + cb->tail), (void *)(add >> 16));
3675+ INC_TAIL(cb, I2S_BUFFER_SIZE);
3676+
3677+ iowrite32(*(s16 *)(cb->buf + cb->tail), (void *)(add & 0xFFFF));
3678+ INC_TAIL(cb, I2S_BUFFER_SIZE);
3679+ count -= 4;
3680+ }
3681+
3682+ return ret;
3683+}
3684+
3685+static void timbi2s_control_destroy(struct timbi2s_bus_control *control)
3686+{
3687+ kfree(control);
3688+ control = NULL;
3689+}
3690+
3691+static void timbi2s_control_add_dev(struct timbi2s_dev *i2sdev)
3692+{
3693+ list_add(&i2sdev->item, &i2sdev->bus->control->list);
3694+}
3695+
3696+static void timbi2s_control_del_dev(struct timbi2s_dev *i2sdev)
3697+{
3698+ list_del(&i2sdev->item);
3699+ if (list_empty(&i2sdev->bus->control->list))
3700+ timbi2s_control_destroy(i2sdev->bus->control);
3701+}
3702+
3703+static irqreturn_t timbi2s_irq(int irq, void *dev_id)
3704+{
3705+ u8 pend;
3706+ u32 iunit;
3707+ int i;
3708+
3709+ struct timbi2s_bus *tbus = dev_id;
3710+ queue_work(tbus->workqueue, &tbus->work);
3711+
3712+ iunit = ioread32(tbus->membase + I2S_UIR);
3713+ /* Find out which I2S instance is interrupting */
3714+ for (i = 0; i < 32; i++) {
3715+ if ((1 << i) & iunit) {
3716+ pend = ioread8(tbus->membase +
3717+ (I2S_IPR + (i * REGSTEP * 7)));
3718+ iowrite8(pend, tbus->membase +
3719+ (I2S_ICR + (i * REGSTEP * 7)));
3720+ }
3721+ }
3722+
3723+ return IRQ_HANDLED;
3724+}
3725+
3726+static int __init timbi2s_probe(struct platform_device *dev)
3727+{
3728+ int err = 0;
3729+ struct timbi2s_dev *tdev, *tmp;
3730+ struct timbi2s_bus *tbus;
3731+ struct resource *iomem;
3732+ int i;
3733+
3734+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
3735+ if (!iomem) {
3736+ err = -EINVAL;
3737+ goto err_mem;
3738+ }
3739+
3740+ tbus = kzalloc(sizeof(*tbus), GFP_KERNEL);
3741+ if (!tbus) {
3742+ err = -EINVAL;
3743+ goto err_mem;
3744+ }
3745+
3746+ /* Init bus_control */
3747+ tbus->control = kzalloc(sizeof(struct timbi2s_bus_control), GFP_KERNEL);
3748+ if (!tbus->control) {
3749+ printk(KERN_ERR DRIVER_NAME
3750+ ": Failed to allocate timbi2s_bus_control.\n");
3751+ err = -ENOMEM;
3752+ goto err_free;
3753+ }
3754+ INIT_LIST_HEAD(&tbus->control->list);
3755+
3756+ /* Init workqueue */
3757+ tbus->workqueue = create_singlethread_workqueue("timbi2s");
3758+ if (tbus->workqueue == NULL) {
3759+ printk(KERN_ERR DRIVER_NAME
3760+ ": unable to create workqueue\n");
3761+ err = -ENOMEM;
3762+ goto err_control;
3763+ }
3764+ INIT_WORK(&tbus->work, timbi2s_int_handler);
3765+
3766+ if (!request_mem_region(iomem->start,
3767+ resource_size(iomem), DRIVER_NAME)) {
3768+ printk(KERN_EMERG DRIVER_NAME
3769+ ": Mem region is already in use\n");
3770+ err = -ENXIO;
3771+ goto err_control;
3772+ }
3773+
3774+ tbus->membase = ioremap(iomem->start, resource_size(iomem));
3775+ if (tbus->membase == NULL) {
3776+ err = -ENOMEM;
3777+ goto err_request;
3778+ }
3779+
3780+ bus_p = tbus;
3781+
3782+
3783+
3784+ /* For now we have only 4 I2S instances in IP : 3 RX and 1 TX */
3785+ /* Note: TX'es are always on top */
3786+ /* TODO: auto-check how many are alive and bring them into control */
3787+ for (i = 0; i < IP_I2S_NR; i++) {
3788+ tdev = kzalloc(sizeof(*tdev), GFP_KERNEL);
3789+ if (!tdev) {
3790+ err = -EINVAL;
3791+ goto clean_list;
3792+ }
3793+
3794+ /* Allocate circ_buf */
3795+ tdev->buffer = timbi2s_buf_alloc();
3796+ if (tdev->buffer == NULL) {
3797+ printk(KERN_ERR "timbi2s: unable to allocate buffer\n");
3798+ goto clean_list;
3799+ }
3800+
3801+ INIT_LIST_HEAD(&tdev->item);
3802+ spin_lock_init(&tdev->lock);
3803+
3804+ /* set up offsets for each instance of I2S */
3805+ tdev->bus = tbus; /* ptr to our bus */
3806+ tdev->membase = tbus->membase;
3807+ tdev->in_use = 0;
3808+ tdev->pscale_offset = I2S_PRESCALE + (i * REGSTEP * 7);
3809+ tdev->icr_offset = I2S_ICR + (i * REGSTEP * 7);
3810+ tdev->isr_offset = I2S_ISR + (i * REGSTEP * 7);
3811+ tdev->ipr_offset = I2S_IPR + (i * REGSTEP * 7);
3812+ tdev->ier_offset = I2S_IER + (i * REGSTEP * 7);
3813+ tdev->ctrl_offset = I2S_CTRL + (i * REGSTEP * 7);
3814+ tdev->fifo = I2S_FIFO + (i * REGSTEP * 7);
3815+
3816+ /* Try to check and reset hardware */
3817+ if (timbi2s_ioctrl(tdev))
3818+ timbi2s_control_add_dev(tdev);
3819+
3820+ tdev = NULL;
3821+ }
3822+
3823+ tbus->irq = platform_get_irq(dev, 0);
3824+ if (tbus->irq < 0) {
3825+ err = -EINVAL;
3826+ goto clean_list;
3827+ }
3828+
3829+ err = request_irq(tbus->irq, timbi2s_irq, 0, DRIVER_NAME, tbus);
3830+ if (err != 0)
3831+ goto clean_list;
3832+
3833+ platform_set_drvdata(dev, tbus);
3834+
3835+ dev_info(&dev->dev, "Driver for Timberdale I2S (ver: %d)"
3836+ " has been successfully registered.\n",
3837+ ioread32(tbus->membase + 0x00));
3838+ return 0;
3839+
3840+clean_list:
3841+ list_for_each_entry_safe(tdev, tmp, &tbus->control->list, item) {
3842+ if (tdev->workqueue != NULL) {
3843+ flush_workqueue(tdev->workqueue);
3844+ destroy_workqueue(tdev->workqueue);
3845+ }
3846+
3847+ if (tdev->buffer != NULL)
3848+ timbi2s_buf_free(tdev->buffer);
3849+
3850+ timbi2s_control_del_dev(tdev);
3851+ kfree(tdev);
3852+ }
3853+ free_irq(tbus->irq, tbus);
3854+ iounmap(tbus->membase);
3855+err_request:
3856+ release_mem_region(iomem->start, resource_size(iomem));
3857+err_control:
3858+ if (tbus->control != NULL)
3859+ timbi2s_control_destroy(tbus->control);
3860+err_free:
3861+ kfree(tbus);
3862+err_mem:
3863+ printk(KERN_ERR
3864+ DRIVER_NAME": Failed to register Timberdale I2S: %d\n", err);
3865+
3866+ return err;
3867+}
3868+
3869+static int __devexit timbi2s_remove(struct platform_device *dev)
3870+{
3871+ struct timbi2s_bus *tbus;
3872+ struct timbi2s_dev *tdev, *tmp;
3873+ struct resource *r;
3874+
3875+ tbus = platform_get_drvdata(dev);
3876+ free_irq(tbus->irq, tbus);
3877+
3878+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
3879+
3880+ list_for_each_entry_safe(tdev, tmp, &tbus->control->list, item) {
3881+ if (tdev->workqueue != NULL) {
3882+ flush_workqueue(tdev->workqueue);
3883+ destroy_workqueue(tdev->workqueue);
3884+ }
3885+
3886+ if (tdev->buffer != NULL)
3887+ timbi2s_buf_free(tdev->buffer);
3888+
3889+ kfree(tdev);
3890+ }
3891+
3892+ iounmap(tdev->membase);
3893+ if (r)
3894+ release_mem_region(r->start, resource_size(r));
3895+
3896+ dev_info(&dev->dev, "Driver for Timberdale I2S has been"
3897+ " successfully unregistered.\n");
3898+
3899+ platform_set_drvdata(dev, 0);
3900+ return 0;
3901+}
3902+
3903+static struct platform_driver timbi2s_platform_driver = {
3904+ .driver = {
3905+ .name = DRIVER_NAME,
3906+ .owner = THIS_MODULE,
3907+ },
3908+ .probe = timbi2s_probe,
3909+ .remove = __devexit_p(timbi2s_remove),
3910+};
3911+
3912+/*--------------------------------------------------------------------------*/
3913+
3914+static int __init timbi2s_init(void)
3915+{
3916+ return platform_driver_register(&timbi2s_platform_driver);
3917+}
3918+
3919+static void __exit timbi2s_exit(void)
3920+{
3921+ platform_driver_unregister(&timbi2s_platform_driver);
3922+}
3923+
3924+module_init(timbi2s_init);
3925+module_exit(timbi2s_exit);
3926+
3927+MODULE_AUTHOR("Mocean Laboratories");
3928+MODULE_DESCRIPTION("Timberdale I2S bus driver");
3929+MODULE_LICENSE("GPL v2");
3930diff -uNr linux-2.6.29-clean/drivers/mmc/host/Kconfig linux-2.6.29/drivers/mmc/host/Kconfig
3931--- linux-2.6.29-clean/drivers/mmc/host/Kconfig 2009-04-01 09:20:24.000000000 -0700
3932+++ linux-2.6.29/drivers/mmc/host/Kconfig 2009-04-06 13:51:47.000000000 -0700
3933@@ -65,6 +65,16 @@
3934
3935 If unsure, say Y.
3936
3937+config MMC_SDHCI_PLTFM
3938+ tristate "SDHCI support on platform devices"
3939+ depends on MMC_SDHCI
3940+ help
3941+ This selects the Secure Digital Host Controller Interface.
3942+
3943+ If you have a controller with this interface, say Y or M here.
3944+
3945+ If unsure, say N.
3946+
3947 config MMC_OMAP
3948 tristate "TI OMAP Multimedia Card Interface support"
3949 depends on ARCH_OMAP
3950diff -uNr linux-2.6.29-clean/drivers/mmc/host/Makefile linux-2.6.29/drivers/mmc/host/Makefile
3951--- linux-2.6.29-clean/drivers/mmc/host/Makefile 2009-04-01 09:20:24.000000000 -0700
3952+++ linux-2.6.29/drivers/mmc/host/Makefile 2009-04-06 13:51:47.000000000 -0700
3953@@ -13,6 +13,7 @@
3954 obj-$(CONFIG_MMC_SDHCI) += sdhci.o
3955 obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
3956 obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
3957+obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
3958 obj-$(CONFIG_MMC_WBSD) += wbsd.o
3959 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
3960 obj-$(CONFIG_MMC_OMAP) += omap.o
3961diff -uNr linux-2.6.29-clean/drivers/mmc/host/sdhci-pltfm.c linux-2.6.29/drivers/mmc/host/sdhci-pltfm.c
3962--- linux-2.6.29-clean/drivers/mmc/host/sdhci-pltfm.c 1969-12-31 16:00:00.000000000 -0800
3963+++ linux-2.6.29/drivers/mmc/host/sdhci-pltfm.c 2009-04-06 13:51:47.000000000 -0700
3964@@ -0,0 +1,262 @@
3965+/*
3966+ * sdhci-pltfm.c Support for SDHCI platform devices
3967+ * Copyright (c) 2009 Intel Corporation
3968+ *
3969+ * This program is free software; you can redistribute it and/or modify
3970+ * it under the terms of the GNU General Public License version 2 as
3971+ * published by the Free Software Foundation.
3972+ *
3973+ * This program is distributed in the hope that it will be useful,
3974+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3975+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3976+ * GNU General Public License for more details.
3977+ *
3978+ * You should have received a copy of the GNU General Public License
3979+ * along with this program; if not, write to the Free Software
3980+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3981+ */
3982+
3983+/* Supports:
3984+ * SDHCI platform devices
3985+ *
3986+ * Inspired by sdhci-pci.c, by Pierre Ossman
3987+ */
3988+
3989+#include <linux/delay.h>
3990+#include <linux/highmem.h>
3991+#include <linux/platform_device.h>
3992+
3993+#include <linux/mmc/host.h>
3994+
3995+#include <linux/io.h>
3996+
3997+#include "sdhci.h"
3998+
3999+
4000+#define MAX_SLOTS 8
4001+
4002+struct sdhci_pltfm_chip;
4003+
4004+struct sdhci_pltfm_slot {
4005+ struct sdhci_pltfm_chip *chip;
4006+ struct sdhci_host *host;
4007+
4008+ int pltfm_resource;
4009+};
4010+
4011+struct sdhci_pltfm_chip {
4012+ struct platform_device *pdev;
4013+
4014+ unsigned int quirks;
4015+
4016+ int num_slots; /* Slots on controller */
4017+ struct sdhci_pltfm_slot *slots[MAX_SLOTS]; /* Pointers to host slots */
4018+};
4019+
4020+
4021+/*****************************************************************************\
4022+ * *
4023+ * SDHCI core callbacks *
4024+ * *
4025+\*****************************************************************************/
4026+
4027+static struct sdhci_ops sdhci_pltfm_ops = {
4028+};
4029+
4030+/*****************************************************************************\
4031+ * *
4032+ * Device probing/removal *
4033+ * *
4034+\*****************************************************************************/
4035+
4036+
4037+static struct sdhci_pltfm_slot * __devinit sdhci_pltfm_probe_slot(
4038+ struct platform_device *pdev, struct sdhci_pltfm_chip *chip,
4039+ int resource)
4040+{
4041+ struct sdhci_pltfm_slot *slot;
4042+ struct sdhci_host *host;
4043+ struct resource *iomem;
4044+ int ret;
4045+
4046+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, resource);
4047+ if (!iomem)
4048+ return ERR_PTR(-ENODEV);
4049+
4050+ if (resource_size(iomem) != 0x100) {
4051+ dev_err(&pdev->dev, "Invalid iomem size. You may "
4052+ "experience problems.\n");
4053+ }
4054+
4055+ if (!pdev->dev.parent) {
4056+ dev_err(&pdev->dev, "The parent device be a PCI device\n");
4057+ return ERR_PTR(-ENODEV);
4058+ }
4059+
4060+ host = sdhci_alloc_host(pdev->dev.parent,
4061+ sizeof(struct sdhci_pltfm_slot));
4062+ if (IS_ERR(host))
4063+ return ERR_PTR(PTR_ERR(host));
4064+
4065+ slot = sdhci_priv(host);
4066+
4067+ slot->chip = chip;
4068+ slot->host = host;
4069+ slot->pltfm_resource = resource;
4070+
4071+ host->hw_name = "PLTFM";
4072+ host->ops = &sdhci_pltfm_ops;
4073+ host->quirks = chip->quirks;
4074+
4075+ host->irq = platform_get_irq(pdev, 0);
4076+
4077+ if (!request_mem_region(iomem->start, resource_size(iomem),
4078+ mmc_hostname(host->mmc))) {
4079+ dev_err(&pdev->dev, "cannot request region\n");
4080+ ret = -EBUSY;
4081+ goto free;
4082+ }
4083+
4084+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
4085+ if (!host->ioaddr) {
4086+ dev_err(&pdev->dev, "failed to remap registers\n");
4087+ goto release;
4088+ }
4089+
4090+ ret = sdhci_add_host(host);
4091+ if (ret)
4092+ goto unmap;
4093+
4094+ return slot;
4095+
4096+unmap:
4097+ iounmap(host->ioaddr);
4098+release:
4099+ release_mem_region(iomem->start, resource_size(iomem));
4100+free:
4101+ sdhci_free_host(host);
4102+
4103+ return ERR_PTR(ret);
4104+}
4105+
4106+static void sdhci_pltfm_remove_slot(struct sdhci_pltfm_slot *slot)
4107+{
4108+ int dead;
4109+ u32 scratch;
4110+ struct resource *iomem;
4111+
4112+ dead = 0;
4113+ scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
4114+ if (scratch == (u32)-1)
4115+ dead = 1;
4116+
4117+ sdhci_remove_host(slot->host, dead);
4118+
4119+ iounmap(slot->host->ioaddr);
4120+
4121+ iomem = platform_get_resource(slot->chip->pdev, IORESOURCE_MEM,
4122+ slot->pltfm_resource);
4123+ release_mem_region(iomem->start, resource_size(iomem));
4124+
4125+ sdhci_free_host(slot->host);
4126+}
4127+
4128+static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
4129+{
4130+ struct sdhci_pltfm_chip *chip;
4131+ struct sdhci_pltfm_slot *slot;
4132+ u8 slots;
4133+ int ret, i;
4134+
4135+ BUG_ON(pdev == NULL);
4136+
4137+ for (slots = 0; slots <= MAX_SLOTS; slots++)
4138+ if (!platform_get_resource(pdev, IORESOURCE_MEM, slots))
4139+ break;
4140+
4141+ BUG_ON(slots > MAX_SLOTS || slots == 0);
4142+
4143+ chip = kzalloc(sizeof(struct sdhci_pltfm_chip), GFP_KERNEL);
4144+ if (!chip) {
4145+ ret = -ENOMEM;
4146+ goto err;
4147+ }
4148+
4149+ chip->pdev = pdev;
4150+ chip->num_slots = slots;
4151+ platform_set_drvdata(pdev, chip);
4152+
4153+ for (i = 0; i < slots; i++) {
4154+ slot = sdhci_pltfm_probe_slot(pdev, chip, i);
4155+ if (IS_ERR(slot)) {
4156+ for (i--; i >= 0; i--)
4157+ sdhci_pltfm_remove_slot(chip->slots[i]);
4158+ ret = PTR_ERR(slot);
4159+ goto free;
4160+ }
4161+
4162+ chip->slots[i] = slot;
4163+ }
4164+
4165+ return 0;
4166+
4167+free:
4168+ platform_set_drvdata(pdev, NULL);
4169+ kfree(chip);
4170+
4171+err:
4172+ printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
4173+ return ret;
4174+}
4175+
4176+static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
4177+{
4178+ int i;
4179+ struct sdhci_pltfm_chip *chip;
4180+
4181+ chip = platform_get_drvdata(pdev);
4182+
4183+ if (chip) {
4184+ for (i = 0; i < chip->num_slots; i++)
4185+ sdhci_pltfm_remove_slot(chip->slots[i]);
4186+
4187+ platform_set_drvdata(pdev, NULL);
4188+ kfree(chip);
4189+ }
4190+
4191+ return 0;
4192+}
4193+
4194+static struct platform_driver sdhci_pltfm_driver = {
4195+ .driver = {
4196+ .name = "sdhci",
4197+ .owner = THIS_MODULE,
4198+ },
4199+ .probe = sdhci_pltfm_probe,
4200+ .remove = __devexit_p(sdhci_pltfm_remove),
4201+};
4202+
4203+/*****************************************************************************\
4204+ * *
4205+ * Driver init/exit *
4206+ * *
4207+\*****************************************************************************/
4208+
4209+static int __init sdhci_drv_init(void)
4210+{
4211+ return platform_driver_register(&sdhci_pltfm_driver);
4212+}
4213+
4214+static void __exit sdhci_drv_exit(void)
4215+{
4216+ platform_driver_unregister(&sdhci_pltfm_driver);
4217+}
4218+
4219+module_init(sdhci_drv_init);
4220+module_exit(sdhci_drv_exit);
4221+
4222+MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
4223+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
4224+MODULE_LICENSE("GPL v2");
4225+MODULE_ALIAS("platform:sdhci");
4226+
4227diff -uNr linux-2.6.29-clean/drivers/serial/Kconfig linux-2.6.29/drivers/serial/Kconfig
4228--- linux-2.6.29-clean/drivers/serial/Kconfig 2009-04-01 09:20:24.000000000 -0700
4229+++ linux-2.6.29/drivers/serial/Kconfig 2009-04-06 13:51:47.000000000 -0700
4230@@ -1412,4 +1412,11 @@
4231 default 19200 if (SERIAL_SPORT_BAUD_RATE_19200)
4232 default 9600 if (SERIAL_SPORT_BAUD_RATE_9600)
4233
4234+config SERIAL_TIMBERDALE
4235+ tristate "Support for timberdale UART"
4236+ depends on MFD_TIMBERDALE
4237+ select SERIAL_CORE
4238+ ---help---
4239+ Add support for UART controller on timberdale.
4240+
4241 endmenu
4242diff -uNr linux-2.6.29-clean/drivers/serial/Makefile linux-2.6.29/drivers/serial/Makefile
4243--- linux-2.6.29-clean/drivers/serial/Makefile 2009-04-01 09:20:24.000000000 -0700
4244+++ linux-2.6.29/drivers/serial/Makefile 2009-04-06 13:51:47.000000000 -0700
4245@@ -76,3 +76,4 @@
4246 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
4247 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
4248 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
4249+obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
4250diff -uNr linux-2.6.29-clean/drivers/serial/timbuart.c linux-2.6.29/drivers/serial/timbuart.c
4251--- linux-2.6.29-clean/drivers/serial/timbuart.c 1969-12-31 16:00:00.000000000 -0800
4252+++ linux-2.6.29/drivers/serial/timbuart.c 2009-04-06 13:51:47.000000000 -0700
4253@@ -0,0 +1,519 @@
4254+/*
4255+ * timbuart.c timberdale FPGA UART driver
4256+ * Copyright (c) 2009 Intel Corporation
4257+ *
4258+ * This program is free software; you can redistribute it and/or modify
4259+ * it under the terms of the GNU General Public License version 2 as
4260+ * published by the Free Software Foundation.
4261+ *
4262+ * This program is distributed in the hope that it will be useful,
4263+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4264+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4265+ * GNU General Public License for more details.
4266+ *
4267+ * You should have received a copy of the GNU General Public License
4268+ * along with this program; if not, write to the Free Software
4269+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4270+ */
4271+
4272+/* Supports:
4273+ * Timberdale FPGA UART
4274+ */
4275+
4276+#include <linux/pci.h>
4277+#include <linux/interrupt.h>
4278+#include <linux/serial_core.h>
4279+#include <linux/kernel.h>
4280+#include <linux/platform_device.h>
4281+#include <linux/ioport.h>
4282+
4283+#include "timbuart.h"
4284+
4285+struct timbuart_port {
4286+ struct uart_port port;
4287+ struct tasklet_struct tasklet;
4288+ int usedma;
4289+ u8 last_ier;
4290+ struct platform_device *dev;
4291+};
4292+
4293+static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800,
4294+ 921600, 1843200, 3250000};
4295+
4296+static void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier);
4297+
4298+static irqreturn_t timbuart_handleinterrupt(int irq, void *devid);
4299+
4300+static void timbuart_stop_rx(struct uart_port *port)
4301+{
4302+ /* spin lock held by upper layer, disable all RX interrupts */
4303+ u8 ier = ioread8(port->membase + TIMBUART_IER) & ~RXFLAGS;
4304+ iowrite8(ier, port->membase + TIMBUART_IER);
4305+}
4306+
4307+static void timbuart_stop_tx(struct uart_port *port)
4308+{
4309+ /* spinlock held by upper layer, disable TX interrupt */
4310+ u8 ier = ioread8(port->membase + TIMBUART_IER) & ~TXBAE;
4311+ iowrite8(ier, port->membase + TIMBUART_IER);
4312+}
4313+
4314+static void timbuart_start_tx(struct uart_port *port)
4315+{
4316+ struct timbuart_port *uart =
4317+ container_of(port, struct timbuart_port, port);
4318+
4319+ /* do not transfer anything here -> fire off the tasklet */
4320+ tasklet_schedule(&uart->tasklet);
4321+}
4322+
4323+static void timbuart_flush_buffer(struct uart_port *port)
4324+{
4325+ u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX;
4326+
4327+ iowrite8(ctl, port->membase + TIMBUART_CTRL);
4328+ iowrite8(TXBF, port->membase + TIMBUART_ISR);
4329+}
4330+
4331+static void timbuart_rx_chars(struct uart_port *port)
4332+{
4333+ struct tty_struct *tty = port->info->port.tty;
4334+
4335+ while (ioread8(port->membase + TIMBUART_ISR) & RXDP) {
4336+ u8 ch = ioread8(port->membase + TIMBUART_RXFIFO);
4337+ /* ack */
4338+ iowrite8(RXDP, port->membase + TIMBUART_ISR);
4339+ port->icount.rx++;
4340+ tty_insert_flip_char(tty, ch, TTY_NORMAL);
4341+ }
4342+
4343+ spin_unlock(&port->lock);
4344+ tty_flip_buffer_push(port->info->port.tty);
4345+ spin_lock(&port->lock);
4346+
4347+ dev_dbg(port->dev, "%s - total read %d bytes\n",
4348+ __func__, port->icount.rx);
4349+}
4350+
4351+static void timbuart_tx_chars(struct uart_port *port)
4352+{
4353+ struct circ_buf *xmit = &port->info->xmit;
4354+
4355+ while (!(ioread8(port->membase + TIMBUART_ISR) & TXBF) &&
4356+ !uart_circ_empty(xmit)) {
4357+ iowrite8(xmit->buf[xmit->tail],
4358+ port->membase + TIMBUART_TXFIFO);
4359+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
4360+ port->icount.tx++;
4361+ }
4362+
4363+ dev_dbg(port->dev,
4364+ "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n",
4365+ __func__,
4366+ port->icount.tx,
4367+ ioread8(port->membase + TIMBUART_CTRL),
4368+ port->mctrl & TIOCM_RTS,
4369+ ioread8(port->membase + TIMBUART_BAUDRATE));
4370+}
4371+
4372+static void timbuart_handle_tx_port(struct uart_port *port, u8 isr, u8 *ier)
4373+{
4374+ struct timbuart_port *uart =
4375+ container_of(port, struct timbuart_port, port);
4376+ struct circ_buf *xmit = &port->info->xmit;
4377+
4378+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
4379+ return;
4380+
4381+ if (port->x_char)
4382+ return;
4383+
4384+ if (isr & TXFLAGS) {
4385+ timbuart_tx_chars(port);
4386+ /* clear all TX interrupts */
4387+ iowrite8(TXFLAGS, port->membase + TIMBUART_ISR);
4388+
4389+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
4390+ uart_write_wakeup(port);
4391+ } else
4392+ /* Re-enable any tx interrupt */
4393+ *ier |= uart->last_ier & TXFLAGS;
4394+
4395+ /* enable interrupts if there are chars in the transmit buffer,
4396+ * Or if we delivered some bytes and want the almost empty interrupt
4397+ * we wake up the upper layer later when we got the interrupt
4398+ * to give it some time to go out...
4399+ */
4400+ if (!uart_circ_empty(xmit))
4401+ *ier |= TXBAE;
4402+
4403+ dev_dbg(port->dev, "%s - leaving\n", __func__);
4404+}
4405+
4406+void timbuart_handle_rx_port(struct uart_port *port, u8 isr, u8 *ier)
4407+{
4408+ if (isr & RXFLAGS) {
4409+ /* Some RX status is set */
4410+ if (isr & RXBF) {
4411+ u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
4412+ TIMBUART_CTRL_FLSHRX;
4413+ iowrite8(ctl, port->membase + TIMBUART_CTRL);
4414+ port->icount.overrun++;
4415+ } else if (isr & (RXDP))
4416+ timbuart_rx_chars(port);
4417+
4418+ /* ack all RX interrupts */
4419+ iowrite8(RXFLAGS, port->membase + TIMBUART_ISR);
4420+ }
4421+
4422+ /* always have the RX interrupts enabled */
4423+ *ier |= RXBAF | RXBF | RXTT;
4424+
4425+ dev_dbg(port->dev, "%s - leaving\n", __func__);
4426+}
4427+
4428+void timbuart_tasklet(unsigned long arg)
4429+{
4430+ struct timbuart_port *uart = (struct timbuart_port *)arg;
4431+ u8 isr, ier = 0;
4432+
4433+ spin_lock(&uart->port.lock);
4434+
4435+ isr = ioread8(uart->port.membase + TIMBUART_ISR);
4436+ dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr);
4437+
4438+ if (!uart->usedma)
4439+ timbuart_handle_tx_port(&uart->port, isr, &ier);
4440+
4441+ timbuart_mctrl_check(&uart->port, isr, &ier);
4442+
4443+ if (!uart->usedma)
4444+ timbuart_handle_rx_port(&uart->port, isr, &ier);
4445+
4446+ iowrite8(ier, uart->port.membase + TIMBUART_IER);
4447+
4448+ spin_unlock(&uart->port.lock);
4449+ dev_dbg(uart->port.dev, "%s leaving\n", __func__);
4450+}
4451+
4452+static unsigned int timbuart_tx_empty(struct uart_port *port)
4453+{
4454+ u8 isr = ioread8(port->membase + TIMBUART_ISR);
4455+
4456+ return (isr & TXBAE) ? TIOCSER_TEMT : 0;
4457+}
4458+
4459+static unsigned int timbuart_get_mctrl(struct uart_port *port)
4460+{
4461+ u8 cts = ioread8(port->membase + TIMBUART_CTRL);
4462+ dev_dbg(port->dev, "%s - cts %x\n", __func__, cts);
4463+
4464+ if (cts & TIMBUART_CTRL_CTS)
4465+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
4466+ else
4467+ return TIOCM_DSR | TIOCM_CAR;
4468+}
4469+
4470+static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
4471+{
4472+ dev_dbg(port->dev, "%s - %x\n", __func__, mctrl);
4473+
4474+ if (mctrl & TIOCM_RTS)
4475+ iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
4476+ else
4477+ iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
4478+}
4479+
4480+static void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier)
4481+{
4482+ unsigned int cts;
4483+
4484+ if (isr & CTS_DELTA) {
4485+ /* ack */
4486+ iowrite8(CTS_DELTA, port->membase + TIMBUART_ISR);
4487+ cts = timbuart_get_mctrl(port);
4488+ uart_handle_cts_change(port, cts & TIOCM_CTS);
4489+ wake_up_interruptible(&port->info->delta_msr_wait);
4490+ }
4491+
4492+ *ier |= CTS_DELTA;
4493+}
4494+
4495+static void timbuart_enable_ms(struct uart_port *port)
4496+{
4497+ /* N/A */
4498+}
4499+
4500+static void timbuart_break_ctl(struct uart_port *port, int ctl)
4501+{
4502+ /* N/A */
4503+}
4504+
4505+static int timbuart_startup(struct uart_port *port)
4506+{
4507+ struct timbuart_port *uart =
4508+ container_of(port, struct timbuart_port, port);
4509+
4510+ dev_dbg(port->dev, "%s\n", __func__);
4511+
4512+ iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL);
4513+ iowrite8(0xff, port->membase + TIMBUART_ISR);
4514+ /* Enable all but TX interrupts */
4515+ iowrite8(RXBAF | RXBF | RXTT | CTS_DELTA,
4516+ port->membase + TIMBUART_IER);
4517+
4518+ return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED,
4519+ "timb-uart", uart);
4520+}
4521+
4522+static void timbuart_shutdown(struct uart_port *port)
4523+{
4524+ struct timbuart_port *uart =
4525+ container_of(port, struct timbuart_port, port);
4526+ dev_dbg(port->dev, "%s\n", __func__);
4527+ free_irq(port->irq, uart);
4528+ iowrite8(0, port->membase + TIMBUART_IER);
4529+}
4530+
4531+static int get_bindex(int baud)
4532+{
4533+ int i;
4534+
4535+ for (i = 0; i < ARRAY_SIZE(baudrates); i++)
4536+ if (baud == baudrates[i])
4537+ return i;
4538+
4539+ return -1;
4540+}
4541+
4542+static void timbuart_set_termios(struct uart_port *port,
4543+ struct ktermios *termios,
4544+ struct ktermios *old)
4545+{
4546+ unsigned int baud;
4547+ short bindex;
4548+ unsigned long flags;
4549+
4550+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
4551+ bindex = get_bindex(baud);
4552+ dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex);
4553+
4554+ if (bindex < 0) {
4555+ printk(KERN_ALERT "timbuart: Unsupported baud rate\n");
4556+ } else {
4557+ spin_lock_irqsave(&port->lock, flags);
4558+ iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE);
4559+ uart_update_timeout(port, termios->c_cflag, baud);
4560+ spin_unlock_irqrestore(&port->lock, flags);
4561+ }
4562+}
4563+
4564+static const char *timbuart_type(struct uart_port *port)
4565+{
4566+ return port->type == PORT_UNKNOWN ? "timbuart" : NULL;
4567+}
4568+
4569+/* We do not request/release mappings of the registers here,
4570+ * currently it's done in the proble function.
4571+ */
4572+static void timbuart_release_port(struct uart_port *port)
4573+{
4574+ struct platform_device *pdev = to_platform_device(port->dev);
4575+ int size =
4576+ resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
4577+
4578+ if (port->flags & UPF_IOREMAP) {
4579+ iounmap(port->membase);
4580+ port->membase = NULL;
4581+ }
4582+
4583+ release_mem_region(port->mapbase, size);
4584+}
4585+
4586+static int timbuart_request_port(struct uart_port *port)
4587+{
4588+ struct platform_device *pdev = to_platform_device(port->dev);
4589+ int size =
4590+ resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
4591+
4592+ if (!request_mem_region(port->mapbase, size, "timb-uart"))
4593+ return -EBUSY;
4594+
4595+ if (port->flags & UPF_IOREMAP) {
4596+ port->membase = ioremap(port->mapbase, size);
4597+ if (port->membase == NULL) {
4598+ release_mem_region(port->mapbase, size);
4599+ return -ENOMEM;
4600+ }
4601+ }
4602+
4603+ return 0;
4604+}
4605+
4606+static irqreturn_t timbuart_handleinterrupt(int irq, void *devid)
4607+{
4608+ struct timbuart_port *uart = (struct timbuart_port *)devid;
4609+
4610+ uart->last_ier = ioread8(uart->port.membase + TIMBUART_IER);
4611+
4612+ /* disable interrupts, let the tasklet enable them again if needed */
4613+ iowrite8(0, uart->port.membase + TIMBUART_IER);
4614+
4615+ /* fire off bottom half */
4616+ tasklet_schedule(&uart->tasklet);
4617+
4618+ return IRQ_HANDLED;
4619+}
4620+
4621+/*
4622+ * Configure/autoconfigure the port.
4623+ */
4624+static void timbuart_config_port(struct uart_port *port, int flags)
4625+{
4626+ if (flags & UART_CONFIG_TYPE) {
4627+ port->type = PORT_TIMBUART;
4628+ timbuart_request_port(port);
4629+ }
4630+}
4631+
4632+static int timbuart_verify_port(struct uart_port *port,
4633+ struct serial_struct *ser)
4634+{
4635+ /* we don't want the core code to modify any port params */
4636+ return -EINVAL;
4637+}
4638+
4639+static struct uart_ops timbuart_ops = {
4640+ .tx_empty = timbuart_tx_empty,
4641+ .set_mctrl = timbuart_set_mctrl,
4642+ .get_mctrl = timbuart_get_mctrl,
4643+ .stop_tx = timbuart_stop_tx,
4644+ .start_tx = timbuart_start_tx,
4645+ .flush_buffer = timbuart_flush_buffer,
4646+ .stop_rx = timbuart_stop_rx,
4647+ .enable_ms = timbuart_enable_ms,
4648+ .break_ctl = timbuart_break_ctl,
4649+ .startup = timbuart_startup,
4650+ .shutdown = timbuart_shutdown,
4651+ .set_termios = timbuart_set_termios,
4652+ .type = timbuart_type,
4653+ .release_port = timbuart_release_port,
4654+ .request_port = timbuart_request_port,
4655+ .config_port = timbuart_config_port,
4656+ .verify_port = timbuart_verify_port
4657+};
4658+
4659+static struct uart_driver timbuart_driver = {
4660+ .owner = THIS_MODULE,
4661+ .driver_name = "timberdale_uart",
4662+ .dev_name = "ttyTU",
4663+ .major = TIMBUART_MAJOR,
4664+ .minor = TIMBUART_MINOR,
4665+ .nr = 1
4666+};
4667+
4668+static int timbuart_probe(struct platform_device *dev)
4669+{
4670+ int err;
4671+ struct timbuart_port *uart;
4672+ struct resource *iomem;
4673+
4674+ dev_dbg(&dev->dev, "%s\n", __func__);
4675+
4676+ uart = kzalloc(sizeof(*uart), GFP_KERNEL);
4677+ if (!uart) {
4678+ err = -EINVAL;
4679+ goto err_mem;
4680+ }
4681+
4682+ uart->usedma = 0;
4683+
4684+ uart->port.uartclk = 3250000 * 16;
4685+ uart->port.fifosize = TIMBUART_FIFO_SIZE;
4686+ uart->port.regshift = 2;
4687+ uart->port.iotype = UPIO_MEM;
4688+ uart->port.ops = &timbuart_ops;
4689+ uart->port.irq = 0;
4690+ uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
4691+ uart->port.line = 0;
4692+ uart->port.dev = &dev->dev;
4693+
4694+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
4695+ if (!iomem) {
4696+ err = -ENOMEM;
4697+ goto err_register;
4698+ }
4699+ uart->port.mapbase = iomem->start;
4700+ uart->port.membase = NULL;
4701+
4702+ uart->port.irq = platform_get_irq(dev, 0);
4703+ if (uart->port.irq < 0) {
4704+ err = -EINVAL;
4705+ goto err_register;
4706+ }
4707+
4708+ tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart);
4709+
4710+ err = uart_register_driver(&timbuart_driver);
4711+ if (err)
4712+ goto err_register;
4713+
4714+ err = uart_add_one_port(&timbuart_driver, &uart->port);
4715+ if (err)
4716+ goto err_add_port;
4717+
4718+ platform_set_drvdata(dev, uart);
4719+
4720+ return 0;
4721+
4722+err_add_port:
4723+ uart_unregister_driver(&timbuart_driver);
4724+err_register:
4725+ kfree(uart);
4726+err_mem:
4727+ printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n",
4728+ err);
4729+
4730+ return err;
4731+}
4732+
4733+static int timbuart_remove(struct platform_device *dev)
4734+{
4735+ struct timbuart_port *uart = platform_get_drvdata(dev);
4736+
4737+ tasklet_kill(&uart->tasklet);
4738+ uart_remove_one_port(&timbuart_driver, &uart->port);
4739+ uart_unregister_driver(&timbuart_driver);
4740+ kfree(uart);
4741+
4742+ return 0;
4743+}
4744+
4745+static struct platform_driver timbuart_platform_driver = {
4746+ .driver = {
4747+ .name = "timb-uart",
4748+ .owner = THIS_MODULE,
4749+ },
4750+ .probe = timbuart_probe,
4751+ .remove = timbuart_remove,
4752+};
4753+
4754+/*--------------------------------------------------------------------------*/
4755+
4756+static int __init timbuart_init(void)
4757+{
4758+ return platform_driver_register(&timbuart_platform_driver);
4759+}
4760+
4761+static void __exit timbuart_exit(void)
4762+{
4763+ platform_driver_unregister(&timbuart_platform_driver);
4764+}
4765+
4766+module_init(timbuart_init);
4767+module_exit(timbuart_exit);
4768+
4769+MODULE_DESCRIPTION("Timberdale UART driver");
4770+MODULE_LICENSE("GPL v2");
4771+MODULE_ALIAS("platform:timb-uart");
4772+
4773diff -uNr linux-2.6.29-clean/drivers/serial/timbuart.h linux-2.6.29/drivers/serial/timbuart.h
4774--- linux-2.6.29-clean/drivers/serial/timbuart.h 1969-12-31 16:00:00.000000000 -0800
4775+++ linux-2.6.29/drivers/serial/timbuart.h 2009-04-06 13:51:47.000000000 -0700
4776@@ -0,0 +1,57 @@
4777+/*
4778+ * timbuart.c timberdale FPGA GPIO driver
4779+ * Copyright (c) 2009 Intel Corporation
4780+ *
4781+ * This program is free software; you can redistribute it and/or modify
4782+ * it under the terms of the GNU General Public License version 2 as
4783+ * published by the Free Software Foundation.
4784+ *
4785+ * This program is distributed in the hope that it will be useful,
4786+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4787+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4788+ * GNU General Public License for more details.
4789+ *
4790+ * You should have received a copy of the GNU General Public License
4791+ * along with this program; if not, write to the Free Software
4792+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4793+ */
4794+
4795+/* Supports:
4796+ * Timberdale FPGA UART
4797+ */
4798+
4799+#ifndef _TIMBUART_H
4800+#define _TIMBUART_H
4801+
4802+#define TIMBUART_FIFO_SIZE 2048
4803+
4804+#define TIMBUART_RXFIFO 0x08
4805+#define TIMBUART_TXFIFO 0x0c
4806+#define TIMBUART_IER 0x10
4807+#define TIMBUART_IPR 0x14
4808+#define TIMBUART_ISR 0x18
4809+#define TIMBUART_CTRL 0x1c
4810+#define TIMBUART_BAUDRATE 0x20
4811+
4812+#define TIMBUART_CTRL_RTS 0x01
4813+#define TIMBUART_CTRL_CTS 0x02
4814+#define TIMBUART_CTRL_FLSHTX 0x40
4815+#define TIMBUART_CTRL_FLSHRX 0x80
4816+
4817+#define TXBF 0x01
4818+#define TXBAE 0x02
4819+#define CTS_DELTA 0x04
4820+#define RXDP 0x08
4821+#define RXBAF 0x10
4822+#define RXBF 0x20
4823+#define RXTT 0x40
4824+#define RXBNAE 0x80
4825+
4826+#define RXFLAGS (RXDP | RXBAF | RXBF | RXTT | RXBNAE)
4827+#define TXFLAGS (TXBF | TXBAE)
4828+
4829+#define TIMBUART_MAJOR 204
4830+#define TIMBUART_MINOR 192
4831+
4832+#endif /* _TIMBUART_H */
4833+
4834diff -uNr linux-2.6.29-clean/drivers/spi/Kconfig linux-2.6.29/drivers/spi/Kconfig
4835--- linux-2.6.29-clean/drivers/spi/Kconfig 2009-04-01 09:20:25.000000000 -0700
4836+++ linux-2.6.29/drivers/spi/Kconfig 2009-04-06 13:51:47.000000000 -0700
4837@@ -211,8 +211,8 @@
4838 SPI driver for Toshiba TXx9 MIPS SoCs
4839
4840 config SPI_XILINX
4841- tristate "Xilinx SPI controller"
4842- depends on XILINX_VIRTEX && EXPERIMENTAL
4843+ tristate "Xilinx SPI controller common module"
4844+ depends on EXPERIMENTAL
4845 select SPI_BITBANG
4846 help
4847 This exposes the SPI controller IP from the Xilinx EDK.
4848@@ -220,6 +220,25 @@
4849 See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
4850 Product Specification document (DS464) for hardware details.
4851
4852+config SPI_XILINX_OF
4853+ tristate "Xilinx SPI controller OF device"
4854+ depends on SPI_XILINX && XILINX_VIRTEX
4855+ help
4856+ This exposes the SPI controller IP from the Xilinx EDK.
4857+
4858+ See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
4859+ Product Specification document (DS464) for hardware details.
4860+
4861+config SPI_XILINX_PLTFM
4862+ tristate "Xilinx SPI controller platform device"
4863+ depends on SPI_XILINX
4864+ help
4865+ This exposes the SPI controller IP from the Xilinx EDK.
4866+
4867+ See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
4868+ Product Specification document (DS464) for hardware details.
4869+
4870+
4871 #
4872 # Add new SPI master controllers in alphabetical order above this line
4873 #
4874diff -uNr linux-2.6.29-clean/drivers/spi/Makefile linux-2.6.29/drivers/spi/Makefile
4875--- linux-2.6.29-clean/drivers/spi/Makefile 2009-04-01 09:20:25.000000000 -0700
4876+++ linux-2.6.29/drivers/spi/Makefile 2009-04-06 13:51:47.000000000 -0700
4877@@ -29,6 +29,8 @@
4878 obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
4879 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
4880 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
4881+obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o
4882+obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o
4883 obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
4884 # ... add above this line ...
4885
4886diff -uNr linux-2.6.29-clean/drivers/spi/xilinx_spi.c linux-2.6.29/drivers/spi/xilinx_spi.c
4887--- linux-2.6.29-clean/drivers/spi/xilinx_spi.c 2009-04-01 09:20:25.000000000 -0700
4888+++ linux-2.6.29/drivers/spi/xilinx_spi.c 2009-04-06 13:51:47.000000000 -0700
4889@@ -14,22 +14,28 @@
4890 #include <linux/module.h>
4891 #include <linux/init.h>
4892 #include <linux/interrupt.h>
4893-#include <linux/platform_device.h>
4894-
4895-#include <linux/of_platform.h>
4896-#include <linux/of_device.h>
4897-#include <linux/of_spi.h>
4898
4899 #include <linux/spi/spi.h>
4900 #include <linux/spi/spi_bitbang.h>
4901 #include <linux/io.h>
4902
4903-#define XILINX_SPI_NAME "xilinx_spi"
4904+#include "xilinx_spi.h"
4905+
4906+#ifndef CONFIG_PPC
4907+#define in_8(addr) ioread8(addr)
4908+#define in_be16(addr) ioread16(addr)
4909+#define in_be32(addr) ioread32(addr)
4910+
4911+#define out_8(addr, b) iowrite8(b, addr)
4912+#define out_be16(addr, w) iowrite16(w, addr)
4913+#define out_be32(addr, l) iowrite32(l, addr)
4914+#endif
4915+
4916
4917 /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
4918 * Product Specification", DS464
4919 */
4920-#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */
4921+#define XSPI_CR_OFFSET_DEF 0x62 /* 16-bit Control Register */
4922
4923 #define XSPI_CR_ENABLE 0x02
4924 #define XSPI_CR_MASTER_MODE 0x04
4925@@ -41,7 +47,7 @@
4926 #define XSPI_CR_MANUAL_SSELECT 0x80
4927 #define XSPI_CR_TRANS_INHIBIT 0x100
4928
4929-#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */
4930+#define XSPI_SR_OFFSET_DEF 0x67 /* 8-bit Status Register */
4931
4932 #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
4933 #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
4934@@ -49,10 +55,10 @@
4935 #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
4936 #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
4937
4938-#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */
4939-#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */
4940+#define XSPI_TXD_OFFSET_DEF 0x6b /* 8-bit Data Transmit Register */
4941+#define XSPI_RXD_OFFSET_DEF 0x6f /* 8-bit Data Receive Register */
4942
4943-#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
4944+#define XSPI_SSR_OFFSET_DEF 0x70 /* 32-bit Slave Select Register */
4945
4946 /* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
4947 * IPIF registers are 32 bit
4948@@ -74,24 +80,10 @@
4949 #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
4950 #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
4951
4952-struct xilinx_spi {
4953- /* bitbang has to be first */
4954- struct spi_bitbang bitbang;
4955- struct completion done;
4956-
4957- void __iomem *regs; /* virt. address of the control registers */
4958-
4959- u32 irq;
4960-
4961- u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
4962-
4963- u8 *rx_ptr; /* pointer in the Tx buffer */
4964- const u8 *tx_ptr; /* pointer in the Rx buffer */
4965- int remaining_bytes; /* the number of bytes left to transfer */
4966-};
4967
4968-static void xspi_init_hw(void __iomem *regs_base)
4969+void xspi_init_hw(struct xilinx_spi *xspi)
4970 {
4971+ void __iomem *regs_base = xspi->regs;
4972 /* Reset the SPI device */
4973 out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
4974 XIPIF_V123B_RESET_MASK);
4975@@ -101,30 +93,31 @@
4976 out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
4977 XIPIF_V123B_GINTR_ENABLE);
4978 /* Deselect the slave on the SPI bus */
4979- out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
4980+ out_be32(regs_base + xspi->ssr_offset, 0xffff);
4981 /* Disable the transmitter, enable Manual Slave Select Assertion,
4982 * put SPI controller into master mode, and enable it */
4983- out_be16(regs_base + XSPI_CR_OFFSET,
4984+ out_be16(regs_base + xspi->cr_offset,
4985 XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
4986 | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
4987 }
4988+EXPORT_SYMBOL(xspi_init_hw);
4989
4990-static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
4991+void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
4992 {
4993 struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
4994
4995 if (is_on == BITBANG_CS_INACTIVE) {
4996 /* Deselect the slave on the SPI bus */
4997- out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
4998+ out_be32(xspi->regs + xspi->ssr_offset, 0xffff);
4999 } else if (is_on == BITBANG_CS_ACTIVE) {
5000 /* Set the SPI clock phase and polarity */
5001- u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET)
5002+ u16 cr = in_be16(xspi->regs + xspi->cr_offset)
5003 & ~XSPI_CR_MODE_MASK;
5004 if (spi->mode & SPI_CPHA)
5005 cr |= XSPI_CR_CPHA;
5006 if (spi->mode & SPI_CPOL)
5007 cr |= XSPI_CR_CPOL;
5008- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
5009+ out_be16(xspi->regs + xspi->cr_offset, cr);
5010
5011 /* We do not check spi->max_speed_hz here as the SPI clock
5012 * frequency is not software programmable (the IP block design
5013@@ -132,10 +125,11 @@
5014 */
5015
5016 /* Activate the chip select */
5017- out_be32(xspi->regs + XSPI_SSR_OFFSET,
5018+ out_be32(xspi->regs + xspi->ssr_offset,
5019 ~(0x0001 << spi->chip_select));
5020 }
5021 }
5022+EXPORT_SYMBOL(xilinx_spi_chipselect);
5023
5024 /* spi_bitbang requires custom setup_transfer() to be defined if there is a
5025 * custom txrx_bufs(). We have nothing to setup here as the SPI IP block
5026@@ -143,8 +137,7 @@
5027 * Check for 8 bits per word. Chip select delay calculations could be
5028 * added here as soon as bitbang_work() can be made aware of the delay value.
5029 */
5030-static int xilinx_spi_setup_transfer(struct spi_device *spi,
5031- struct spi_transfer *t)
5032+int xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
5033 {
5034 u8 bits_per_word;
5035
5036@@ -157,11 +150,12 @@
5037
5038 return 0;
5039 }
5040+EXPORT_SYMBOL(xilinx_spi_setup_transfer);
5041
5042 /* the spi->mode bits understood by this driver: */
5043 #define MODEBITS (SPI_CPOL | SPI_CPHA)
5044
5045-static int xilinx_spi_setup(struct spi_device *spi)
5046+int xilinx_spi_setup(struct spi_device *spi)
5047 {
5048 struct spi_bitbang *bitbang;
5049 struct xilinx_spi *xspi;
5050@@ -188,25 +182,25 @@
5051
5052 return 0;
5053 }
5054+EXPORT_SYMBOL(xilinx_spi_setup);
5055
5056 static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
5057 {
5058 u8 sr;
5059
5060 /* Fill the Tx FIFO with as many bytes as possible */
5061- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
5062+ sr = in_8(xspi->regs + xspi->sr_offset);
5063 while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
5064- if (xspi->tx_ptr) {
5065- out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
5066- } else {
5067- out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
5068- }
5069+ if (xspi->tx_ptr)
5070+ out_8(xspi->regs + xspi->txd_offset, *xspi->tx_ptr++);
5071+ else
5072+ out_8(xspi->regs + xspi->txd_offset, 0);
5073 xspi->remaining_bytes--;
5074- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
5075+ sr = in_8(xspi->regs + xspi->sr_offset);
5076 }
5077 }
5078
5079-static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
5080+int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
5081 {
5082 struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
5083 u32 ipif_ier;
5084@@ -229,8 +223,8 @@
5085 ipif_ier | XSPI_INTR_TX_EMPTY);
5086
5087 /* Start the transfer by not inhibiting the transmitter any longer */
5088- cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT;
5089- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
5090+ cr = in_be16(xspi->regs + xspi->cr_offset) & ~XSPI_CR_TRANS_INHIBIT;
5091+ out_be16(xspi->regs + xspi->cr_offset, cr);
5092
5093 wait_for_completion(&xspi->done);
5094
5095@@ -239,14 +233,14 @@
5096
5097 return t->len - xspi->remaining_bytes;
5098 }
5099-
5100+EXPORT_SYMBOL(xilinx_spi_txrx_bufs);
5101
5102 /* This driver supports single master mode only. Hence Tx FIFO Empty
5103 * is the only interrupt we care about.
5104 * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
5105 * Fault are not to happen.
5106 */
5107-static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
5108+irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
5109 {
5110 struct xilinx_spi *xspi = dev_id;
5111 u32 ipif_isr;
5112@@ -264,20 +258,19 @@
5113 * transmitter while the Isr refills the transmit register/FIFO,
5114 * or make sure it is stopped if we're done.
5115 */
5116- cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
5117- out_be16(xspi->regs + XSPI_CR_OFFSET,
5118+ cr = in_be16(xspi->regs + xspi->cr_offset);
5119+ out_be16(xspi->regs + xspi->cr_offset,
5120 cr | XSPI_CR_TRANS_INHIBIT);
5121
5122 /* Read out all the data from the Rx FIFO */
5123- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
5124+ sr = in_8(xspi->regs + xspi->sr_offset);
5125 while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
5126 u8 data;
5127
5128- data = in_8(xspi->regs + XSPI_RXD_OFFSET);
5129- if (xspi->rx_ptr) {
5130+ data = in_8(xspi->regs + xspi->rxd_offset);
5131+ if (xspi->rx_ptr)
5132 *xspi->rx_ptr++ = data;
5133- }
5134- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
5135+ sr = in_8(xspi->regs + xspi->sr_offset);
5136 }
5137
5138 /* See if there is more data to send */
5139@@ -286,7 +279,7 @@
5140 /* Start the transfer by not inhibiting the
5141 * transmitter any longer
5142 */
5143- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
5144+ out_be16(xspi->regs + xspi->cr_offset, cr);
5145 } else {
5146 /* No more data to send.
5147 * Indicate the transfer is completed.
5148@@ -297,167 +290,18 @@
5149
5150 return IRQ_HANDLED;
5151 }
5152+EXPORT_SYMBOL(xilinx_spi_irq);
5153
5154-static int __init xilinx_spi_of_probe(struct of_device *ofdev,
5155- const struct of_device_id *match)
5156-{
5157- struct spi_master *master;
5158- struct xilinx_spi *xspi;
5159- struct resource r_irq_struct;
5160- struct resource r_mem_struct;
5161-
5162- struct resource *r_irq = &r_irq_struct;
5163- struct resource *r_mem = &r_mem_struct;
5164- int rc = 0;
5165- const u32 *prop;
5166- int len;
5167-
5168- /* Get resources(memory, IRQ) associated with the device */
5169- master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
5170-
5171- if (master == NULL) {
5172- return -ENOMEM;
5173- }
5174-
5175- dev_set_drvdata(&ofdev->dev, master);
5176-
5177- rc = of_address_to_resource(ofdev->node, 0, r_mem);
5178- if (rc) {
5179- dev_warn(&ofdev->dev, "invalid address\n");
5180- goto put_master;
5181- }
5182-
5183- rc = of_irq_to_resource(ofdev->node, 0, r_irq);
5184- if (rc == NO_IRQ) {
5185- dev_warn(&ofdev->dev, "no IRQ found\n");
5186- goto put_master;
5187- }
5188-
5189- xspi = spi_master_get_devdata(master);
5190- xspi->bitbang.master = spi_master_get(master);
5191- xspi->bitbang.chipselect = xilinx_spi_chipselect;
5192- xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
5193- xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
5194- xspi->bitbang.master->setup = xilinx_spi_setup;
5195- init_completion(&xspi->done);
5196-
5197- xspi->irq = r_irq->start;
5198-
5199- if (!request_mem_region(r_mem->start,
5200- r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
5201- rc = -ENXIO;
5202- dev_warn(&ofdev->dev, "memory request failure\n");
5203- goto put_master;
5204- }
5205-
5206- xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1);
5207- if (xspi->regs == NULL) {
5208- rc = -ENOMEM;
5209- dev_warn(&ofdev->dev, "ioremap failure\n");
5210- goto put_master;
5211- }
5212- xspi->irq = r_irq->start;
5213-
5214- /* dynamic bus assignment */
5215- master->bus_num = -1;
5216-
5217- /* number of slave select bits is required */
5218- prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
5219- if (!prop || len < sizeof(*prop)) {
5220- dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
5221- goto put_master;
5222- }
5223- master->num_chipselect = *prop;
5224-
5225- /* SPI controller initializations */
5226- xspi_init_hw(xspi->regs);
5227-
5228- /* Register for SPI Interrupt */
5229- rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
5230- if (rc != 0) {
5231- dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
5232- goto unmap_io;
5233- }
5234-
5235- rc = spi_bitbang_start(&xspi->bitbang);
5236- if (rc != 0) {
5237- dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
5238- goto free_irq;
5239- }
5240-
5241- dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
5242- (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
5243-
5244- /* Add any subnodes on the SPI bus */
5245- of_register_spi_devices(master, ofdev->node);
5246-
5247- return rc;
5248-
5249-free_irq:
5250- free_irq(xspi->irq, xspi);
5251-unmap_io:
5252- iounmap(xspi->regs);
5253-put_master:
5254- spi_master_put(master);
5255- return rc;
5256-}
5257-
5258-static int __devexit xilinx_spi_remove(struct of_device *ofdev)
5259+void xilinx_spi_set_default_reg_offsets(struct xilinx_spi *xspi)
5260 {
5261- struct xilinx_spi *xspi;
5262- struct spi_master *master;
5263-
5264- master = platform_get_drvdata(ofdev);
5265- xspi = spi_master_get_devdata(master);
5266-
5267- spi_bitbang_stop(&xspi->bitbang);
5268- free_irq(xspi->irq, xspi);
5269- iounmap(xspi->regs);
5270- dev_set_drvdata(&ofdev->dev, 0);
5271- spi_master_put(xspi->bitbang.master);
5272-
5273- return 0;
5274-}
5275-
5276-/* work with hotplug and coldplug */
5277-MODULE_ALIAS("platform:" XILINX_SPI_NAME);
5278-
5279-static int __exit xilinx_spi_of_remove(struct of_device *op)
5280-{
5281- return xilinx_spi_remove(op);
5282+ xspi->cr_offset = XSPI_CR_OFFSET_DEF;
5283+ xspi->sr_offset = XSPI_SR_OFFSET_DEF;
5284+ xspi->txd_offset = XSPI_TXD_OFFSET_DEF;
5285+ xspi->rxd_offset = XSPI_RXD_OFFSET_DEF;
5286+ xspi->ssr_offset = XSPI_SSR_OFFSET_DEF;
5287 }
5288+EXPORT_SYMBOL(xilinx_spi_set_default_reg_offsets);
5289
5290-static struct of_device_id xilinx_spi_of_match[] = {
5291- { .compatible = "xlnx,xps-spi-2.00.a", },
5292- { .compatible = "xlnx,xps-spi-2.00.b", },
5293- {}
5294-};
5295-
5296-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
5297-
5298-static struct of_platform_driver xilinx_spi_of_driver = {
5299- .owner = THIS_MODULE,
5300- .name = "xilinx-xps-spi",
5301- .match_table = xilinx_spi_of_match,
5302- .probe = xilinx_spi_of_probe,
5303- .remove = __exit_p(xilinx_spi_of_remove),
5304- .driver = {
5305- .name = "xilinx-xps-spi",
5306- .owner = THIS_MODULE,
5307- },
5308-};
5309-
5310-static int __init xilinx_spi_init(void)
5311-{
5312- return of_register_platform_driver(&xilinx_spi_of_driver);
5313-}
5314-module_init(xilinx_spi_init);
5315-
5316-static void __exit xilinx_spi_exit(void)
5317-{
5318- of_unregister_platform_driver(&xilinx_spi_of_driver);
5319-}
5320-module_exit(xilinx_spi_exit);
5321 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
5322 MODULE_DESCRIPTION("Xilinx SPI driver");
5323 MODULE_LICENSE("GPL");
5324diff -uNr linux-2.6.29-clean/drivers/spi/xilinx_spi.h linux-2.6.29/drivers/spi/xilinx_spi.h
5325--- linux-2.6.29-clean/drivers/spi/xilinx_spi.h 1969-12-31 16:00:00.000000000 -0800
5326+++ linux-2.6.29/drivers/spi/xilinx_spi.h 2009-04-06 13:51:47.000000000 -0700
5327@@ -0,0 +1,52 @@
5328+/*
5329+ * xilinx_spi.c
5330+ *
5331+ * Xilinx SPI controller driver (master mode only)
5332+ *
5333+ * Author: MontaVista Software, Inc.
5334+ * source@mvista.com
5335+ *
5336+ * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the
5337+ * terms of the GNU General Public License version 2. This program is licensed
5338+ * "as is" without any warranty of any kind, whether express or implied.
5339+ */
5340+
5341+#ifndef _XILINX_SPI_H_
5342+#define _XILINX_SPI_H_ 1
5343+
5344+#include <linux/spi/spi.h>
5345+#include <linux/spi/spi_bitbang.h>
5346+
5347+#define XILINX_SPI_NAME "xilinx_spi"
5348+
5349+
5350+struct xilinx_spi {
5351+ /* bitbang has to be first */
5352+ struct spi_bitbang bitbang;
5353+ struct completion done;
5354+
5355+ void __iomem *regs; /* virt. address of the control registers */
5356+
5357+ u32 irq;
5358+
5359+ u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
5360+
5361+ u8 *rx_ptr; /* pointer in the Tx buffer */
5362+ const u8 *tx_ptr; /* pointer in the Rx buffer */
5363+ int remaining_bytes; /* the number of bytes left to transfer */
5364+ /* offset to the XSPI regs, these might vary... */
5365+ u8 cr_offset;
5366+ u8 sr_offset;
5367+ u8 txd_offset;
5368+ u8 rxd_offset;
5369+ u8 ssr_offset;
5370+};
5371+
5372+void xspi_init_hw(struct xilinx_spi *xspi);
5373+void xilinx_spi_set_default_reg_offsets(struct xilinx_spi *xspi);
5374+void xilinx_spi_chipselect(struct spi_device *spi, int is_on);
5375+int xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t);
5376+int xilinx_spi_setup(struct spi_device *spi);
5377+int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t);
5378+irqreturn_t xilinx_spi_irq(int irq, void *dev_id);
5379+#endif
5380diff -uNr linux-2.6.29-clean/drivers/spi/xilinx_spi_of.c linux-2.6.29/drivers/spi/xilinx_spi_of.c
5381--- linux-2.6.29-clean/drivers/spi/xilinx_spi_of.c 1969-12-31 16:00:00.000000000 -0800
5382+++ linux-2.6.29/drivers/spi/xilinx_spi_of.c 2009-04-06 13:51:47.000000000 -0700
5383@@ -0,0 +1,193 @@
5384+/*
5385+ * xilinx_spi.c
5386+ *
5387+ * Xilinx SPI controller driver (master mode only)
5388+ *
5389+ * Author: MontaVista Software, Inc.
5390+ * source@mvista.com
5391+ *
5392+ * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the
5393+ * terms of the GNU General Public License version 2. This program is licensed
5394+ * "as is" without any warranty of any kind, whether express or implied.
5395+ */
5396+
5397+#include <linux/module.h>
5398+#include <linux/init.h>
5399+#include <linux/interrupt.h>
5400+#include <linux/io.h>
5401+#include <linux/platform_device.h>
5402+
5403+#include <linux/of_platform.h>
5404+#include <linux/of_device.h>
5405+#include <linux/of_spi.h>
5406+
5407+#include <linux/spi/spi.h>
5408+#include <linux/spi/spi_bitbang.h>
5409+
5410+#include "xilinx_spi.h"
5411+
5412+
5413+static int __init xilinx_spi_of_probe(struct of_device *ofdev,
5414+ const struct of_device_id *match)
5415+{
5416+ struct spi_master *master;
5417+ struct xilinx_spi *xspi;
5418+ struct resource r_irq_struct;
5419+ struct resource r_mem_struct;
5420+
5421+ struct resource *r_irq = &r_irq_struct;
5422+ struct resource *r_mem = &r_mem_struct;
5423+ int rc = 0;
5424+ const u32 *prop;
5425+ int len;
5426+
5427+ /* Get resources(memory, IRQ) associated with the device */
5428+ master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
5429+
5430+ if (master == NULL)
5431+ return -ENOMEM;
5432+
5433+ dev_set_drvdata(&ofdev->dev, master);
5434+
5435+ rc = of_address_to_resource(ofdev->node, 0, r_mem);
5436+ if (rc) {
5437+ dev_warn(&ofdev->dev, "invalid address\n");
5438+ goto put_master;
5439+ }
5440+
5441+ rc = of_irq_to_resource(ofdev->node, 0, r_irq);
5442+ if (rc == NO_IRQ) {
5443+ dev_warn(&ofdev->dev, "no IRQ found\n");
5444+ goto put_master;
5445+ }
5446+
5447+ xspi = spi_master_get_devdata(master);
5448+ xspi->bitbang.master = spi_master_get(master);
5449+ xspi->bitbang.chipselect = xilinx_spi_chipselect;
5450+ xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
5451+ xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
5452+ xspi->bitbang.master->setup = xilinx_spi_setup;
5453+ init_completion(&xspi->done);
5454+
5455+ xspi->irq = r_irq->start;
5456+
5457+ if (!request_mem_region(r_mem->start,
5458+ r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
5459+ rc = -ENXIO;
5460+ dev_warn(&ofdev->dev, "memory request failure\n");
5461+ goto put_master;
5462+ }
5463+
5464+ xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1);
5465+ if (xspi->regs == NULL) {
5466+ rc = -ENOMEM;
5467+ dev_warn(&ofdev->dev, "ioremap failure\n");
5468+ goto put_master;
5469+ }
5470+ xspi->irq = r_irq->start;
5471+
5472+ /* dynamic bus assignment */
5473+ master->bus_num = -1;
5474+
5475+ /* number of slave select bits is required */
5476+ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
5477+ if (!prop || len < sizeof(*prop)) {
5478+ dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
5479+ goto put_master;
5480+ }
5481+ master->num_chipselect = *prop;
5482+
5483+ xilinx_spi_set_default_reg_offsets(xspi);
5484+
5485+ /* SPI controller initializations */
5486+ xspi_init_hw(xspi->regs);
5487+
5488+ /* Register for SPI Interrupt */
5489+ rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
5490+ if (rc != 0) {
5491+ dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
5492+ goto unmap_io;
5493+ }
5494+
5495+ rc = spi_bitbang_start(&xspi->bitbang);
5496+ if (rc != 0) {
5497+ dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
5498+ goto free_irq;
5499+ }
5500+
5501+ dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
5502+ (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
5503+
5504+ /* Add any subnodes on the SPI bus */
5505+ of_register_spi_devices(master, ofdev->node);
5506+
5507+ return rc;
5508+
5509+free_irq:
5510+ free_irq(xspi->irq, xspi);
5511+unmap_io:
5512+ iounmap(xspi->regs);
5513+put_master:
5514+ spi_master_put(master);
5515+ return rc;
5516+}
5517+
5518+static int __devexit xilinx_spi_remove(struct of_device *ofdev)
5519+{
5520+ struct xilinx_spi *xspi;
5521+ struct spi_master *master;
5522+
5523+ master = platform_get_drvdata(ofdev);
5524+ xspi = spi_master_get_devdata(master);
5525+
5526+ spi_bitbang_stop(&xspi->bitbang);
5527+ free_irq(xspi->irq, xspi);
5528+ iounmap(xspi->regs);
5529+ dev_set_drvdata(&ofdev->dev, 0);
5530+ spi_master_put(xspi->bitbang.master);
5531+
5532+ return 0;
5533+}
5534+
5535+/* work with hotplug and coldplug */
5536+MODULE_ALIAS("platform:" XILINX_SPI_NAME);
5537+
5538+static int __exit xilinx_spi_of_remove(struct of_device *op)
5539+{
5540+ return xilinx_spi_remove(op);
5541+}
5542+
5543+static struct of_device_id xilinx_spi_of_match[] = {
5544+ { .compatible = "xlnx,xps-spi-2.00.a", },
5545+ { .compatible = "xlnx,xps-spi-2.00.b", },
5546+ {}
5547+};
5548+
5549+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
5550+
5551+static struct of_platform_driver xilinx_spi_of_driver = {
5552+ .owner = THIS_MODULE,
5553+ .name = "xilinx-xps-spi",
5554+ .match_table = xilinx_spi_of_match,
5555+ .probe = xilinx_spi_of_probe,
5556+ .remove = __exit_p(xilinx_spi_of_remove),
5557+ .driver = {
5558+ .name = "xilinx-xps-spi",
5559+ .owner = THIS_MODULE,
5560+ },
5561+};
5562+
5563+static int __init xilinx_spi_init(void)
5564+{
5565+ return of_register_platform_driver(&xilinx_spi_of_driver);
5566+}
5567+module_init(xilinx_spi_init);
5568+
5569+static void __exit xilinx_spi_exit(void)
5570+{
5571+ of_unregister_platform_driver(&xilinx_spi_of_driver);
5572+}
5573+module_exit(xilinx_spi_exit);
5574+MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
5575+MODULE_DESCRIPTION("Xilinx SPI driver");
5576+MODULE_LICENSE("GPL");
5577diff -uNr linux-2.6.29-clean/drivers/spi/xilinx_spi_pltfm.c linux-2.6.29/drivers/spi/xilinx_spi_pltfm.c
5578--- linux-2.6.29-clean/drivers/spi/xilinx_spi_pltfm.c 1969-12-31 16:00:00.000000000 -0800
5579+++ linux-2.6.29/drivers/spi/xilinx_spi_pltfm.c 2009-04-06 13:51:47.000000000 -0700
5580@@ -0,0 +1,184 @@
5581+/*
5582+ * xilinx_spi_pltfm.c Support for Xilinx SPI platform devices
5583+ * Copyright (c) 2009 Intel Corporation
5584+ *
5585+ * This program is free software; you can redistribute it and/or modify
5586+ * it under the terms of the GNU General Public License version 2 as
5587+ * published by the Free Software Foundation.
5588+ *
5589+ * This program is distributed in the hope that it will be useful,
5590+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5591+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5592+ * GNU General Public License for more details.
5593+ *
5594+ * You should have received a copy of the GNU General Public License
5595+ * along with this program; if not, write to the Free Software
5596+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5597+ */
5598+
5599+/* Supports:
5600+ * Xilinx SPI devices as platform devices
5601+ *
5602+ * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
5603+ */
5604+
5605+#include <linux/module.h>
5606+#include <linux/init.h>
5607+#include <linux/interrupt.h>
5608+#include <linux/io.h>
5609+#include <linux/platform_device.h>
5610+
5611+#include <linux/spi/spi.h>
5612+#include <linux/spi/spi_bitbang.h>
5613+#include <linux/spi/xilinx_spi.h>
5614+
5615+#include "xilinx_spi.h"
5616+
5617+static int __init xilinx_spi_probe(struct platform_device *dev)
5618+{
5619+ int ret = 0;
5620+ struct spi_master *master;
5621+ struct xilinx_spi *xspi;
5622+ struct xspi_platform_data *pdata;
5623+ struct resource *r;
5624+
5625+ master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
5626+
5627+ if (master == NULL)
5628+ return -ENOMEM;
5629+
5630+
5631+ platform_set_drvdata(dev, master);
5632+ pdata = dev->dev.platform_data;
5633+ if (pdata == NULL) {
5634+ ret = -ENODEV;
5635+ goto put_master;
5636+ }
5637+
5638+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
5639+ if (r == NULL) {
5640+ ret = -ENODEV;
5641+ goto put_master;
5642+ }
5643+
5644+ xspi = spi_master_get_devdata(master);
5645+ xspi->bitbang.master = spi_master_get(master);
5646+ xspi->bitbang.chipselect = xilinx_spi_chipselect;
5647+ xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
5648+ xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
5649+ xspi->bitbang.master->setup = xilinx_spi_setup;
5650+ init_completion(&xspi->done);
5651+
5652+ if (!request_mem_region(r->start, resource_size(r), XILINX_SPI_NAME)) {
5653+ ret = -ENXIO;
5654+ goto put_master;
5655+ }
5656+
5657+ xspi->regs = ioremap(r->start, resource_size(r));
5658+ if (xspi->regs == NULL) {
5659+ ret = -ENOMEM;
5660+ goto map_failed;
5661+ }
5662+
5663+ ret = platform_get_irq(dev, 0);
5664+ if (ret < 0) {
5665+ ret = -ENXIO;
5666+ goto unmap_io;
5667+ }
5668+ xspi->irq = ret;
5669+
5670+ master->bus_num = pdata->bus_num;
5671+ master->num_chipselect = pdata->num_chipselect;
5672+ xspi->speed_hz = pdata->speed_hz;
5673+ xilinx_spi_set_default_reg_offsets(xspi);
5674+ if (pdata->cr_offset)
5675+ xspi->cr_offset = pdata->cr_offset;
5676+ if (pdata->sr_offset)
5677+ xspi->sr_offset = pdata->sr_offset;
5678+ if (pdata->txd_offset)
5679+ xspi->txd_offset = pdata->txd_offset;
5680+ if (pdata->rxd_offset)
5681+ xspi->rxd_offset = pdata->rxd_offset;
5682+ if (pdata->ssr_offset)
5683+ xspi->ssr_offset = pdata->ssr_offset;
5684+
5685+ /* SPI controller initializations */
5686+ xspi_init_hw(xspi);
5687+
5688+ /* Register for SPI Interrupt */
5689+ ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
5690+ if (ret != 0)
5691+ goto unmap_io;
5692+
5693+ ret = spi_bitbang_start(&xspi->bitbang);
5694+ if (ret != 0) {
5695+ dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
5696+ goto free_irq;
5697+ }
5698+
5699+ dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
5700+ (u32)r->start, (u32)xspi->regs, xspi->irq);
5701+ return ret;
5702+
5703+free_irq:
5704+ free_irq(xspi->irq, xspi);
5705+unmap_io:
5706+ iounmap(xspi->regs);
5707+map_failed:
5708+ release_mem_region(r->start, resource_size(r));
5709+put_master:
5710+ spi_master_put(master);
5711+ return ret;
5712+}
5713+
5714+static int __devexit xilinx_spi_remove(struct platform_device *dev)
5715+{
5716+ struct xilinx_spi *xspi;
5717+ struct spi_master *master;
5718+ struct resource *r;
5719+
5720+ master = platform_get_drvdata(dev);
5721+ xspi = spi_master_get_devdata(master);
5722+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
5723+
5724+ spi_bitbang_stop(&xspi->bitbang);
5725+ free_irq(xspi->irq, xspi);
5726+ iounmap(xspi->regs);
5727+
5728+ if (r)
5729+ release_mem_region(r->start, resource_size(r));
5730+
5731+ platform_set_drvdata(dev, 0);
5732+ spi_master_put(xspi->bitbang.master);
5733+
5734+ return 0;
5735+}
5736+
5737+/* work with hotplug and coldplug */
5738+MODULE_ALIAS("platform:" XILINX_SPI_NAME);
5739+
5740+static struct platform_driver xilinx_spi_driver = {
5741+ .probe = xilinx_spi_probe,
5742+ .remove = __devexit_p(xilinx_spi_remove),
5743+ .driver = {
5744+ .name = XILINX_SPI_NAME,
5745+ .owner = THIS_MODULE,
5746+ },
5747+};
5748+
5749+static int __init xilinx_spi_init(void)
5750+{
5751+ return platform_driver_register(&xilinx_spi_driver);
5752+}
5753+module_init(xilinx_spi_init);
5754+
5755+static void __exit xilinx_spi_exit(void)
5756+{
5757+ platform_driver_unregister(&xilinx_spi_driver);
5758+}
5759+module_exit(xilinx_spi_exit);
5760+
5761+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
5762+MODULE_DESCRIPTION("Xilinx SPI platform driver");
5763+MODULE_LICENSE("GPL v2");
5764+
5765diff -uNr linux-2.6.29-clean/include/linux/i2c-ocores.h linux-2.6.29/include/linux/i2c-ocores.h
5766--- linux-2.6.29-clean/include/linux/i2c-ocores.h 2009-04-01 09:20:20.000000000 -0700
5767+++ linux-2.6.29/include/linux/i2c-ocores.h 2009-04-06 13:51:47.000000000 -0700
5768@@ -14,6 +14,8 @@
5769 struct ocores_i2c_platform_data {
5770 u32 regstep; /* distance between registers */
5771 u32 clock_khz; /* input clock in kHz */
5772+ u8 num_devices; /* number of devices in the devices list */
5773+ struct i2c_board_info const *devices; /* devices connected to the bus */
5774 };
5775
5776 #endif /* _LINUX_I2C_OCORES_H */
5777diff -uNr linux-2.6.29-clean/include/linux/mfd/timbdma.h linux-2.6.29/include/linux/mfd/timbdma.h
5778--- linux-2.6.29-clean/include/linux/mfd/timbdma.h 1969-12-31 16:00:00.000000000 -0800
5779+++ linux-2.6.29/include/linux/mfd/timbdma.h 2009-04-06 13:51:47.000000000 -0700
5780@@ -0,0 +1,80 @@
5781+/*
5782+ * timbdma.h timberdale FPGA DMA driver defines
5783+ * Copyright (c) 2009 Intel Corporation
5784+ *
5785+ * This program is free software; you can redistribute it and/or modify
5786+ * it under the terms of the GNU General Public License version 2 as
5787+ * published by the Free Software Foundation.
5788+ *
5789+ * This program is distributed in the hope that it will be useful,
5790+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5791+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5792+ * GNU General Public License for more details.
5793+ *
5794+ * You should have received a copy of the GNU General Public License
5795+ * along with this program; if not, write to the Free Software
5796+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5797+ */
5798+
5799+/* Supports:
5800+ * Timberdale FPGA DMA engine
5801+ */
5802+
5803+#ifndef _TIMBDMA_H
5804+#define _TIMBDMA_H
5805+
5806+#include <linux/spinlock.h>
5807+
5808+
5809+#define DMA_IRQ_UART_RX 0x01
5810+#define DMA_IRQ_UART_TX 0x02
5811+#define DMA_IRQ_MLB_RX 0x04
5812+#define DMA_IRQ_MLB_TX 0x08
5813+#define DMA_IRQ_VIDEO_RX 0x10
5814+#define DMA_IRQ_VIDEO_DROP 0x20
5815+#define DMA_IRQS 6
5816+
5817+
5818+typedef int (*timbdma_interruptcb)(u32 flag, void *data);
5819+
5820+enum timbdma_ctrlmap {
5821+ timbdma_ctrlmap_DMACFGBTUART = 0x000000,
5822+ timbdma_ctrlmap_DMACFGMLBSY = 0x000040,
5823+ timbdma_ctrlmap_DMACFGVIDEO = 0x000080,
5824+ timbdma_ctrlmap_TIMBSTATUS = 0x080000,
5825+ timbdma_ctrlmap_TIMBPEND = 0x080004,
5826+ timbdma_ctrlmap_TIMBENABLE = 0x080008,
5827+ timbdma_ctrlmap_VIDEOBUFFER = 0x200000
5828+};
5829+
5830+enum timbdma_dmacfg {
5831+ timbdma_dmacfg_RXSTARTH = 0x00,
5832+ timbdma_dmacfg_RXSTARTL = 0x04,
5833+ timbdma_dmacfg_RXLENGTH = 0x08,
5834+ timbdma_dmacfg_RXFPGAWP = 0x0C,
5835+ timbdma_dmacfg_RXSWRP = 0x10,
5836+ timbdma_dmacfg_RXENABLE = 0x14,
5837+ timbdma_dmacfg_TXSTARTH = 0x18,
5838+ timbdma_dmacfg_TXSTARTL = 0x1C,
5839+ timbdma_dmacfg_TXLENGTH = 0x20,
5840+ timbdma_dmacfg_TXSWWP = 0x24,
5841+ timbdma_dmacfg_TXFPGARP = 0x28,
5842+ timbdma_dmacfg_TXBEFINT = 0x2C,
5843+ timbdma_dmacfg_BPERROW = 0x30
5844+};
5845+
5846+struct timbdma_dev {
5847+ void __iomem *membase;
5848+ timbdma_interruptcb callbacks[DMA_IRQS];
5849+ void *callback_data[DMA_IRQS];
5850+ spinlock_t lock; /* mutual exclusion */
5851+};
5852+
5853+void timb_start_dma(u32 flag, unsigned long buf, int len, int bytes_per_row);
5854+
5855+void *timb_stop_dma(u32 flags);
5856+
5857+void timb_set_dma_interruptcb(u32 flags, timbdma_interruptcb icb, void *data);
5858+
5859+#endif /* _TIMBDMA_H */
5860+
5861diff -uNr linux-2.6.29-clean/include/linux/mfd/timbi2s.h linux-2.6.29/include/linux/mfd/timbi2s.h
5862--- linux-2.6.29-clean/include/linux/mfd/timbi2s.h 1969-12-31 16:00:00.000000000 -0800
5863+++ linux-2.6.29/include/linux/mfd/timbi2s.h 2009-04-06 13:51:47.000000000 -0700
5864@@ -0,0 +1,66 @@
5865+/*
5866+ * timbi2s.h timberdale FPGA I2S driver
5867+ * Copyright (c) 2009 Intel Corporation
5868+ *
5869+ * This program is free software; you can redistribute it and/or modify
5870+ * it under the terms of the GNU General Public License version 2 as
5871+ * published by the Free Software Foundation.
5872+ *
5873+ * This program is distributed in the hope that it will be useful,
5874+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5875+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5876+ * GNU General Public License for more details.
5877+ *
5878+ * You should have received a copy of the GNU General Public License
5879+ * along with this program; if not, write to the Free Software
5880+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5881+ */
5882+
5883+/* Supports:
5884+ * Timberdale FPGA I2S
5885+ */
5886+
5887+struct timbi2s_bus_control {
5888+ struct list_head list;
5889+};
5890+
5891+struct timbi2s_bus {
5892+ void __iomem *membase;
5893+ u32 irq;
5894+ struct timbi2s_bus_control *control;
5895+ struct workqueue_struct *workqueue;
5896+ struct work_struct work;
5897+};
5898+
5899+struct timbi2s_dev {
5900+ void __iomem *membase;
5901+ u32 irq;
5902+ struct timbi2s_bus *bus;
5903+ struct workqueue_struct *workqueue;
5904+ struct work_struct work;
5905+ u32 ioctrl;
5906+ u32 devid;
5907+ u8 timbi2s_rx;
5908+ u8 timbi2s_tx;
5909+ struct circ_buf *buffer;
5910+ /* Register access */
5911+ spinlock_t lock;
5912+
5913+ int in_use;
5914+ u8 pscale_offset; /* Prescale */
5915+ u8 icr_offset; /* Clear register */
5916+ u8 isr_offset; /* Status */
5917+ u8 ipr_offset; /* Pending register */
5918+ u8 ier_offset; /* Interrupt Enable register */
5919+ u8 ctrl_offset;
5920+ u8 fifo;
5921+
5922+ struct list_head item;
5923+};
5924+
5925+static struct timbi2s_dev *timbi2s_get_tx(void);
5926+static struct timbi2s_dev *timbi2s_get_rx(void);
5927+static void timbi2s_put(struct timbi2s_dev *tdev);
5928+
5929+static int timbi2s_ioctrl(struct timbi2s_dev *i2sdev);
5930+
5931diff -uNr linux-2.6.29-clean/include/linux/serial_core.h linux-2.6.29/include/linux/serial_core.h
5932--- linux-2.6.29-clean/include/linux/serial_core.h 2009-04-01 09:20:20.000000000 -0700
5933+++ linux-2.6.29/include/linux/serial_core.h 2009-04-06 13:51:47.000000000 -0700
5934@@ -164,6 +164,9 @@
5935 /* NWPSERIAL */
5936 #define PORT_NWPSERIAL 85
5937
5938+/* Timberdale UART */
5939+#define PORT_TIMBUART 86
5940+
5941 #ifdef __KERNEL__
5942
5943 #include <linux/compiler.h>
5944diff -uNr linux-2.6.29-clean/include/linux/spi/xilinx_spi.h linux-2.6.29/include/linux/spi/xilinx_spi.h
5945--- linux-2.6.29-clean/include/linux/spi/xilinx_spi.h 1969-12-31 16:00:00.000000000 -0800
5946+++ linux-2.6.29/include/linux/spi/xilinx_spi.h 2009-04-06 13:51:47.000000000 -0700
5947@@ -0,0 +1,17 @@
5948+#ifndef __LINUX_SPI_XILINX_SPI_H
5949+#define __LINUX_SPI_XILINX_SPI_H
5950+
5951+/* SPI Controller IP */
5952+struct xspi_platform_data {
5953+ s16 bus_num;
5954+ u16 num_chipselect;
5955+ u32 speed_hz;
5956+ u8 cr_offset;
5957+ u8 sr_offset;
5958+ u8 txd_offset;
5959+ u8 rxd_offset;
5960+ u8 ssr_offset;
5961+};
5962+
5963+#endif /* __LINUX_SPI_XILINX_SPI_H */
5964+
5965diff -uNr linux-2.6.29-clean/include/media/adv7180.h linux-2.6.29/include/media/adv7180.h
5966--- linux-2.6.29-clean/include/media/adv7180.h 1969-12-31 16:00:00.000000000 -0800
5967+++ linux-2.6.29/include/media/adv7180.h 2009-04-06 13:51:47.000000000 -0700
5968@@ -0,0 +1,127 @@
5969+/*
5970+ * adv7180.h Analog Devices ADV7180 video decoder driver defines
5971+ * Copyright (c) 2009 Intel Corporation
5972+ *
5973+ * This program is free software; you can redistribute it and/or modify
5974+ * it under the terms of the GNU General Public License version 2 as
5975+ * published by the Free Software Foundation.
5976+ *
5977+ * This program is distributed in the hope that it will be useful,
5978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5980+ * GNU General Public License for more details.
5981+ *
5982+ * You should have received a copy of the GNU General Public License
5983+ * along with this program; if not, write to the Free Software
5984+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5985+ */
5986+
5987+#define DRIVER_NAME "adv7180"
5988+
5989+#define I2C_ADV7180 0x42
5990+#define ADV7180_NR_REG 0xfc
5991+
5992+#define ADV7180_IN_CTRL 0x00 /* Input CR */
5993+#define ADV7180_OUT_CTRL 0x03 /* Output CR */
5994+#define ADV7180_EXT_OUT_CTRL 0x04 /* Extended Output CR */
5995+
5996+#define ADV7180_ADI_CTRL 0x0e /* ADI CR */
5997+# define ADI_ENABLE 0x20 /* Enable access to sub-regs */
5998+
5999+#define ADV7180_SR_1 0x10 /* Status Register 1 */
6000+#define ADV7180_SR_2 0x12
6001+#define ADV7180_SR_3 0x13
6002+
6003+/* Interrupt and VDP sub-registers */
6004+#define ADV7180_ISR_1 0x42 /* Interrupt Status Register 1 */
6005+#define ADV7180_ICR_1 0x43 /* Interrupt Clear Register 1 */
6006+
6007+#define ADV7180_ISR_2 0x46
6008+#define ADV7180_ICR_2 0x47
6009+
6010+#define ADV7180_ISR_3 0x4a
6011+#define ADV7180_ICR_3 0x4b
6012+
6013+#define ADV7180_ISR_4 0x4e
6014+#define ADV7180_ICR_4 0x4f
6015+/* */
6016+
6017+#define ADV7180_SR 0x10
6018+#define ADV7180_STATUS_NTSM 0x00 /* NTSM M/J */
6019+#define ADV7180_STATUS_NTSC 0x10 /* NTSC 4.43 */
6020+#define ADV7180_STATUS_PAL_M 0x20 /* PAL M */
6021+#define ADV7180_STATUS_PAL_60 0x30 /* PAL 60 */
6022+#define ADV7180_STATUS_PAL 0x40 /* PAL B/G/H/I/D */
6023+#define ADV7180_STATUS_SECAM 0x50 /* SECAM */
6024+#define ADV7180_STATUS_PAL_N 0x60 /* PAL Combination N */
6025+#define ADV7180_STATUS_SECAM_525 0x70 /* SECAM 525 */
6026+
6027+enum input_mode {
6028+ CVBS, /* Composite */
6029+ SVIDEO, /* S-video */
6030+ YPbPr, /* Component */
6031+};
6032+
6033+struct adv7180 {
6034+ unsigned char reg[ADV7180_NR_REG];
6035+ int norm;
6036+ enum input_mode input;
6037+ int enable;
6038+ struct i2c_client *client;
6039+};
6040+
6041+static const unsigned char reset_icr[] = {
6042+ ADV7180_ICR_1, 0x00,
6043+ ADV7180_ICR_2, 0x00,
6044+ ADV7180_ICR_3, 0x00,
6045+ ADV7180_ICR_4, 0x00,
6046+};
6047+
6048+/* ADV7180 LQFP-64. ADV7180.pdf, page 104 */
6049+static const unsigned char init_cvbs_64[] = {
6050+ 0x00, 0x01, /* INSEL = CVBS in on Ain2 */
6051+ 0x04, 0x57, /* Enable SFL */
6052+ 0x17, 0x41, /* Select SH1 */
6053+
6054+ 0x31, 0x02, /* Clear NEWAV_MODE, SAV/EAV to
6055+ * suit ADV video encoders
6056+ */
6057+ 0x3d, 0xa2, /* MWE enable manual window,
6058+ * color kill threshold to 2
6059+ */
6060+ 0x3e, 0x6a, /* BLM optimization */
6061+ 0x3f, 0xa0, /* BGB optimization */
6062+ 0x0e, 0x80, /* Hidden space */
6063+ 0x55, 0x81, /* ADC configuration */
6064+ 0x0e, 0x00, /* User space */
6065+};
6066+
6067+static const unsigned char init_svideo_64[] = {
6068+ 0x00, 0x08, /* Insel = Y/C, Y = AIN3, C = AIN6 */
6069+ 0x04, 0x57, /* Enable SFL */
6070+ 0x31, 0x02, /* Clear NEWAV_MODE, SAV/EAV to
6071+ * suit ADV video encoders
6072+ */
6073+ 0x3d, 0xa2, /* MWE enable manual window,
6074+ * color kill threshold to 2
6075+ */
6076+ 0x3e, 0x6a, /* BLM optimization */
6077+ 0x3f, 0xa0, /* BGB optimization */
6078+ 0x58, 0x04, /* Mandatory write. This must be
6079+ * performed for correct operation.
6080+ */
6081+ 0x0e, 0x80, /* Hidden space */
6082+ 0x55, 0x81, /* ADC configuration */
6083+ 0x0e, 0x00, /* User space */
6084+};
6085+
6086+static const unsigned char init_ypbpr_64[] = {
6087+ 0x00, 0x09, /* INSEL = YPrPb, Y = AIN1, Pr = AIN4, Pb = AIN5 */
6088+ 0x31, 0x02, /* Clear NEWAV_MODE, SAV/EAV to suit ADV video encoders */
6089+ 0x3d, 0xa2, /* MWE enable manual window */
6090+ 0x3e, 0x6a, /* BLM optimization */
6091+ 0x3f, 0xa0, /* ADI recommended */
6092+ 0x0e, 0x80, /* Hidden space */
6093+ 0x55, 0x81, /* ADC configuration */
6094+ 0x0e, 0x00, /* User space */
6095+};