crucial_oj: add oj driver and modifications needed in gpio_input/event/matrix
diff --git a/drivers/spi/spi_oj.c b/drivers/spi/spi_oj.c
new file mode 100644
index 0000000..d626d89
--- /dev/null
+++ b/drivers/spi/spi_oj.c
@@ -0,0 +1,239 @@
+/* linux/driver/spi/spi_oj.c
+ *
+ *
+ * Copyright (C) 2009 HTC Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ *
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#define tSRAD	160
+#define tSWW	30
+
+#define OJ_MOTION              (26)
+#define OJ_SHUTDOWN            (35)
+#define OJ_RST                 (36)
+
+// #define OJ_DEBUG 1
+static struct spi_device        *spidev;
+struct work_struct oj_work;
+
+u8 oj_reg_read(u8 reg)
+{
+	u8 val;
+	struct spi_msg msg;
+	int err = 0;
+	if (!spidev)
+          {
+            printk(KERN_ERR "%s: spidev = 0\n", __func__);
+		return 0;
+          }
+	udelay(1);
+
+	msg.buffer[0] = reg;
+	msg.len = 0;
+	err += spi_read_write_lock(spidev, &msg, NULL, 1, 1);
+	udelay(tSRAD);
+	err += spi_read_write_lock(spidev, NULL, &val, 1, 0);
+#ifdef OJ_DEBUG
+	if (err != 0)
+		printk("oj_reg_read fail\n");
+#endif
+	return val;
+}
+EXPORT_SYMBOL(oj_reg_read);
+
+int oj_reg_write(u8 reg, u8 val)
+{
+	struct spi_msg msg;
+	int err = 0;
+	if (!spidev)
+		return 0;
+#ifdef OJ_DEBUG
+	printk(KERN_INFO "write %x to reg%x\n", val, reg);
+#endif
+	msg.buffer[0] = reg | 0x80;
+	msg.buffer[1] = val;
+	msg.len = 0;
+	udelay(1);
+	err += spi_read_write_lock(spidev, &msg, NULL, 2, 1);
+#ifdef OJ_DEBUG
+	if (err != 0)
+		printk("oj_reg_write fail\n");
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(oj_reg_write);
+
+int oj_burst_read(char *buf, int len)
+{
+	struct spi_msg msg;
+	int err = 0;
+	if (!spidev)
+		return 0;
+
+	msg.buffer[0] = 0x02;
+	msg.len = 0;
+	udelay(1);
+	err += spi_read_write_lock(spidev, &msg, NULL, 1, 1);
+	udelay(tSRAD);
+	err += spi_read_write_lock(spidev, NULL, buf, len, 0);
+#ifdef OJ_DEBUG
+	if (err != 0)
+		printk("oj_burst_read fail\n");
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(oj_burst_read);
+
+#ifdef OJ_DEBUG
+static irqreturn_t oj_interrupt(int irq, void *data)
+{
+	int motion;
+	/* printk("oj interrupt\n");*/
+	motion = gpio_get_value(OJ_MOTION);
+	if (motion)
+		return IRQ_HANDLED;
+	schedule_work(&oj_work);
+	return IRQ_HANDLED;
+}
+
+static void oj_do_work(struct work_struct *w)
+{
+	char motion_val;
+	printk(KERN_INFO "%s\n", __func__);
+	printk(KERN_INFO "reg02 = 0x%x\n", oj_reg_read(0x02));
+	printk(KERN_INFO "reg03 = 0x%x\n", oj_reg_read(0x03));
+	printk(KERN_INFO "reg04 = 0x%x\n", oj_reg_read(0x04));
+	motion_val = oj_reg_read(0x02);
+	if (motion_val & (1 << 7)) {
+		printk(KERN_INFO "reg02 = 0x%x\n", oj_reg_read(0x02));
+		printk(KERN_INFO "reg03 = 0x%x\n", oj_reg_read(0x03));
+		printk(KERN_INFO "reg04 = 0x%x\n", oj_reg_read(0x04));
+	}
+
+	printk(KERN_INFO "gpio26 = %d\n", gpio_get_value(26));
+}
+#endif
+
+static int oj_spi_probe(struct spi_device *spi)
+{
+#ifdef OJ_DEBUG
+	int irq_oj;
+	int ret;
+#endif
+	printk(KERN_INFO "%s \n", __func__);
+	spidev = spi;
+
+#ifdef OJ_DEBUG
+	gpio_set_value(OJ_RST, 0);
+	udelay(20);
+	gpio_set_value(OJ_RST, 1);
+	mdelay(10);
+	oj_reg_write(0x3a, 0x5a);
+	mdelay(23);
+	printk(KERN_INFO "reg02 = 0x%x\n", oj_reg_read(0x02));
+	printk(KERN_INFO "reg03 = 0x%x\n", oj_reg_read(0x03));
+	printk(KERN_INFO "reg04 = 0x%x\n", oj_reg_read(0x04));
+	printk(KERN_INFO "reg00 = 0x%x\n", oj_reg_read(0x00));
+	printk(KERN_INFO "gpio26 = %d\n", gpio_get_value(26));
+
+	ret = gpio_request(OJ_MOTION, "OJ irq");
+	if (ret < 0) {
+		printk(KERN_ERR "gpio_request error\n");
+		return 0;
+	}
+
+	ret = gpio_direction_input(OJ_MOTION);
+	if (ret < 0) {
+		printk(KERN_ERR "gpio_drection_input eror\n");
+		gpio_free(OJ_MOTION);
+		return 0;
+	}
+
+	irq_oj = gpio_to_irq(OJ_MOTION);
+	if (irq_oj < 0) {
+		printk(KERN_ERR "gpio_to_irq error\n");
+		gpio_free(OJ_MOTION);
+		return 0;
+	}
+
+	ret = request_irq(irq_oj, oj_interrupt,
+				IRQF_TRIGGER_FALLING, "OJ irq", NULL);
+	if (ret < 0) {
+		printk(KERN_ERR "%s(): request_irq  fail\n", __func__);
+		gpio_free(OJ_MOTION);
+	}
+	INIT_WORK(&oj_work, oj_do_work);
+#endif
+	return 0 ;
+}
+
+static int __exit oj_spi_remove(struct spi_device *spi)
+{
+	spidev = NULL;
+	return 0;
+}
+
+
+static struct spi_driver spi_oj = {
+	.driver = {
+		.name  = "spi_oj",
+		.owner = THIS_MODULE,
+	},
+	.probe         = oj_spi_probe,
+	.remove        = __exit_p(oj_spi_remove),
+};
+
+static int __init spi_oj_init(void)
+{
+	int rc;
+	rc = spi_register_driver(&spi_oj);
+	return rc;
+}
+module_init(spi_oj_init);
+
+static void __exit spi_oj_exit(void)
+{
+	spi_unregister_driver(&spi_oj);
+}
+module_exit(spi_oj_exit);
+
+#ifdef OJ_DEBUG
+static int oj_set_debug(const char *val, struct kernel_param *kp)
+{
+	printk(KERN_INFO "reg02 = 0x%x\n", oj_reg_read(0x02));
+	printk(KERN_INFO "reg03 = 0x%x\n", oj_reg_read(0x03));
+	printk(KERN_INFO "reg04 = 0x%x\n", oj_reg_read(0x04));
+	printk(KERN_INFO "reg00 = 0x%x\n", oj_reg_read(0x00));
+	printk(KERN_INFO "gpio26 = %d\n", gpio_get_value(26));
+	return 0;
+}
+
+static int oj_get_debug(char *buffer, struct kernel_param *kp)
+{
+	oj_reg_write(0x02, 0);
+	return 1;
+}
+
+//module_param_call(debug, oj_set_debug, oj_get_debug, 0, 0664);
+#endif /*OJ_DEBUG*/