BigW Consortium Gitlab

Commit 80d952e3 by Forest Godfrey

First pass with working I2C driver. Loads cleanly against real device, but needs a lot of

code cleanup.
parent 4a9b5f01
#ifndef _AI2C_PLATFORM_DATA_H
#define _AI2C_PLATFORM_DATA_H
typedef struct arduino_i2c_keyboard_platform_data {
int gpio_intr_pin;
int *keymap;
} arduino_i2c_keyboard_platform_data_t;
#endif /* _AI2C_PLATFORM_DATA_H */
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
#define IRQ_GPIO_PIN 22
#include "ai2c_platform_data.h"
#define IRQ_GPIO_PIN 9
#define GPIO_IRQ_NAME "ai2c_keyboard_irq"
static int irq_num = -1;
static int count = 0;
static int up_count = 0;
struct delayed_work my_work;
static struct i2c_client *my_client = NULL; // XXX - FIXME
const int keymap[] = {
0,
};
static void
ai2c_intr(struct work_struct *work) {
if (up_count++ < 10) {
printk("ai2c_intr: entered\n");
}
if (my_client)
i2c_smbus_write_byte_data(my_client, 50, 48);
return;
}
static irqreturn_t
ai2c_intr_lower(int irq, void *data) {
if (count++ < 10) {
printk("ai2c_intr_lower: entered\n");
}
schedule_delayed_work(&my_work, 25);
return IRQ_HANDLED;
}
int
ai2c_init(void) {
static int
ai2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
int ret;
int flags = 0;
void *drv_info = NULL;
const arduino_i2c_keyboard_platform_data_t *pdata =
dev_get_platdata(&client->dev);
printk(KERN_INFO "Arduino I2C Keyboard Starting\n");
ret = gpio_request(IRQ_GPIO_PIN, GPIO_IRQ_NAME);
dev_info(&client->dev, "Arduino I2C Keyboard Probe Starting\n");
if (!pdata) {
dev_err(&client->dev, "No platform present - failing\n");
return -EINVAL;
}
ret = gpio_request(pdata->gpio_intr_pin, GPIO_IRQ_NAME);
if (ret < 0) {
printk(KERN_ERR "ai2c: IRQ pin reservation failed: error %d\n", ret);
dev_err(&client->dev, "ai2c: IRQ pin reservation of %d failed: error %d\n", pdata->gpio_intr_pin, ret);
return ret;
}
gpio_direction_input(IRQ_GPIO_PIN);
irq_num = gpio_to_irq(IRQ_GPIO_PIN);
gpio_direction_input(pdata->gpio_intr_pin);
gpio_set_debounce(pdata->gpio_intr_pin, 50); // 50ms
#ifndef CONFIG_SIERRA
/* GPIO exports are broken on Sierra Wireless Linux due to their weird gpiolib mods */
gpio_export(pdata->gpio_intr_pin, "arduino_i2c_intr_pin");
#endif /* CONFIG_SIERRA */
printk(KERN_INFO "ai2c: Reserved pin [%d]: irq = %d\n", IRQ_GPIO_PIN, irq_num);
irq_num = gpio_to_irq(pdata->gpio_intr_pin);
dev_dbg(&client->dev, "ai2c: Reserved pin [%d]: irq = %d\n", pdata->gpio_intr_pin, irq_num);
flags |= IRQF_TRIGGER_FALLING;
ret = request_irq(irq_num, ai2c_intr_lower, flags, "ai2c_keyboard", drv_info);
if (ret < 0) {
printk(KERN_ERR "ai2c: request_irq failed: error %d\n", ret);
dev_err(&client->dev, "ai2c: request_irq failed: error %d\n", ret);
return ret;
}
irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_FALLING);
my_client = client; // XXX - FIXME - Put in IRQ Info
return 0;
}
void
ai2c_shutdown(void) {
printk(KERN_INFO "Arduino I2C Keyboard Shutting Down\n");
static int
ai2c_remove(struct i2c_client *client) {
if (irq_num > 0) {
free_irq(irq_num, ai2c_intr_lower);
}
return 0;
}
static const struct i2c_device_id ai2c_id[] = {
{ "ai2c-keys", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ai2c_id);
static struct i2c_driver ai2c_driver = {
.driver = {
.name = KBUILD_MODNAME,
},
.probe = ai2c_probe,
.remove = ai2c_remove,
.id_table = ai2c_id,
};
int
ai2c_init(void) {
int ret;
printk(KERN_INFO "Arduino I2C Keyboard Starting\n");
ret = i2c_add_driver(&ai2c_driver);
if (ret < 0) {
printk(KERN_ERR "Unable to register AI2C keyboard driver\n");
}
INIT_DELAYED_WORK(&my_work, ai2c_intr);
return ret;
}
void
ai2c_shutdown(void) {
printk(KERN_INFO "Arduino I2C Keyboard Shutting Down\n");
}
module_init(ai2c_init);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment