[Armadeus-commitlog] SF.net SVN: armadeus: [775] trunk/target/linux/modules
Brought to you by:
sszy
|
From: <jo...@us...> - 2008-03-16 12:58:24
|
Revision: 775
http://armadeus.svn.sourceforge.net/armadeus/?rev=775&view=rev
Author: jorasse
Date: 2008-03-16 05:58:29 -0700 (Sun, 16 Mar 2008)
Log Message:
-----------
[Linux] updated imx keypad driver compatibility with recent linux kernel and fixed some bugs.
Modified Paths:
--------------
trunk/target/linux/modules/Makefile
trunk/target/linux/modules/keypad/Kconfig
trunk/target/linux/modules/keypad/Makefile
trunk/target/linux/modules/keypad/imxkeypad.c
Modified: trunk/target/linux/modules/Makefile
===================================================================
--- trunk/target/linux/modules/Makefile 2008-03-14 13:01:08 UTC (rev 774)
+++ trunk/target/linux/modules/Makefile 2008-03-16 12:58:29 UTC (rev 775)
@@ -7,7 +7,7 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
-obj-$(CONFIG_ARMADEUS_DRIVERS) += gpio/ ps2keyboard/ fpga_devtools/ pwm/ backlight/ isp1761/
+obj-$(CONFIG_ARMADEUS_DRIVERS) += gpio/ ps2keyboard/ keypad/ fpga_devtools/ pwm/ backlight/ isp1761/
# Part execute when called from standard make in this directory:
else
Modified: trunk/target/linux/modules/keypad/Kconfig
===================================================================
--- trunk/target/linux/modules/keypad/Kconfig 2008-03-14 13:01:08 UTC (rev 774)
+++ trunk/target/linux/modules/keypad/Kconfig 2008-03-16 12:58:29 UTC (rev 775)
@@ -2,9 +2,9 @@
#
config ARMADEUS_KEYPAD_DRIVER
- boolean "Armadeus keypad driver"
+ tristate "Armadeus keypad driver"
default n
depends on ARMADEUS_DRIVERS
---help---
- GPIO can be used to control a matrix keypad with this driver
+ GPIO pins can be used to control a matrix keypad with this driver
Modified: trunk/target/linux/modules/keypad/Makefile
===================================================================
--- trunk/target/linux/modules/keypad/Makefile 2008-03-14 13:01:08 UTC (rev 774)
+++ trunk/target/linux/modules/keypad/Makefile 2008-03-16 12:58:29 UTC (rev 775)
@@ -1,21 +1,20 @@
#
-# Makefile for the Armadeus keypad drivers
+# Makefile for the imx keypad drivers
#
-# unfinished state; to be continued
-BASE_DIR="../../../../buildroot/"
-
-REL=`grep "BR2_PACKAGE_LINUX_VERSION=" $(BASE_DIR).config | \
- sed "s/BR2_PACKAGE_LINUX_VERSION=\\"//" | sed "s/\\"//"`
-
-ARMADEUS_KERNEL_DIR=$(BASE_DIR)build_arm_nofpu/linux-$(REL)
-
+# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
-obj-m += imxkeypad.o
+obj-$(CONFIG_ARMADEUS_KEYPAD_DRIVER) += imxkeypad.o
+# Part executed when called from standard make in this directory:
+# (preferably use Makefile in parent directory)
else
-#KDIR := /lib/modules/$(shell uname -r)/build
+
+BASE_DIR="../../../../buildroot/"
+REL=`grep "BR2_PACKAGE_LINUX_VERSION=" $(BASE_DIR).config | \
+ sed "s/BR2_PACKAGE_LINUX_VERSION=\\"//" | sed "s/\\"//"`
+ARMADEUS_KERNEL_DIR=$(BASE_DIR)build_arm_nofpu/linux-$(REL)
KDIR := $(ARMADEUS_KERNEL_DIR)
PWD := $(shell pwd)
@@ -24,10 +23,6 @@
clean:
rm -f *.*o
-
-install:
- echo "Installing drivers..."
- echo "type: cp *.ko $(BASE_DIR)build_arm_nofpu/root/lib/modules/2.6.12/kernel/drivers/"
+ rm -f Module.symvers
endif
-
Modified: trunk/target/linux/modules/keypad/imxkeypad.c
===================================================================
--- trunk/target/linux/modules/keypad/imxkeypad.c 2008-03-14 13:01:08 UTC (rev 774)
+++ trunk/target/linux/modules/keypad/imxkeypad.c 2008-03-16 12:58:29 UTC (rev 775)
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006 Eric Jarrige
+ * imxkeypad driver for Linux/ARM Armadeus project
*
+ * Copyright (c) 2006-2008 Eric Jarrige
+ *
* Based on LoCoMo keyboard driver
*/
/*
- * imxkeypad driver for Linux/ARM
*/
/*
@@ -25,7 +26,7 @@
*
*/
-#include <linux/config.h>
+#include <linux/autoconf.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -35,35 +36,29 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/ioport.h>
#include <asm/io.h>
-#include <asm/arch/imx-regs.h>
+#include <asm/arch/hardware.h>
#include <asm/irq.h>
-MODULE_AUTHOR("Eric Jarrige <jo...@us...>");
+MODULE_AUTHOR("Eric Jarrige");
MODULE_DESCRIPTION("IMX keypad driver");
MODULE_LICENSE("GPL");
-#define KPD_ROW_IDX 0
-#define KPD_COL_IDX 1
+#define DEBUG
#define KPD_MAX_ROWS 8
-#define KPD_ROWS 4
-#define KPD_ROWS_BIT_OFFSET 3
+#define KPD_MAX_COLS 8
-#define KPD_MAX_COLS 16
-#define KPD_COLS 4
-#define KPD_COLS_BIT_OFFSET 7
+#define KB_ROWMASK(r) (1 << (r + kpdPtr->rows_offset))
+#define SCANCODE(c,r) ( (c * kpdPtr->num_rows) + (r) )
-#define IMXKEYPAD_NUMKEYS (KPD_ROWS * KPD_COLS)
-#define KB_ROWMASK(r) (1 << (r + KPD_ROWS_BIT_OFFSET))
-#define SCANCODE(c,r) ( (c * KPD_ROWS) + (r) )
-
#define KB_DELAY 8
#define SCAN_INTERVAL (HZ/10)
-static unsigned char imxkeypad_keycode[IMXKEYPAD_NUMKEYS] = {
+static unsigned char imxkeypad_keycode[KPD_MAX_ROWS * KPD_MAX_COLS] = {
KEY_LEFT, KEY_RIGHT, KEY_ENTER, KEY_ESC, /* 0 - 3 */
KEY_3, KEY_6, KEY_9, KEY_SPACE, /* 4 - 7 */
KEY_2, KEY_5, KEY_8, KEY_0, /* 8 - 11 */
@@ -71,40 +66,28 @@
};
struct imxkeypad {
- unsigned char keycode[IMXKEYPAD_NUMKEYS];
- struct input_dev input;
+ unsigned char keycode[KPD_MAX_ROWS * KPD_MAX_COLS];
+ struct input_dev *input;
char phys[32];
- unsigned long base;
int num_rows;
int rows_offset;
int num_cols;
int cols_offset;
-
+ int port;
+ int irqs[KPD_MAX_ROWS];
spinlock_t lock;
struct timer_list timer;
char irq_disabled;
+ int debouncing;
};
-static int irq[KPD_MAX_ROWS] = {
- IRQ_GPIOA(0+KPD_ROWS_BIT_OFFSET),
- IRQ_GPIOA(1+KPD_ROWS_BIT_OFFSET),
- IRQ_GPIOA(2+KPD_ROWS_BIT_OFFSET),
- IRQ_GPIOA(3+KPD_ROWS_BIT_OFFSET)
-};
-static unsigned int num_irq = KPD_ROWS;
-module_param_array(irq, int, &num_irq, 0000);
-MODULE_PARM_DESC(irq, "irqs asserted on key pressed");
+static int io_port=0;
+module_param(io_port, int, 0000);
+MODULE_PARM_DESC(io_port, "GPIO port (0..3)");
-static long int io_addr[]={(long)&DR(0),(long)&SSR(0)};
-module_param_array(io_addr, long, NULL, 0000);
-MODULE_PARM_DESC(io_addr, "control and status register addresses");
-#define CTRL_REG (io_addr[0])
-#define STAT_REG (io_addr[1])
-
-
static long int size[]={4,4};
module_param_array(size, long, NULL, 0000);
MODULE_PARM_DESC(size, "matrix size: num rows, num cols");
@@ -114,237 +97,224 @@
MODULE_PARM_DESC(bit_offset, "rows and cols bits offset in registers");
/* helper functions for reading the keyboard matrix */
-static inline void imxkeypad_charge_all(unsigned long membase)
+static inline void imxkeypad_charge_all(struct imxkeypad *kpdPtr)
{
- DR(0) |= (((1<<KPD_COLS)-1)<<KPD_COLS_BIT_OFFSET);
+ DR(kpdPtr->port) |=
+ (((1<<(kpdPtr->num_cols))-1)<<(kpdPtr->cols_offset));
}
-static inline void imxkeypad_activate_all(unsigned long membase)
+static inline void imxkeypad_activate_all(struct imxkeypad *kpdPtr)
{
- DR(0) &= ~(((1<<KPD_COLS)-1)<<KPD_COLS_BIT_OFFSET);
+ DR(kpdPtr->port) &= ~(((1<<(kpdPtr->num_cols))-1)<<(kpdPtr->cols_offset));
}
-static inline void imxkeypad_activate_col(unsigned long membase, int col)
+static inline void imxkeypad_activate_col(struct imxkeypad *kpdPtr, int col)
{
- DR(0) &= ~(1 << (col + KPD_COLS_BIT_OFFSET));
+ DR(kpdPtr->port) &= ~(1 << (col + kpdPtr->cols_offset));
}
-static inline void imxkeypad_reset_col(unsigned long membase, int col)
+static inline void imxkeypad_reset_col(struct imxkeypad *kpdPtr, int col)
{
- DR(0) |= (1 << (col + KPD_COLS_BIT_OFFSET));
+ DR(kpdPtr->port) |= (1 << (col + kpdPtr->cols_offset));
}
/*
- * The LoCoMo keyboard only generates interrupts when a key is pressed.
+ * The imx keypad only generates interrupts when a key is pressed.
* So when a key is pressed, we enable a timer. This timer scans the
* keyboard, and this is how we detect when the key is released.
*/
/* Scan the hardware keyboard and push any changes up through the input layer */
-static void imxkeypad_scankeyboard(struct imxkeypad *imxkeypad, struct pt_regs *regs)
+static void imxkeypad_scankeyboard(struct imxkeypad *kpdPtr)
{
- unsigned int row, col, rowd, scancode;
- unsigned long flags;
+ unsigned int row, col, scancode;
+ unsigned long rowd;
unsigned int num_pressed;
- unsigned long membase = imxkeypad->base;
- spin_lock_irqsave(&imxkeypad->lock, flags);
+ imxkeypad_charge_all(kpdPtr);
- if (!imxkeypad->irq_disabled) {
- for (row = 0; row < num_irq; row++) {
- disable_irq_nosync(irq[row]);
- }
- imxkeypad->irq_disabled = 1;
- }
- //disable_irq_nosync(irq);
-
-
- if (regs)
- input_regs(&imxkeypad->input, regs);
-
- imxkeypad_charge_all(membase);
-
num_pressed = 0;
- for (col = 0; col < KPD_COLS; col++) {
+ for (col = 0; col < kpdPtr->num_cols; col++) {
- imxkeypad_activate_col(membase, col);
+ imxkeypad_activate_col(kpdPtr, col);
udelay(KB_DELAY);
- rowd = ~readl(&SSR(0));
- for (row = 0; row < KPD_ROWS; row++ ) {
+ rowd = ~(SSR(kpdPtr->port));
+ for (row = 0; row < kpdPtr->num_rows; row++ ) {
scancode = SCANCODE(col, row);
if (rowd & KB_ROWMASK(row)) {
- num_pressed += 1;
- input_report_key(&imxkeypad->input, imxkeypad->keycode[scancode], 1);
- } else {
- input_report_key(&imxkeypad->input, imxkeypad->keycode[scancode], 0);
+ num_pressed++;
+ input_report_key(kpdPtr->input, kpdPtr->keycode[scancode], 1);
+ kpdPtr->debouncing = 1;
+ printk(KERN_DEBUG "key index: %d\n", scancode);
+ } else if (1 >= kpdPtr->debouncing) {
+ input_report_key(kpdPtr->input, kpdPtr->keycode[scancode], 0);
}
}
- imxkeypad_reset_col(membase, col);
+ imxkeypad_reset_col(kpdPtr, col);
}
- imxkeypad_activate_all(membase);
+ imxkeypad_activate_all(kpdPtr);
- input_sync(&imxkeypad->input);
+ input_sync(kpdPtr->input);
- /* if any keys are pressed, enable the timer */
- if (num_pressed)
- mod_timer(&imxkeypad->timer, jiffies + SCAN_INTERVAL);
- printk(KERN_ERR "imxkeypad: polling\n");
+ /* on key release repeat some scan to remove debounce */
+ if ((!num_pressed)&&(0 <= kpdPtr->debouncing)) {
+ kpdPtr->debouncing--;
+ }
- if ((!num_pressed)&&(imxkeypad->irq_disabled)) {
- for (row = 0; row < num_irq; row++) {
- enable_irq(irq[row]);
+ if ((!num_pressed)&&(kpdPtr->irq_disabled)&&(0 >= kpdPtr->debouncing)) {
+ for (row = 0; row < kpdPtr->num_rows; row++) {
+ enable_irq(kpdPtr->irqs[row]);
}
- imxkeypad->irq_disabled = 0;
+ kpdPtr->irq_disabled = 0;
+ } else {
+ /* if any keys are pressed or still checking debounce, enable the timer */
+ mod_timer(&kpdPtr->timer, jiffies + SCAN_INTERVAL);
}
- spin_unlock_irqrestore(&imxkeypad->lock, flags);
-
-
}
/*
* imxkeypad interrupt handler.
*/
-static irqreturn_t imxkeypad_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t imxkeypad_interrupt(int irq, void *dev_id/*, struct pt_regs *regs*/)
{
- struct imxkeypad *imxkeypad = dev_id;
- /** wait chattering delay **/
- /* udelay(100); */
+ struct imxkeypad *kpdPtr = dev_id;
+ unsigned int row;
+
+ if (!kpdPtr->irq_disabled) {
+ for (row = 0; row < kpdPtr->num_rows; row++) {
+ disable_irq(kpdPtr->irqs[row]);
+ }
+ kpdPtr->irq_disabled = 1;
+ kpdPtr->debouncing = 1;
+ }
- printk(KERN_ERR "imxkeypad: interrupt\n");
- //imxkeypad_scankeyboard(imxkeypad, regs);
- mod_timer(&imxkeypad->timer, jiffies + SCAN_INTERVAL);
+ printk(KERN_DEBUG "keypad int\n");
+ mod_timer(&kpdPtr->timer, jiffies + SCAN_INTERVAL);
+
return IRQ_HANDLED;
}
/*
- * LoCoMo timer checking for released keys
+ * imxkeypad timer checking for released keys
*/
static void imxkeypad_timer_callback(unsigned long data)
{
- struct imxkeypad *imxkeypad = (struct imxkeypad *) data;
- imxkeypad_scankeyboard(imxkeypad, NULL);
+ struct imxkeypad *kpdPtr = (struct imxkeypad *) data;
+ imxkeypad_scankeyboard(kpdPtr);
}
-static struct imxkeypad imxkeypad = {
- .phys = "imxkeypad/input0",
-};
+static struct imxkeypad imxkeypad;
static int __init imxkeypad_init(void)
{
int i, ret;
- printk("Initializing Armadeus keypad driver\n");
+ printk(KERN_INFO "Initializing Armadeus keypad driver\n");
-// imxkeypad = kmalloc(sizeof(struct imxkeypad), GFP_KERNEL);
-// if (!imxkeypad)
-// return -ENOMEM;
-
memset(&imxkeypad, 0, sizeof(struct imxkeypad));
- /* try and claim memory region */
-// if (!request_mem_region((unsigned long) dev->mapbase,
-// dev->length,
-// LOCOMO_DRIVER_NAME(dev))) {
-// ret = -EBUSY;
-// printk(KERN_ERR "imxkeypad: Can't acquire access to io memory for keyboard\n");
-// goto free;
-// }
-
-// imxkeypad->ldev = dev;
-// locomo_set_drvdata(dev, imxkeypad);
-
-// imxkeypad->base = (unsigned long) dev->mapbase;
-
spin_lock_init(&imxkeypad.lock);
init_timer(&imxkeypad.timer);
imxkeypad.timer.function = imxkeypad_timer_callback;
imxkeypad.timer.data = (unsigned long) &imxkeypad;
-
- imxkeypad.input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ strcpy(imxkeypad.phys, "imxkeypad/input0");
- init_input_dev(&imxkeypad.input);
- imxkeypad.input.keycode = imxkeypad.keycode;
- imxkeypad.input.keycodesize = sizeof(unsigned char);
- imxkeypad.input.keycodemax = ARRAY_SIZE(imxkeypad_keycode);
- imxkeypad.input.private = &imxkeypad;
+ imxkeypad.input = input_allocate_device();
+ if (!imxkeypad.input) {
+ printk(KERN_ERR "imxkeypad: Can't allocate device structure\n");
+ goto out;
+ }
+ imxkeypad.input->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+
+ imxkeypad.input->keycode = imxkeypad.keycode;
+ imxkeypad.input->keycodesize = sizeof(unsigned char);
+ imxkeypad.input->keycodemax = ARRAY_SIZE(imxkeypad_keycode);
+ imxkeypad.input->private = &imxkeypad;
+ imxkeypad.input->name = "imxkeypad";
+ imxkeypad.input->phys = imxkeypad.phys;
+ imxkeypad.input->id.bustype = BUS_HOST;
+ imxkeypad.input->id.vendor = 0x0001;
+ imxkeypad.input->id.product = 0x0001;
+ imxkeypad.input->id.version = 0x0100;
+
+
+
+ printk(KERN_DEBUG "imxkeypad matrix size: %ld rows, %ld cols\n", size[0], size[1]);
+ imxkeypad.num_rows = size[0];
+ imxkeypad.num_cols = size[1];
+
+ printk(KERN_DEBUG "imxkeypad bit_offset : rows %ld bits, cols %ld bits\n", bit_offset[0], bit_offset[1]);
+ imxkeypad.rows_offset = bit_offset[0];
+ imxkeypad.cols_offset = bit_offset[1];
+
+ printk(KERN_DEBUG "imxkeypad GPIO port: %d\n", io_port);
+ imxkeypad.port = io_port;
+
+ /* init keycode table */
memcpy(imxkeypad.keycode, imxkeypad_keycode, sizeof(imxkeypad.keycode));
- for (i = 0; i < IMXKEYPAD_NUMKEYS; i++)
- set_bit(imxkeypad.keycode[i], imxkeypad.input.keybit);
- clear_bit(0, imxkeypad.input.keybit);
+ for (i = 0; i < (imxkeypad.num_cols*imxkeypad.num_rows); i++)
+ set_bit(imxkeypad.keycode[i], imxkeypad.input->keybit);
+ clear_bit(0, imxkeypad.input->keybit);
- imxkeypad.input.name = "imxkeypad";
- imxkeypad.input.phys = imxkeypad.phys;
- imxkeypad.input.id.bustype = BUS_HOST;
- //imxkeypad.input.id.vendor = 0x0001;
- //imxkeypad.input.id.product = 0x0001;
- //imxkeypad.input.id.version = 0x0100;
+ /* init each gpios row pin as an input with pullup */
+ for (i = 0; i < imxkeypad.num_rows; i++) {
+ imx_gpio_mode( (imxkeypad.port<<GPIO_PORT_SHIFT)
+ | GPIO_GIUS | GPIO_IN | GPIO_PUEN
+ | (imxkeypad.rows_offset + i) );
+ }
+ /* init each gpios column pin as an output */
+ for (i = 0; i < imxkeypad.num_cols; i++) {
+ imx_gpio_mode( (imxkeypad.port<<GPIO_PORT_SHIFT)
+ | GPIO_GIUS | GPIO_OUT | GPIO_DR
+ | (imxkeypad.cols_offset + i) );
+
+ }
+ /* Activate every column to detect any key pressed */
+ imxkeypad_activate_all(&imxkeypad);
+ input_register_device(imxkeypad.input);
+
/* attempt to get the interrupts */
- for (i = 0; i < num_irq; i++) {
- //imxkeypad.irq[i] = IRQ_GPIOA(i+KPD_ROWS_BIT_OFFSET);
- printk(KERN_ERR "imxkeypad: requesting irq %d\n", irq[i]);
- ret = request_irq(irq[i], imxkeypad_interrupt, 0, "imxkeypad", &imxkeypad);
+ for (i = 0; i < imxkeypad.num_rows; i++) {
+ imxkeypad.irqs[i] = IMX_IRQS + 32*imxkeypad.port + imxkeypad.rows_offset + i;
+ printk(KERN_DEBUG "imxkeypad: requesting irq %d\n", imxkeypad.irqs[i]);
+ ret = request_irq(imxkeypad.irqs[i], imxkeypad_interrupt, 0, "imxkeypad", &imxkeypad);
if (ret) {
printk(KERN_ERR "imxkeypad: Can't get irq for keyboard\n");
- goto out;
+ goto free;
}
+ else set_irq_type( imxkeypad.irqs[i], IRQF_TRIGGER_FALLING );
}
- printk(KERN_ERR "imxkeypad io_addr ctrl: %lx, status: %lx\n", io_addr[0], io_addr[1]);
-
- printk(KERN_ERR "imxkeypad matrix size: %ld rows, %ld cols\n", size[0], size[1]);
- printk(KERN_ERR "imxkeypad bit_offset : rows %ld bits, cols %ld bits\n", bit_offset[0], bit_offset[1]);
-
- input_register_device(&imxkeypad.input);
-
- imxkeypad_activate_all(0);
-
- //mod_timer(&imxkeypad.timer, jiffies + SCAN_INTERVAL);
-
- printk(KERN_INFO "input: Armadeus keypad on imxkeypad\n");
-
return 0;
+free:
+ input_unregister_device(imxkeypad.input);
out:
-// release_mem_region((unsigned long) dev->mapbase, dev->length);
-//free:
-// kfree(imxkeypad);
-
-
return 0;
-
}
static void __exit imxkeypad_exit(void)
{
int i;
-// driver_unregister(&keyboard_driver.drv);
- for (i = 0; i < num_irq; i++) {
- free_irq(irq[i], &imxkeypad);
+ for (i = 0; i < imxkeypad.num_rows; i++) {
+ free_irq(imxkeypad.irqs[i], &imxkeypad);
}
del_timer_sync(&imxkeypad.timer);
- input_unregister_device(&imxkeypad.input);
-
-// release_mem_region((unsigned long) dev->mapbase, dev->length);
-
-// kfree(imxkeypad);
-
- printk(KERN_INFO "input: Armadeus keypad terminated\n");
-
-
+ input_unregister_device(imxkeypad.input);
}
module_init(imxkeypad_init);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|