|
From: <hap...@us...> - 2007-09-17 15:42:09
|
Revision: 1328
http://hackndev.svn.sourceforge.net/hackndev/?rev=1328&view=rev
Author: happy-slapin
Date: 2007-09-17 08:37:25 -0700 (Mon, 17 Sep 2007)
Log Message:
-----------
cleanup: update from hh.org
Added Paths:
-----------
linux4palm/linux/branches/cleanup-branch-never-commit/drivers/input/keyboard/gpiodev_keys2.c
linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/gpiodev_keys2.h
linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/mfd/htc-bbkeys.h
Removed Paths:
-------------
linux4palm/linux/branches/cleanup-branch-never-commit/include/asm-arm/arch-pxa/i2c-pxa.h
Added: linux4palm/linux/branches/cleanup-branch-never-commit/drivers/input/keyboard/gpiodev_keys2.c
===================================================================
--- linux4palm/linux/branches/cleanup-branch-never-commit/drivers/input/keyboard/gpiodev_keys2.c (rev 0)
+++ linux4palm/linux/branches/cleanup-branch-never-commit/drivers/input/keyboard/gpiodev_keys2.c 2007-09-17 15:37:25 UTC (rev 1328)
@@ -0,0 +1,336 @@
+/*
+ * Driver for diagonal joypads on GPIO lines capable of generating interrupts.
+ *
+ * Copyright 2007 Milan Plzik, based on gpio-keys.c (c) Phil Blundell 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/sort.h>
+#include <linux/gpiodev.h>
+#include <linux/gpiodev_keys2.h>
+
+struct gpiodev_keys2_drvdata {
+ struct input_dev *input;
+ struct timer_list debounce_timer;
+ struct gpiodev_keys2_gpio ***button_gpios;
+ int *gpio_delays;
+ struct gpiodev_keys2_button **buttons_by_prio;
+ int *gpio_used_prio;
+};
+
+
+static struct gpiodev_keys2_gpio *lookup_gpio (struct gpiodev_keys2_platform_data *pdata,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < pdata->ngpios; i++) {
+ if (!strcmp (name, pdata->gpios[i].name))
+ return &pdata->gpios[i];
+ }
+
+ return NULL;
+}
+
+static int count_gpios (struct gpiodev_keys2_button *btn)
+{
+ int i = 0;
+ const char **gpio = btn->gpio_names;
+
+ while (gpio[i]) i++;
+
+ return i;
+}
+
+
+static irqreturn_t gpiodev_keys2_isr(int irq, void *data)
+{
+ int i;
+ struct platform_device *pdev = data;
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ struct gpiodev_keys2_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ /* Find out which GPIO has been asserted and the corresponding delay for
+ * debouncing. */
+ for (i = 0; i < pdata->ngpios; i++)
+ if (irq == gpiodev_to_irq(&pdata->gpios[i].gpio)) {
+ break;
+ };
+
+ /* Prepare delayed call of debounce handler */
+ if (time_before(drvdata->debounce_timer.expires, jiffies +
+ msecs_to_jiffies(drvdata->gpio_delays[i])) ||
+ !timer_pending(&drvdata->debounce_timer))
+ mod_timer(&drvdata->debounce_timer,
+ jiffies + msecs_to_jiffies(drvdata->gpio_delays[i]));
+
+ return IRQ_HANDLED;
+}
+
+static void debounce_handler(unsigned long data)
+{
+ struct platform_device *pdev = (void*)data;
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ struct gpiodev_keys2_drvdata *drvdata = platform_get_drvdata(pdev);
+ struct gpiodev_keys2_button *button;
+ struct gpiodev_keys2_gpio **gpio;
+ int i;
+
+ memset(drvdata->gpio_used_prio, 0, sizeof(drvdata->gpio_used_prio[0])*pdata->ngpios);
+
+ /* Clear reported buttons */
+ for (i = 0; i < pdata->nbuttons; i++)
+ input_report_key(drvdata->input, pdata->buttons[i].keycode, 0);
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ int button_idx = drvdata->buttons_by_prio[i] - &pdata->buttons[0];
+ button = drvdata->buttons_by_prio[i];
+ gpio = drvdata->button_gpios[button_idx];
+
+ /* are all required GPIOs asserted? */
+ do {
+ int gpio_idx = gpio[0] - pdata->gpios; /* index in pdata->gpios */
+ if (((gpiodev_get_value(&gpio[0]->gpio) ? 1 : 0) ^ (gpio[0]->active_low)) &&
+ /* this is only true when gpio prio is 0,
+ * because the buttons are ordered descending by
+ * priority */
+ drvdata->gpio_used_prio[gpio_idx]<=button->priority)
+ continue;
+ else
+ break;
+ } while ((++gpio)[0] != NULL);
+
+ if (gpio[0] == NULL) {
+ /* all gpios are asserted and unused otherwise, so key
+ * can be pressed and GPIOs will be marked as used. */
+ gpio = drvdata->button_gpios[button_idx];
+ do {
+ int gpio_idx = gpio[0] - pdata->gpios;
+ drvdata->gpio_used_prio[gpio_idx] = button->priority;
+ } while (((++gpio)[0]) != NULL);
+ if (button->keycode != -1)
+ input_report_key(drvdata->input, button->keycode, 1);
+ }
+ };
+ input_sync(drvdata->input);
+}
+
+
+static int btnprio_cmp (const void *a, const void *b)
+{
+ const struct gpiodev_keys2_button *b1, *b2;
+
+ b1 = *((const struct gpiodev_keys2_button**)a);
+ b2 = *((const struct gpiodev_keys2_button**)b);
+
+ return b2->priority - b1->priority;
+}
+
+/* Builds array, which on i-th position contains pointers to all GPIOs used by
+ * i-th button in pdata->buttons, and also finds maximal debounce time for each
+ * gpio.
+ */
+
+static int gpiodev_keys2_init_drvdata(struct platform_device *pdev)
+{
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ struct gpiodev_keys2_drvdata *drvdata = platform_get_drvdata(pdev);
+ struct gpiodev_keys2_gpio *gpio;
+ int i, j;
+ int button_gpios;
+
+ if (drvdata->button_gpios) {
+ printk (KERN_ERR "gpiodev-keys2: Attempting to re-create drvdata\n");
+ return -EBUSY;
+ };
+
+ drvdata->button_gpios = kzalloc(
+ pdata->nbuttons*sizeof(*drvdata->button_gpios),
+ GFP_KERNEL);
+ drvdata->gpio_delays = kzalloc(pdata->ngpios*sizeof(*drvdata->gpio_delays), GFP_KERNEL);
+ drvdata->buttons_by_prio = kzalloc(pdata->nbuttons*sizeof(*drvdata->buttons_by_prio), GFP_KERNEL);
+ drvdata->gpio_used_prio = kzalloc(pdata->ngpios*sizeof(*drvdata->gpio_used_prio), GFP_KERNEL);
+
+ for (i = 0; i < pdata->nbuttons; i++) {
+ button_gpios = count_gpios(&pdata->buttons[i]);
+ drvdata->button_gpios[i] = kzalloc((button_gpios+1)*sizeof(drvdata->button_gpios[i]), GFP_KERNEL);
+
+ /* Put all GPIOs used by i-th button into button_gpios[i] */
+ for (j = 0; j < button_gpios; j++) {
+ gpio = lookup_gpio(pdata, pdata->buttons[i].gpio_names[j]);
+ if (!gpio) {
+ printk(KERN_WARNING "gpiodev-keys2: Unknown gpio '%s'\n", pdata->buttons[i].gpio_names[j]);
+ continue;
+ };
+
+ /* See whether actual button has delay, which is bigger
+ * than delay GPIO. If so, update GPIOs delay.
+ */
+ drvdata->gpio_delays[gpio - pdata->gpios] = max(
+ drvdata->gpio_delays[gpio - pdata->gpios],
+ pdata->buttons[i].debounce_ms);
+
+ drvdata->button_gpios[i][j] = gpio;
+ };
+
+
+ };
+
+ /* Create list of buttons sorted descending by priority */
+ for (i = 0; i < pdata->nbuttons; i++)
+ drvdata->buttons_by_prio[i] = &pdata->buttons[i];
+
+ sort(drvdata->buttons_by_prio, pdata->nbuttons, sizeof(drvdata->buttons_by_prio[0]), btnprio_cmp, NULL);
+ for (i = 0; i <pdata->nbuttons; i++)
+ printk (KERN_INFO "- button '%s', prio %d\n", drvdata->buttons_by_prio[i]->gpio_names[0], drvdata->buttons_by_prio[i]->priority);
+
+ return 0;
+}
+
+static void gpiodev_keys2_free_mapping(struct platform_device *pdev)
+{
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ struct gpiodev_keys2_drvdata *drvdata = platform_get_drvdata(pdev);
+ int i;
+
+ if (!drvdata)
+ return;
+
+ for (i = 0; i < pdata->nbuttons; i++)
+ kfree(drvdata->button_gpios[i]);
+
+ kfree(drvdata->button_gpios);
+ kfree(drvdata->gpio_delays);
+ kfree(drvdata->buttons_by_prio);
+ kfree(drvdata->gpio_used_prio);
+}
+
+
+static int __devinit gpiodev_keys2_probe(struct platform_device *pdev)
+{
+ struct gpiodev_keys2_drvdata *drvdata;
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input;
+ int i, error;
+
+ input = input_allocate_device();
+ if (!input)
+ return -ENOMEM;
+
+ input->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ input->name = pdev->name;
+ input->phys = "gpiodev-keys2/input0";
+ input->cdev.dev = &pdev->dev;
+ // input->private // do we need this?
+ input->id.bustype = BUS_HOST;
+ input->id.vendor = 0x0001;
+ input->id.product = 0x0001;
+ input->id.version = 0x0100;
+
+ drvdata = kzalloc(sizeof(struct gpiodev_keys2_drvdata), GFP_KERNEL);
+ drvdata->input = input;
+ platform_set_drvdata(pdev, drvdata);
+
+ setup_timer(&drvdata->debounce_timer, debounce_handler, (unsigned long) pdev);
+
+ for (i = 0; i < pdata->nbuttons; i++)
+ set_bit(pdata->buttons[i].keycode, input->keybit);
+
+ error = input_register_device(input);
+ if (error) {
+ printk(KERN_ERR "Unable to register gpiodev-keys2 input device\n");
+ goto fail;
+ }
+
+ gpiodev_keys2_init_drvdata(pdev);
+
+
+ for (i = 0; i < pdata->ngpios; i++) {
+ int irq = gpiodev_to_irq(&(pdata->gpios[i].gpio));
+
+ set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+ error = request_irq(irq, gpiodev_keys2_isr,
+ IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+ pdata->gpios[i].name ?
+ pdata->gpios[i].name : "gpiodev_keys2", pdev);
+
+ if (error) {
+ printk(KERN_ERR "gpiodev-keys: unable to claim irq %d; error %d\n", irq, error);
+ goto fail;
+ }
+ }
+
+
+ return 0;
+
+fail:
+ for (i = i - 1; i >= 0; i--)
+ free_irq(gpiodev_to_irq(&pdata->gpios[i].gpio),pdev);
+
+ input_free_device(input);
+
+ del_timer_sync(&drvdata->debounce_timer);
+
+ return error;
+}
+
+static int __devexit gpiodev_keys2_remove(struct platform_device *pdev)
+{
+ struct gpiodev_keys2_drvdata *drvdata = platform_get_drvdata(pdev);
+ struct gpiodev_keys2_platform_data *pdata = pdev->dev.platform_data;
+ int i;
+
+ del_timer_sync(&drvdata->debounce_timer);
+
+ for (i = 0; i < pdata->ngpios; i++)
+ free_irq(gpiodev_to_irq(&pdata->gpios[i].gpio), pdev);
+
+ input_unregister_device(drvdata->input);
+ input_free_device(drvdata->input);
+ gpiodev_keys2_free_mapping(pdev);
+ kfree(drvdata);
+
+ return 0;
+}
+
+
+struct platform_driver gpiodev_keys2_device_driver = {
+ .probe = gpiodev_keys2_probe,
+ .remove = __devexit_p(gpiodev_keys2_remove),
+ .driver = {
+ .name = "gpiodev-keys2",
+ }
+};
+
+static int __init gpiodev_keys2_init(void)
+{
+ return platform_driver_register(&gpiodev_keys2_device_driver);
+}
+
+static void __exit gpiodev_keys2_exit(void)
+{
+ platform_driver_unregister(&gpiodev_keys2_device_driver);
+}
+
+module_init(gpiodev_keys2_init);
+module_exit(gpiodev_keys2_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Milan Plzik <mil...@gm...>");
+MODULE_DESCRIPTION("Keyboard driver for GPIO");
Deleted: linux4palm/linux/branches/cleanup-branch-never-commit/include/asm-arm/arch-pxa/i2c-pxa.h
===================================================================
--- linux4palm/linux/branches/cleanup-branch-never-commit/include/asm-arm/arch-pxa/i2c-pxa.h 2007-09-17 15:12:45 UTC (rev 1327)
+++ linux4palm/linux/branches/cleanup-branch-never-commit/include/asm-arm/arch-pxa/i2c-pxa.h 2007-09-17 15:37:25 UTC (rev 1328)
@@ -1,76 +0,0 @@
-/*
- * i2c_pxa.h
- *
- * Copyright (C) 2002 Intrinsyc Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#ifndef _I2C_PXA_H_
-#define _I2C_PXA_H_
-
-struct i2c_algo_pxa_data
-{
- void (*write_byte) (u8 value);
- u8 (*read_byte) (void);
- void (*start) (void);
- void (*repeat_start) (void);
- void (*stop) (void);
- void (*abort) (void);
- int (*wait_bus_not_busy) (void);
- int (*wait_for_interrupt) (int wait_type);
- void (*transfer) (int lastbyte, int receive, int midbyte);
- void (*reset) (void);
-
- int udelay;
- int timeout;
-};
-
-#define DEF_TIMEOUT 3
-#define BUS_ERROR (-EREMOTEIO)
-#define ACK_DELAY 0 /* time to delay before checking bus error */
-#define MAX_MESSAGES 65536 /* maximum number of messages to send */
-
-#define I2C_SLEEP_TIMEOUT 2 /* time to sleep for on i2c transactions */
-#define I2C_RETRY (-2000) /* an error has occurred retry transmit */
-#define I2C_TRANSMIT 1
-#define I2C_RECEIVE 0
-#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */
-#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */
-/* ICR initialize bit values
-*
-* 15. FM 0 (100 Khz operation)
-* 14. UR 0 (No unit reset)
-* 13. SADIE 0 (Disables the unit from interrupting on slave addresses
-* matching its slave address)
-* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration
-* in master mode)
-* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode)
-* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent)
-* 9. IRFIE 1 (Enable interrupts from full buffer received)
-* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty)
-* 7. GCD 1 (Disables i2c unit response to general call messages as a slave)
-* 6. IUE 0 (Disable unit until we change settings)
-* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL)
-* 4. MA 0 (Only send stop with the ICR stop bit)
-* 3. TB 0 (We are not transmitting a byte initially)
-* 2. ACKNAK 0 (Send an ACK after the unit receives a byte)
-* 1. STOP 0 (Do not send a STOP)
-* 0. START 0 (Do not send a START)
-*
-*/
-
-#define I2C_ISR_INIT 0x7FF /* status register init */
-/* I2C status register init values
- *
- * 10. BED 1 (Clear bus error detected)
- * 9. SAD 1 (Clear slave address detected)
- * 7. IRF 1 (Clear IDBR Receive Full)
- * 6. ITE 1 (Clear IDBR Transmit Empty)
- * 5. ALD 1 (Clear Arbitration Loss Detected)
- * 4. SSD 1 (Clear Slave Stop Detected)
- */
-
-#endif
Added: linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/gpiodev_keys2.h
===================================================================
--- linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/gpiodev_keys2.h (rev 0)
+++ linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/gpiodev_keys2.h 2007-09-17 15:37:25 UTC (rev 1328)
@@ -0,0 +1,37 @@
+#ifndef __GPIODEV_KEYS2_H
+#define __GPIODEV_KEYS2_H
+
+#include <linux/gpiodev.h>
+
+#define MAX_GPIOS_PER_BUTTON 5
+
+struct gpiodev_keys2_gpio {
+ const char *name; /* GPIO identifier */
+ struct gpio gpio; /* gpiodev descriptor */
+ int active_low;
+};
+
+struct gpiodev_keys2_button {
+ int keycode; /* key code for the button */
+
+ const char *gpio_names[MAX_GPIOS_PER_BUTTON];
+ /* which GPIOs have to be asserted in order
+ * to emit keypress. This is NULL-terminated
+ * array of string GPIO identifiers */
+
+ int debounce_ms; /* Value for this button's debounce will be at
+ * least this number of milliseconds. */
+
+ int priority; /* If more buttons are likely to be pressed,
+ * only those with highest priority will
+ * generate keypress, others will be released */
+};
+
+struct gpiodev_keys2_platform_data {
+ struct gpiodev_keys2_gpio *gpios;
+ int ngpios;
+ struct gpiodev_keys2_button *buttons;
+ int nbuttons;
+};
+
+#endif
Added: linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/mfd/htc-bbkeys.h
===================================================================
--- linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/mfd/htc-bbkeys.h (rev 0)
+++ linux4palm/linux/branches/cleanup-branch-never-commit/include/linux/mfd/htc-bbkeys.h 2007-09-17 15:37:25 UTC (rev 1328)
@@ -0,0 +1,20 @@
+#ifndef _HTC_BBKEYS_H
+#define _HTC_BBKEYS_H
+
+/* Maximum number of keys available */
+enum { BBKEYS_MAXKEY = 16 };
+
+struct htc_bbkeys_platform_data {
+ /* Beginning of available gpios (eg, GPIO_BASE_INCREMENT) */
+ int gpio_base;
+
+ /* Main interface gpios */
+ int sda_gpio, scl_gpio;
+
+ /* Registers for working with keypad */
+ int ackreg, key1reg, key2reg;
+ /* Keycodes for buttons */
+ int buttons[BBKEYS_MAXKEY];
+};
+
+#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|