blob: d626d894760cca0977efc088ee33fc336602fb2d [file] [log] [blame]
/* 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*/