GIT 476572bbbf6f73f81004032e0c18d8aba85596f7 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/dtor/input.git commit Author: David Brownell Date: Mon Mar 5 01:02:21 2007 -0500 Input: gpio-keys - make available for non-ARM arches The gpio_keys driver is wrongly ARM-specific; it can't build on other platforms with GPIO suport. This fixes that problem. Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov commit ffd51f46cdf856c0b453d2828a74d552cc15f881 Author: Helge Deller Date: Wed Feb 28 23:51:29 2007 -0500 Input: HIL - cleanup coding style Signed-off-by: Helge Deller Signed-off-by: Dmitry Torokhov commit 3acaf540a33199141695f2e2fcfa8829053159bf Author: Helge Deller Date: Wed Feb 28 23:51:19 2007 -0500 Input: HIL - various fixes for HIL drivers - mark some structures const or __read_mostly - hilkbd.c: fix uninitialized spinlock in HIL keyboard driver - hil_mlc.c: use USEC_PER_SEC instead of 1000000 - hp_sdc: bugfix for request_irq()/free_irq() parameters, this prevented multiple load/unload cycles as module Signed-off-by: Helge Deller Signed-off-by: Dmitry Torokhov commit 969111e900226a8dbd1f596f34c09eecd20afc7d Author: Nicolas Ferre Date: Wed Feb 28 23:51:03 2007 -0500 Input: ads7846 - add support for the ads7843 touchscreen The ads7843 support has now become almost trivial since the last rework. Signed-off-by: Nicolas Ferre Acked-by: David Brownell Signed-off-by: Dmitry Torokhov commit bebb8a2bc180a4c920c57e89b2d713a34c1d096c Author: Yoichi Yuasa Date: Sun Feb 18 01:50:18 2007 -0500 Input: add driver for MIPS Cobalt back panel buttons Tested on Cobalt Qube2. Signed-off-by: Yoichi Yuasa Signed-off-by: Dmitry Torokhov commit 24bf10ab2d72863a14187905fd992ca8119c809e Author: Stefan Lucke Date: Sun Feb 18 01:49:10 2007 -0500 Input: psmouse - add support for eGalax PS/2 touchscreen controller Based on the touchkit USB and lifebook PS/2 touchscreen driver. The egalax touchsreen controller (PS/2 or USB version) is used in this 7" device: http://www.cartft.com/catalog/il/449 Signed-off-by: Michal Piotrowski Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov drivers/input/keyboard/hil_kbd.c | 85 +++--- drivers/input/keyboard/hilkbd.c | 5 drivers/input/misc/Kconfig | 11 + drivers/input/misc/Makefile | 1 drivers/input/misc/cobalt_btns.c | 209 +++++++++++++++ drivers/input/mouse/Makefile | 3 drivers/input/mouse/hil_ptr.c | 93 +++--- drivers/input/mouse/psmouse-base.c | 25 +- drivers/input/mouse/psmouse.h | 1 drivers/input/mouse/touchkit_ps2.c | 100 +++++++ drivers/input/mouse/touchkit_ps2.h | 17 + drivers/input/serio/hil_mlc.c | 503 +++++++++++++++++++---------------- drivers/input/serio/hp_sdc.c | 407 ++++++++++++++++------------ drivers/input/serio/hp_sdc_mlc.c | 226 ++++++++-------- drivers/input/touchscreen/ads7846.c | 28 +- 15 files changed, 1098 insertions(+), 616 deletions(-) diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 7cc9728..18f4d41 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -51,7 +51,7 @@ #define HIL_KBD_MAX_LENGTH 16 #define HIL_KBD_SET1_UPBIT 0x01 #define HIL_KBD_SET1_SHIFT 1 -static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = +static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET1 }; #define HIL_KBD_SET2_UPBIT 0x01 @@ -60,10 +60,10 @@ #define HIL_KBD_SET2_SHIFT 1 #define HIL_KBD_SET3_UPBIT 0x80 #define HIL_KBD_SET3_SHIFT 0 -static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] = +static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET3 }; -static char hil_language[][16] = { HIL_LOCALE_MAP }; +static const char hil_language[][16] = { HIL_LOCALE_MAP }; struct hil_kbd { struct input_dev *dev; @@ -94,10 +94,12 @@ static void hil_kbd_process_record(struc idx = kbd->idx4/4; p = data[idx - 1]; - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) + goto report; /* Not a poll response. See if we are loading config records. */ switch (p & HIL_PKT_DATA_MASK) { @@ -107,27 +109,32 @@ static void hil_kbd_process_record(struc for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->idd[i] = 0; break; + case HIL_CMD_RSC: for (i = 0; i < idx; i++) kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->rsc[i] = 0; break; + case HIL_CMD_EXD: for (i = 0; i < idx; i++) kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH; i++) kbd->exd[i] = 0; break; + case HIL_CMD_RNM: for (i = 0; i < idx; i++) kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_KBD_MAX_LENGTH + 1; i++) kbd->rnm[i] = '\0'; break; + default: /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) + break; /* Anything else we'd like to know about. */ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); break; @@ -139,16 +146,19 @@ static void hil_kbd_process_record(struc switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { case HIL_POL_CHARTYPE_NONE: break; + case HIL_POL_CHARTYPE_ASCII: while (cnt < idx - 1) input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); break; + case HIL_POL_CHARTYPE_RSVD1: case HIL_POL_CHARTYPE_RSVD2: case HIL_POL_CHARTYPE_BINARY: while (cnt < idx - 1) input_report_key(dev, kbd->data[cnt++], 1); break; + case HIL_POL_CHARTYPE_SET1: while (cnt < idx - 1) { unsigned int key; @@ -161,6 +171,7 @@ static void hil_kbd_process_record(struc input_report_key(dev, key, !up); } break; + case HIL_POL_CHARTYPE_SET2: while (cnt < idx - 1) { unsigned int key; @@ -173,6 +184,7 @@ static void hil_kbd_process_record(struc input_report_key(dev, key, !up); } break; + case HIL_POL_CHARTYPE_SET3: while (cnt < idx - 1) { unsigned int key; @@ -191,42 +203,43 @@ static void hil_kbd_process_record(struc up(&kbd->sem); } -static void hil_kbd_process_err(struct hil_kbd *kbd) { +static void hil_kbd_process_err(struct hil_kbd *kbd) +{ printk(KERN_WARNING PREFIX "errored HIL packet\n"); kbd->idx4 = 0; up(&kbd->sem); } -static irqreturn_t hil_kbd_interrupt(struct serio *serio, - unsigned char data, unsigned int flags) +static irqreturn_t hil_kbd_interrupt(struct serio *serio, + unsigned char data, unsigned int flags) { struct hil_kbd *kbd; hil_packet packet; int idx; kbd = serio_get_drvdata(serio); - if (kbd == NULL) { - BUG(); - return IRQ_HANDLED; - } + BUG_ON(kbd == NULL); if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { hil_kbd_process_err(kbd); return IRQ_HANDLED; } idx = kbd->idx4/4; - if (!(kbd->idx4 % 4)) kbd->data[idx] = 0; + if (!(kbd->idx4 % 4)) + kbd->data[idx] = 0; packet = kbd->data[idx]; packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); kbd->data[idx] = packet; /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(kbd->idx4)) % 4) return IRQ_HANDLED; + if ((++(kbd->idx4)) % 4) + return IRQ_HANDLED; if ((packet & 0xffff0000) != HIL_ERR_INT) { hil_kbd_process_err(kbd); return IRQ_HANDLED; } - if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd); + if (packet & HIL_PKT_CMD) + hil_kbd_process_record(kbd); return IRQ_HANDLED; } @@ -235,10 +248,7 @@ static void hil_kbd_disconnect(struct se struct hil_kbd *kbd; kbd = serio_get_drvdata(serio); - if (kbd == NULL) { - BUG(); - return; - } + BUG_ON(kbd == NULL); serio_close(serio); input_unregister_device(kbd->dev); @@ -267,34 +277,34 @@ static int hil_kbd_connect(struct serio serio_set_drvdata(serio, kbd); kbd->serio = serio; - init_MUTEX_LOCKED(&(kbd->sem)); + init_MUTEX_LOCKED(&kbd->sem); /* Get device info. MLC driver supplies devid/status/etc. */ serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_IDD); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RSC); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RNM); - down(&(kbd->sem)); + down(&kbd->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EXD); - down(&(kbd->sem)); + down(&kbd->sem); - up(&(kbd->sem)); + up(&kbd->sem); did = kbd->idd[0]; idd = kbd->idd + 1; @@ -310,12 +320,11 @@ static int hil_kbd_connect(struct serio goto bail2; } - if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { + if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); goto bail2; } - kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; @@ -344,8 +353,8 @@ static int hil_kbd_connect(struct serio serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ - down(&(kbd->sem)); - up(&(kbd->sem)); + down(&kbd->sem); + up(&kbd->sem); return 0; bail2: @@ -368,26 +377,26 @@ static struct serio_device_id hil_kbd_id { 0 } }; -struct serio_driver hil_kbd_serio_drv = { +static struct serio_driver hil_kbd_serio_drv = { .driver = { .name = "hil_kbd", }, .description = "HP HIL keyboard driver", .id_table = hil_kbd_ids, - .connect = hil_kbd_connect, - .disconnect = hil_kbd_disconnect, - .interrupt = hil_kbd_interrupt + .connect = hil_kbd_connect, + .disconnect = hil_kbd_disconnect, + .interrupt = hil_kbd_interrupt }; static int __init hil_kbd_init(void) { return serio_register_driver(&hil_kbd_serio_drv); } - + static void __exit hil_kbd_exit(void) { serio_unregister_driver(&hil_kbd_serio_drv); } - + module_init(hil_kbd_init); module_exit(hil_kbd_exit); diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 4de4dc2..230f5db 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Philip Blundell * Copyright (C) 1999 Matthew Wilcox - * Copyright (C) 1999-2006 Helge Deller + * Copyright (C) 1999-2007 Helge Deller * * Very basic HP Human Interface Loop (HIL) driver. * This driver handles the keyboard on HP300 (m68k) and on some @@ -89,7 +89,7 @@ #define HIL_INTOFF 0x5D /* Turn off in #define HIL_READKBDSADR 0xF9 #define HIL_WRITEKBDSADR 0xE9 -static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = +static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly = { HIL_KEYCODES_SET1 }; /* HIL structure */ @@ -211,6 +211,7 @@ hil_keyb_init(void) return -ENODEV; /* already initialized */ } + spin_lock_init(&hil_dev.lock); hil_dev.dev = input_allocate_device(); if (!hil_dev.dev) return -ENOMEM; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 41b4258..5694115 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -40,6 +40,15 @@ config INPUT_M68K_BEEP tristate "M68k Beeper support" depends on M68K +config INPUT_COBALT_BTNS + tristate "Cobalt button interface" + depends on MIPS_COBALT + help + Say Y here if you want to support MIPS Cobalt button interface. + + To compile this driver as a module, choose M here: the + module will be called cobalt_btns. + config INPUT_WISTRON_BTNS tristate "x86 Wistron laptop button interface" depends on X86 && !X86_64 @@ -82,7 +91,7 @@ config INPUT_UINPUT module will be called uinput. config HP_SDC_RTC - tristate "HP SDC Real Time Clock" + tristate "HP SDC Real Time Clock" depends on GSC || HP300 select HP_SDC help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index e0a8d58..9f08f27 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcs obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o +obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c new file mode 100644 index 0000000..b14f49e --- /dev/null +++ b/drivers/input/misc/cobalt_btns.c @@ -0,0 +1,209 @@ +/* + * Cobalt button interface driver. + * + * Copyright (C) 2007 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +#define BUTTONS_POLL_INTERVAL 30 /* msec */ +#define BUTTONS_COUNT_THRESHOLD 3 +#define BUTTONS_STATUS_MASK 0xfe000000 + +struct buttons_dev { + struct input_dev *input; + void __iomem *reg; +}; + +struct buttons_map { + uint32_t mask; + int keycode; + int count; +}; + +static struct buttons_map buttons_map[] = { + { 0x02000000, KEY_RESTART, }, + { 0x04000000, KEY_LEFT, }, + { 0x08000000, KEY_UP, }, + { 0x10000000, KEY_DOWN, }, + { 0x20000000, KEY_RIGHT, }, + { 0x40000000, KEY_ENTER, }, + { 0x80000000, KEY_SELECT, }, +}; + +static struct resource cobalt_buttons_resource __initdata = { + .start = 0x1d000000, + .end = 0x1d000003, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device *cobalt_buttons_device; + +static struct timer_list buttons_timer; + +static void handle_buttons(unsigned long data) +{ + struct buttons_map *button = buttons_map; + struct buttons_dev *bdev; + uint32_t status; + int i; + + bdev = (struct buttons_dev *)data; + status = readl(bdev->reg); + status = ~status & BUTTONS_STATUS_MASK; + + for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { + if (status & button->mask) { + button->count++; + } else { + if (button->count >= BUTTONS_COUNT_THRESHOLD) { + input_report_key(bdev->input, button->keycode, 0); + input_sync(bdev->input); + } + button->count = 0; + } + + if (button->count == BUTTONS_COUNT_THRESHOLD) { + input_report_key(bdev->input, button->keycode, 1); + input_sync(bdev->input); + } + + button++; + } + + mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL)); +} + +static int cobalt_buttons_open(struct input_dev *dev) +{ + mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL)); + + return 0; +} + +static void cobalt_buttons_close(struct input_dev *dev) +{ + del_timer_sync(&buttons_timer); +} + +static int __devinit cobalt_buttons_probe(struct platform_device *pdev) +{ + struct buttons_dev *bdev; + struct input_dev *input; + struct resource *res; + int error, i; + + bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); + input = input_allocate_device(); + if (!bdev || !input) { + error = -ENOMEM; + goto err_free_mem; + } + + input->name = "Cobalt buttons"; + input->phys = "cobalt/input0"; + input->id.bustype = BUS_HOST; + input->cdev.dev = &pdev->dev; + input->open = cobalt_buttons_open; + input->close = cobalt_buttons_close; + + input->evbit[0] = BIT(EV_KEY); + for (i = 0; i < ARRAY_SIZE(buttons_map); i++) { + set_bit(buttons_map[i].keycode, input->keybit); + buttons_map[i].count = 0; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + error = -EBUSY; + goto err_free_mem; + } + + bdev->input = input; + bdev->reg = ioremap(res->start, res->end - res->start + 1); + dev_set_drvdata(&pdev->dev, bdev); + + setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev); + + error = input_register_device(input); + if (error) + goto err_iounmap; + + return 0; + + err_iounmap: + iounmap(bdev->reg); + err_free_mem: + input_free_device(input); + kfree(bdev); + dev_set_drvdata(&pdev->dev, NULL); + return error; +} + +static int __devexit cobalt_buttons_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct buttons_dev *bdev = dev_get_drvdata(dev); + + input_unregister_device(bdev->input); + iounmap(bdev->reg); + kfree(bdev); + dev_set_drvdata(dev, NULL); + + return 0; +} + +static struct platform_driver cobalt_buttons_driver = { + .probe = cobalt_buttons_probe, + .remove = __devexit_p(cobalt_buttons_remove), + .driver = { + .name = "Cobalt buttons", + .owner = THIS_MODULE, + }, +}; + +static int __init cobalt_buttons_init(void) +{ + int retval; + + cobalt_buttons_device = platform_device_register_simple("Cobalt buttons", -1, + &cobalt_buttons_resource, 1); + if (IS_ERR(cobalt_buttons_device)) { + retval = PTR_ERR(cobalt_buttons_device); + return retval; + } + + retval = platform_driver_register(&cobalt_buttons_driver); + if (retval < 0) + platform_device_unregister(cobalt_buttons_device); + + return retval; +} + +static void __exit cobalt_buttons_exit(void) +{ + platform_driver_unregister(&cobalt_buttons_driver); + platform_device_unregister(cobalt_buttons_device); +} + +module_init(cobalt_buttons_init); +module_exit(cobalt_buttons_exit); diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 21a1de6..6751179 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o +psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o \ + trackpoint.o touchkit_ps2.o diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index bfb174f..8e9421a 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -88,10 +88,12 @@ static void hil_ptr_process_record(struc idx = ptr->idx4/4; p = data[idx - 1]; - if ((p & ~HIL_CMDCT_POL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report; - if ((p & ~HIL_CMDCT_RPL) == - (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report; + if ((p & ~HIL_CMDCT_POL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + goto report; + if ((p & ~HIL_CMDCT_RPL) == + (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) + goto report; /* Not a poll response. See if we are loading config records. */ switch (p & HIL_PKT_DATA_MASK) { @@ -101,27 +103,32 @@ static void hil_ptr_process_record(struc for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->idd[i] = 0; break; + case HIL_CMD_RSC: for (i = 0; i < idx; i++) ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->rsc[i] = 0; break; + case HIL_CMD_EXD: for (i = 0; i < idx; i++) ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH; i++) ptr->exd[i] = 0; break; + case HIL_CMD_RNM: for (i = 0; i < idx; i++) ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; for (; i < HIL_PTR_MAX_LENGTH + 1; i++) - ptr->rnm[i] = '\0'; + ptr->rnm[i] = 0; break; + default: /* These occur when device isn't present */ - if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; + if (p == (HIL_ERR_INT | HIL_PKT_CMD)) + break; /* Anything else we'd like to know about. */ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); break; @@ -130,7 +137,8 @@ static void hil_ptr_process_record(struc report: if ((p & HIL_CMDCT_POL) != idx - 1) { - printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx); + printk(KERN_WARNING PREFIX + "Malformed poll packet %x (idx = %i)\n", p, idx); goto out; } @@ -139,7 +147,7 @@ static void hil_ptr_process_record(struc laxis += i; ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ - absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; + absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; for (cnt = 1; i < laxis; i++) { unsigned int lo,hi,val; @@ -157,7 +165,8 @@ #endif input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); - if (i%3) val *= -1; + if (i%3) + val *= -1; input_report_rel(dev, REL_X + i, val); } } @@ -168,10 +177,11 @@ #endif btn = ptr->data[cnt++]; up = btn & 1; btn &= 0xfe; - if (btn == 0x8e) { + if (btn == 0x8e) continue; /* TODO: proximity == touch? */ - } - else if ((btn > 0x8c) || (btn < 0x80)) continue; + else + if ((btn > 0x8c) || (btn < 0x80)) + continue; btn = (btn - 0x80) >> 1; btn = ptr->btnmap[btn]; input_report_key(dev, btn, !up); @@ -182,14 +192,14 @@ #endif up(&ptr->sem); } -static void hil_ptr_process_err(struct hil_ptr *ptr) { +static void hil_ptr_process_err(struct hil_ptr *ptr) +{ printk(KERN_WARNING PREFIX "errored HIL packet\n"); ptr->idx4 = 0; up(&ptr->sem); - return; } -static irqreturn_t hil_ptr_interrupt(struct serio *serio, +static irqreturn_t hil_ptr_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { struct hil_ptr *ptr; @@ -197,29 +207,29 @@ static irqreturn_t hil_ptr_interrupt(str int idx; ptr = serio_get_drvdata(serio); - if (ptr == NULL) { - BUG(); - return IRQ_HANDLED; - } + BUG_ON(ptr == NULL); if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { hil_ptr_process_err(ptr); return IRQ_HANDLED; } idx = ptr->idx4/4; - if (!(ptr->idx4 % 4)) ptr->data[idx] = 0; + if (!(ptr->idx4 % 4)) + ptr->data[idx] = 0; packet = ptr->data[idx]; packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); ptr->data[idx] = packet; /* Records of N 4-byte hil_packets must terminate with a command. */ - if ((++(ptr->idx4)) % 4) return IRQ_HANDLED; + if ((++(ptr->idx4)) % 4) + return IRQ_HANDLED; if ((packet & 0xffff0000) != HIL_ERR_INT) { hil_ptr_process_err(ptr); return IRQ_HANDLED; } - if (packet & HIL_PKT_CMD) + if (packet & HIL_PKT_CMD) hil_ptr_process_record(ptr); + return IRQ_HANDLED; } @@ -228,10 +238,7 @@ static void hil_ptr_disconnect(struct se struct hil_ptr *ptr; ptr = serio_get_drvdata(serio); - if (ptr == NULL) { - BUG(); - return; - } + BUG_ON(ptr == NULL); serio_close(serio); input_unregister_device(ptr->dev); @@ -241,7 +248,7 @@ static void hil_ptr_disconnect(struct se static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) { struct hil_ptr *ptr; - char *txt; + const char *txt; unsigned int i, naxsets, btntype; uint8_t did, *idd; @@ -260,34 +267,34 @@ static int hil_ptr_connect(struct serio serio_set_drvdata(serio, ptr); ptr->serio = serio; - init_MUTEX_LOCKED(&(ptr->sem)); + init_MUTEX_LOCKED(&ptr->sem); /* Get device info. MLC driver supplies devid/status/etc. */ serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_IDD); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RSC); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_RNM); - down(&(ptr->sem)); + down(&ptr->sem); serio->write(serio, 0); serio->write(serio, 0); serio->write(serio, HIL_PKT_CMD >> 8); serio->write(serio, HIL_CMD_EXD); - down(&(ptr->sem)); + down(&ptr->sem); - up(&(ptr->sem)); + up(&ptr->sem); did = ptr->idd[0]; idd = ptr->idd + 1; @@ -301,12 +308,12 @@ static int hil_ptr_connect(struct serio ptr->dev->evbit[0] = BIT(EV_ABS); txt = "absolute"; } - if (!ptr->dev->evbit[0]) { + if (!ptr->dev->evbit[0]) goto bail2; - } ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); - if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY); + if (ptr->nbtn) + ptr->dev->evbit[0] |= BIT(EV_KEY); naxsets = HIL_IDD_NUM_AXSETS(*idd); ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); @@ -315,7 +322,7 @@ static int hil_ptr_connect(struct serio did, txt); printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", ptr->nbtn, naxsets, ptr->naxes); - + btntype = BTN_MISC; if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) #ifdef TABLET_SIMULATES_MOUSE @@ -325,7 +332,7 @@ #else #endif if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) btntype = BTN_TOUCH; - + if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) btntype = BTN_MOUSE; @@ -341,12 +348,10 @@ #endif } if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - for (i = 0; i < ptr->naxes; i++) { + for (i = 0; i < ptr->naxes; i++) set_bit(REL_X + i, ptr->dev->relbit); - } - for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { + for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) set_bit(REL_X + i, ptr->dev->relbit); - } } else { for (i = 0; i < ptr->naxes; i++) { set_bit(ABS_X + i, ptr->dev->absbit); @@ -419,11 +424,11 @@ static int __init hil_ptr_init(void) { return serio_register_driver(&hil_ptr_serio_driver); } - + static void __exit hil_ptr_exit(void) { serio_unregister_driver(&hil_ptr_serio_driver); } - + module_init(hil_ptr_init); module_exit(hil_ptr_exit); diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 0fe5869..eb63855 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -28,6 +28,7 @@ #include "logips2pp.h" #include "alps.h" #include "lifebook.h" #include "trackpoint.h" +#include "touchkit_ps2.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -605,14 +606,20 @@ static int psmouse_extensions(struct psm } } - if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0) - return PSMOUSE_GENPS; + if (max_proto > PSMOUSE_IMEX) { + + if (genius_detect(psmouse, set_properties) == 0) + return PSMOUSE_GENPS; + + if (ps2pp_init(psmouse, set_properties) == 0) + return PSMOUSE_PS2PP; - if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0) - return PSMOUSE_PS2PP; + if (trackpoint_detect(psmouse, set_properties) == 0) + return PSMOUSE_TRACKPOINT; - if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0) - return PSMOUSE_TRACKPOINT; + if (touchkit_ps2_detect(psmouse, set_properties) == 0) + return PSMOUSE_TOUCHKIT_PS2; + } /* * Reset to defaults in case the device got confused by extended @@ -713,6 +720,12 @@ static const struct psmouse_protocol psm .detect = trackpoint_detect, }, { + .type = PSMOUSE_TOUCHKIT_PS2, + .name = "touchkitPS/2", + .alias = "touchkit", + .detect = touchkit_ps2_detect, + }, + { .type = PSMOUSE_AUTO, .name = "auto", .alias = "any", diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index cf1de95..3964e8a 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -87,6 +87,7 @@ enum psmouse_type { PSMOUSE_ALPS, PSMOUSE_LIFEBOOK, PSMOUSE_TRACKPOINT, + PSMOUSE_TOUCHKIT_PS2, PSMOUSE_AUTO /* This one should always be last */ }; diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c new file mode 100644 index 0000000..7b977fd --- /dev/null +++ b/drivers/input/mouse/touchkit_ps2.c @@ -0,0 +1,100 @@ +/* ---------------------------------------------------------------------------- + * touchkit_ps2.c -- Driver for eGalax TouchKit PS/2 Touchscreens + * + * Copyright (C) 2005 by Stefan Lucke + * Copyright (C) 2004 by Daniel Ritz + * Copyright (C) by Todd E. Johnson (mtouchusb.c) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based upon touchkitusb.c + * + * Vendor documentation is available in support section of: + * http://www.egalax.com.tw/ + */ + +#include +#include + +#include +#include +#include + +#include "psmouse.h" +#include "touchkit_ps2.h" + +#define TOUCHKIT_MAX_XC 0x07ff +#define TOUCHKIT_MAX_YC 0x07ff + +#define TOUCHKIT_CMD 0x0a +#define TOUCHKIT_CMD_LENGTH 1 + +#define TOUCHKIT_CMD_ACTIVE 'A' +#define TOUCHKIT_CMD_FIRMWARE_VERSION 'D' +#define TOUCHKIT_CMD_CONTROLLER_TYPE 'E' + +#define TOUCHKIT_SEND_PARMS(s, r, c) ((s) << 12 | (r) << 8 | (c)) + +#define TOUCHKIT_GET_TOUCHED(packet) (((packet)[0]) & 0x01) +#define TOUCHKIT_GET_X(packet) (((packet)[1] << 7) | (packet)[2]) +#define TOUCHKIT_GET_Y(packet) (((packet)[3] << 7) | (packet)[4]) + +static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) +{ + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + + if (psmouse->pktcnt != 5) + return PSMOUSE_GOOD_DATA; + + input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet)); + input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet)); + input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet)); + input_sync(dev); + + return PSMOUSE_FULL_PACKET; +} + +int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) +{ + struct input_dev *dev = psmouse->dev; + unsigned char param[3]; + int command; + + param[0] = TOUCHKIT_CMD_LENGTH; + param[1] = TOUCHKIT_CMD_ACTIVE; + command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD); + + if (ps2_command(&psmouse->ps2dev, param, command)) + return -ENODEV; + + if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 || + param[2] != TOUCHKIT_CMD_ACTIVE) + return -ENODEV; + + if (set_properties) { + dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + set_bit(BTN_TOUCH, dev->keybit); + input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); + input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); + + psmouse->vendor = "eGalax"; + psmouse->name = "Touchscreen"; + psmouse->protocol_handler = touchkit_ps2_process_byte; + psmouse->pktsize = 5; + } + + return 0; +} diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h new file mode 100644 index 0000000..3f03fbc --- /dev/null +++ b/drivers/input/mouse/touchkit_ps2.h @@ -0,0 +1,17 @@ +/* ---------------------------------------------------------------------------- + * touchkit_ps2.h -- Driver for eGalax TouchKit PS/2 Touchscreens + * + * Copyright (C) 2005 by Stefan Lucke + * Copyright (c) 2005 Vojtech Pavlik + * + * 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 _TOUCHKIT_PS2_H +#define _TOUCHKIT_PS2_H + +int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties); + +#endif diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 4fa93ff..485b074 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -32,11 +32,11 @@ * * Driver theory of operation: * - * Some access methods and an ISR is defined by the sub-driver - * (e.g. hp_sdc_mlc.c). These methods are expected to provide a - * few bits of logic in addition to raw access to the HIL MLC, - * specifically, the ISR, which is entirely registered by the - * sub-driver and invoked directly, must check for record + * Some access methods and an ISR is defined by the sub-driver + * (e.g. hp_sdc_mlc.c). These methods are expected to provide a + * few bits of logic in addition to raw access to the HIL MLC, + * specifically, the ISR, which is entirely registered by the + * sub-driver and invoked directly, must check for record * termination or packet match, at which point a semaphore must * be cleared and then the hil_mlcs_tasklet must be scheduled. * @@ -47,7 +47,7 @@ * itself if output is pending. (This rescheduling should be replaced * at some point with a sub-driver-specific mechanism.) * - * A timer task prods the tasklet once per second to prevent + * A timer task prods the tasklet once per second to prevent * hangups when attached devices do not return expected data * and to initiate probes of the loop for new devices. */ @@ -83,69 +83,85 @@ DECLARE_TASKLET_DISABLED(hil_mlcs_taskle /********************** Device info/instance management **********************/ -static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) { +static void hil_mlc_clear_di_map(hil_mlc *mlc, int val) +{ int j; - for (j = val; j < 7 ; j++) { + + for (j = val; j < 7 ; j++) mlc->di_map[j] = -1; - } } -static void hil_mlc_clear_di_scratch (hil_mlc *mlc) { - memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch)); +static void hil_mlc_clear_di_scratch(hil_mlc *mlc) +{ + memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch)); } -static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) { - memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch)); +static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx) +{ + memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch)); } -static int hil_mlc_match_di_scratch (hil_mlc *mlc) { +static int hil_mlc_match_di_scratch(hil_mlc *mlc) +{ int idx; for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; + int j, found = 0; /* In-use slots are not eligible. */ - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (found) continue; - if (!memcmp(mlc->di + idx, - &(mlc->di_scratch), - sizeof(mlc->di_scratch))) break; + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (found) + continue; + + if (!memcmp(mlc->di + idx, &mlc->di_scratch, + sizeof(mlc->di_scratch))) + break; } - return((idx >= HIL_MLC_DEVMEM) ? -1 : idx); + return idx >= HIL_MLC_DEVMEM ? -1 : idx; } -static int hil_mlc_find_free_di(hil_mlc *mlc) { +static int hil_mlc_find_free_di(hil_mlc *mlc) +{ int idx; - /* TODO: Pick all-zero slots first, failing that, - * randomize the slot picked among those eligible. + + /* TODO: Pick all-zero slots first, failing that, + * randomize the slot picked among those eligible. */ for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) break; + int j, found = 0; + + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (!found) + break; } - return(idx); /* Note: It is guaranteed at least one above will match */ + + return idx; /* Note: It is guaranteed at least one above will match */ } -static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) { +static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) +{ int idx; + for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) { - int j, found; - found = 0; - for (j = 0; j < 7 ; j++) { - if (mlc->di_map[j] == idx) found++; - } - if (!found) mlc->serio_map[idx].di_revmap = -1; + int j, found = 0; + + for (j = 0; j < 7 ; j++) + if (mlc->di_map[j] == idx) + found++; + + if (!found) + mlc->serio_map[idx].di_revmap = -1; } } -static void hil_mlc_send_polls(hil_mlc *mlc) { +static void hil_mlc_send_polls(hil_mlc *mlc) +{ int did, i, cnt; struct serio *serio; struct serio_driver *drv; @@ -157,26 +173,31 @@ static void hil_mlc_send_polls(hil_mlc * while (mlc->icount < 15 - i) { hil_packet p; + p = mlc->ipacket[i]; if (did != (p & HIL_PKT_ADDR_MASK) >> 8) { - if (drv == NULL || drv->interrupt == NULL) goto skip; + if (drv && drv->interrupt) { + drv->interrupt(serio, 0, 0); + drv->interrupt(serio, HIL_ERR_INT >> 16, 0); + drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); + drv->interrupt(serio, HIL_CMD_POL + cnt, 0); + } - drv->interrupt(serio, 0, 0); - drv->interrupt(serio, HIL_ERR_INT >> 16, 0); - drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); - drv->interrupt(serio, HIL_CMD_POL + cnt, 0); - skip: did = (p & HIL_PKT_ADDR_MASK) >> 8; serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL; drv = (serio != NULL) ? serio->drv : NULL; cnt = 0; } - cnt++; i++; - if (drv == NULL || drv->interrupt == NULL) continue; - drv->interrupt(serio, (p >> 24), 0); - drv->interrupt(serio, (p >> 16) & 0xff, 0); - drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0); - drv->interrupt(serio, p & 0xff, 0); + + cnt++; + i++; + + if (drv && drv->interrupt) { + drv->interrupt(serio, (p >> 24), 0); + drv->interrupt(serio, (p >> 16) & 0xff, 0); + drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0); + drv->interrupt(serio, p & 0xff, 0); + } } } @@ -215,12 +236,16 @@ #define HILSEN_LAST (HILSEN_UP | 1) #define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK) #define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK) -static int hilse_match(hil_mlc *mlc, int unused) { +static int hilse_match(hil_mlc *mlc, int unused) +{ int rc; + rc = hil_mlc_match_di_scratch(mlc); if (rc == -1) { rc = hil_mlc_find_free_di(mlc); - if (rc == -1) goto err; + if (rc == -1) + goto err; + #ifdef HIL_MLC_DEBUG printk(KERN_DEBUG PREFIX "new in slot %i\n", rc); #endif @@ -231,6 +256,7 @@ #endif serio_rescan(mlc->serio[rc]); return -1; } + mlc->di_map[mlc->ddi] = rc; #ifdef HIL_MLC_DEBUG printk(KERN_DEBUG PREFIX "same in slot %i\n", rc); @@ -238,152 +264,177 @@ #endif mlc->serio_map[rc].di_revmap = mlc->ddi; hil_mlc_clean_serio_map(mlc); return 0; + err: printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n"); return 1; } /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */ -static int hilse_init_lcv(hil_mlc *mlc, int unused) { +static int hilse_init_lcv(hil_mlc *mlc, int unused) +{ struct timeval tv; do_gettimeofday(&tv); - if(mlc->lcv == 0) goto restart; /* First init, no need to dally */ - if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1; - restart: + if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5) + return -1; + mlc->lcv_tv = tv; mlc->lcv = 0; + return 0; } -static int hilse_inc_lcv(hil_mlc *mlc, int lim) { - if (mlc->lcv++ >= lim) return -1; - return 0; +static int hilse_inc_lcv(hil_mlc *mlc, int lim) +{ + return mlc->lcv++ >= lim ? -1 : 0; } #if 0 -static int hilse_set_lcv(hil_mlc *mlc, int val) { +static int hilse_set_lcv(hil_mlc *mlc, int val) +{ mlc->lcv = val; + return 0; } #endif /* Management of the discovered device index (zero based, -1 means no devs) */ -static int hilse_set_ddi(hil_mlc *mlc, int val) { +static int hilse_set_ddi(hil_mlc *mlc, int val) +{ mlc->ddi = val; hil_mlc_clear_di_map(mlc, val + 1); + return 0; } -static int hilse_dec_ddi(hil_mlc *mlc, int unused) { +static int hilse_dec_ddi(hil_mlc *mlc, int unused) +{ mlc->ddi--; - if (mlc->ddi <= -1) { + if (mlc->ddi <= -1) { mlc->ddi = -1; hil_mlc_clear_di_map(mlc, 0); return -1; } hil_mlc_clear_di_map(mlc, mlc->ddi + 1); + return 0; } -static int hilse_inc_ddi(hil_mlc *mlc, int unused) { - if (mlc->ddi >= 6) { - BUG(); - return -1; - } +static int hilse_inc_ddi(hil_mlc *mlc, int unused) +{ + BUG_ON(mlc->ddi >= 6); mlc->ddi++; + return 0; } -static int hilse_take_idd(hil_mlc *mlc, int unused) { +static int hilse_take_idd(hil_mlc *mlc, int unused) +{ int i; - /* Help the state engine: - * Is this a real IDD response or just an echo? + /* Help the state engine: + * Is this a real IDD response or just an echo? * - * Real IDD response does not start with a command. + * Real IDD response does not start with a command. */ - if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail; + if (mlc->ipacket[0] & HIL_PKT_CMD) + goto bail; + /* Should have the command echoed further down. */ for (i = 1; i < 16; i++) { - if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == + if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) && - (mlc->ipacket[i] & HIL_PKT_CMD) && + (mlc->ipacket[i] & HIL_PKT_CMD) && ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD)) break; } - if (i > 15) goto bail; + if (i > 15) + goto bail; + /* And the rest of the packets should still be clear. */ - while (++i < 16) { - if (mlc->ipacket[i]) break; - } - if (i < 16) goto bail; - for (i = 0; i < 16; i++) { - mlc->di_scratch.idd[i] = + while (++i < 16) + if (mlc->ipacket[i]) + break; + + if (i < 16) + goto bail; + + for (i = 0; i < 16; i++) + mlc->di_scratch.idd[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if RSC supported */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) return HILSEN_NEXT; - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) return HILSEN_DOWN | 4; + return 0; + bail: mlc->ddi--; + return -1; /* This should send us off to ACF */ } -static int hilse_take_rsc(hil_mlc *mlc, int unused) { +static int hilse_take_rsc(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.rsc[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.rsc[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if EXD supported (IDD has already been read) */ - if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) + if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) return HILSEN_NEXT; + return 0; } -static int hilse_take_exd(hil_mlc *mlc, int unused) { +static int hilse_take_exd(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.exd[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.exd[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } + /* Next step is to see if RNM supported. */ - if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) + if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) return HILSEN_NEXT; + return 0; } -static int hilse_take_rnm(hil_mlc *mlc, int unused) { +static int hilse_take_rnm(hil_mlc *mlc, int unused) +{ int i; - for (i = 0; i < 16; i++) { - mlc->di_scratch.rnm[i] = + for (i = 0; i < 16; i++) + mlc->di_scratch.rnm[i] = mlc->ipacket[i] & HIL_PKT_DATA_MASK; - } - do { - char nam[17]; - snprintf(nam, 16, "%s", mlc->di_scratch.rnm); - nam[16] = '\0'; - printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam); - } while (0); + + printk(KERN_INFO PREFIX "Device name gotten: %16s\n", + mlc->di_scratch.rnm); + return 0; } -static int hilse_operate(hil_mlc *mlc, int repoll) { +static int hilse_operate(hil_mlc *mlc, int repoll) +{ - if (mlc->opercnt == 0) hil_mlcs_probe = 0; + if (mlc->opercnt == 0) + hil_mlcs_probe = 0; mlc->opercnt = 1; hil_mlc_send_polls(mlc); - if (!hil_mlcs_probe) return 0; + if (!hil_mlcs_probe) + return 0; hil_mlcs_probe = 0; mlc->opercnt = 0; return 1; @@ -408,7 +459,7 @@ #define OUT_DISC(pack) \ #define OUT_LAST(pack) \ { HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 }, -struct hilse_node hil_mlc_se[HILSEN_END] = { +const struct hilse_node hil_mlc_se[HILSEN_END] = { /* 0 HILSEN_START */ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) @@ -428,7 +479,7 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) EXPECT(HIL_ERR_INT | TEST_PACKET(0xa), 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART) OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */ - + /* 9 HILSEN_DHR */ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0) @@ -439,7 +490,7 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT) /* 14 HILSEN_IFC */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) + OUT(HIL_PKT_CMD | HIL_CMD_IFC) EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT ) @@ -455,7 +506,7 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) /* 18 HILSEN_HEAL */ OUT_LAST(HIL_CMD_ELB) - EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, + EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT) FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0) @@ -503,7 +554,7 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) /* 44 HILSEN_PROBE */ OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT) - IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) + IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB) IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT) OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1) @@ -514,7 +565,7 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) /* 52 HILSEN_DSR */ FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0) OUT(HIL_PKT_CMD | HIL_CMD_DSR) - IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) + IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC) /* 55 HILSEN_REPOLL */ OUT(HIL_PKT_CMD | HIL_CMD_RPL) @@ -523,14 +574,15 @@ (HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE) /* 58 HILSEN_IFCACF */ - OUT(HIL_PKT_CMD | HIL_CMD_IFC) + OUT(HIL_PKT_CMD | HIL_CMD_IFC) EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT, 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL) /* 60 HILSEN_END */ }; -static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) { +static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node) +{ switch (node->act) { case HILSE_EXPECT_DISC: @@ -555,29 +607,27 @@ static inline void hilse_setup_input(hil do_gettimeofday(&(mlc->instart)); mlc->icount = 15; memset(mlc->ipacket, 0, 16 * sizeof(hil_packet)); - BUG_ON(down_trylock(&(mlc->isem))); - - return; + BUG_ON(down_trylock(&mlc->isem)); } #ifdef HIL_MLC_DEBUG -static int doze = 0; +static int doze; static int seidx; /* For debug */ -static int kick = 1; #endif -static int hilse_donode (hil_mlc *mlc) { - struct hilse_node *node; +static int hilse_donode(hil_mlc *mlc) +{ + const struct hilse_node *node; int nextidx = 0; int sched_long = 0; unsigned long flags; #ifdef HIL_MLC_DEBUG - if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { - printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx); + if (mlc->seidx && mlc->seidx != seidx && + mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) { + printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx); doze = 0; } - kick = 0; seidx = mlc->seidx; #endif @@ -588,52 +638,61 @@ #endif hil_packet pack; case HILSE_FUNC: - if (node->object.func == NULL) break; + BUG_ON(node->object.func == NULL); rc = node->object.func(mlc, node->arg); - nextidx = (rc > 0) ? node->ugly : + nextidx = (rc > 0) ? node->ugly : ((rc < 0) ? node->bad : node->good); - if (nextidx == HILSEN_FOLLOW) nextidx = rc; + if (nextidx == HILSEN_FOLLOW) + nextidx = rc; break; + case HILSE_EXPECT_LAST: case HILSE_EXPECT_DISC: case HILSE_EXPECT: case HILSE_IN: /* Already set up from previous HILSE_OUT_* */ - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); rc = mlc->in(mlc, node->arg); if (rc == 2) { nextidx = HILSEN_DOZE; sched_long = 1; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; } - if (rc == 1) nextidx = node->ugly; - else if (rc == 0) nextidx = node->good; - else nextidx = node->bad; + if (rc == 1) + nextidx = node->ugly; + else if (rc == 0) + nextidx = node->good; + else + nextidx = node->bad; mlc->istarted = 0; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; + case HILSE_OUT_LAST: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT); goto out; + case HILSE_OUT_DISC: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT); goto out; + case HILSE_OUT: - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; out: - if (mlc->istarted) goto out2; + if (mlc->istarted) + goto out2; /* Prepare to receive input */ if ((node + 1)->act & HILSE_IN) hilse_setup_input(mlc, node + 1); out2: - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); if (down_trylock(&mlc->osem)) { nextidx = HILSEN_DOZE; @@ -641,60 +700,69 @@ #endif } up(&mlc->osem); - write_lock_irqsave(&(mlc->lock), flags); - if (!(mlc->ostarted)) { + write_lock_irqsave(&mlc->lock, flags); + if (!mlc->ostarted) { mlc->ostarted = 1; mlc->opacket = pack; mlc->out(mlc); nextidx = HILSEN_DOZE; - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); break; } mlc->ostarted = 0; do_gettimeofday(&(mlc->instart)); - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); nextidx = HILSEN_NEXT; break; + case HILSE_CTS: nextidx = mlc->cts(mlc) ? node->bad : node->good; break; + default: BUG(); - nextidx = 0; - break; } #ifdef HIL_MLC_DEBUG - if (nextidx == HILSEN_DOZE) doze++; + if (nextidx == HILSEN_DOZE) + doze++; #endif while (nextidx & HILSEN_SCHED) { struct timeval tv; - if (!sched_long) goto sched; + if (!sched_long) + goto sched; do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); tv.tv_usec -= mlc->instart.tv_usec; if (tv.tv_usec >= mlc->intimeout) goto sched; - tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000; + tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC; if (!tv.tv_usec) goto sched; mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec); break; sched: tasklet_schedule(&hil_mlcs_tasklet); break; - } - if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK; - else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK; - else mlc->seidx = nextidx & HILSEN_MASK; + } + + if (nextidx & HILSEN_DOWN) + mlc->seidx += nextidx & HILSEN_MASK; + else if (nextidx & HILSEN_UP) + mlc->seidx -= nextidx & HILSEN_MASK; + else + mlc->seidx = nextidx & HILSEN_MASK; + + if (nextidx & HILSEN_BREAK) + return 1; - if (nextidx & HILSEN_BREAK) return 1; return 0; } /******************** tasklet context functions **************************/ -static void hil_mlcs_process(unsigned long unused) { +static void hil_mlcs_process(unsigned long unused) +{ struct list_head *tmp; read_lock(&hil_mlcs_lock); @@ -702,19 +770,20 @@ static void hil_mlcs_process(unsigned lo struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list); while (hilse_donode(mlc) == 0) { #ifdef HIL_MLC_DEBUG - if (mlc->seidx != 41 && - mlc->seidx != 42 && - mlc->seidx != 43) - printk(KERN_DEBUG PREFIX " + "); + if (mlc->seidx != 41 && + mlc->seidx != 42 && + mlc->seidx != 43) + printk(KERN_DEBUG PREFIX " + "); #endif - }; + } } read_unlock(&hil_mlcs_lock); } /************************* Keepalive timer task *********************/ -void hil_mlcs_timer (unsigned long data) { +void hil_mlcs_timer(unsigned long data) +{ hil_mlcs_probe = 1; tasklet_schedule(&hil_mlcs_tasklet); /* Re-insert the periodic task. */ @@ -724,28 +793,25 @@ void hil_mlcs_timer (unsigned long data) /******************** user/kernel context functions **********************/ -static int hil_mlc_serio_write(struct serio *serio, unsigned char c) { +static int hil_mlc_serio_write(struct serio *serio, unsigned char c) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; struct serio_driver *drv; uint8_t *idx, *last; map = serio->port_data; - if (map == NULL) { - BUG(); - return -EIO; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -EIO; - } - mlc->serio_opacket[map->didx] |= + BUG_ON(mlc == NULL); + + mlc->serio_opacket[map->didx] |= ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx])); if (mlc->serio_oidx[map->didx] >= 3) { /* for now only commands */ - if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) + if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) return -EIO; switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) { case HIL_CMD_IDD: @@ -771,12 +837,11 @@ static int hil_mlc_serio_write(struct se return -EIO; emu: drv = serio->drv; - if (drv == NULL) { - BUG(); - return -EIO; - } + BUG_ON(drv == NULL); + last = idx + 15; - while ((last != idx) && (*last == 0)) last--; + while ((last != idx) && (*last == 0)) + last--; while (idx != last) { drv->interrupt(serio, 0, 0); @@ -789,14 +854,15 @@ static int hil_mlc_serio_write(struct se drv->interrupt(serio, HIL_ERR_INT >> 16, 0); drv->interrupt(serio, HIL_PKT_CMD >> 8, 0); drv->interrupt(serio, *idx, 0); - + mlc->serio_oidx[map->didx] = 0; mlc->serio_opacket[map->didx] = 0; return 0; } -static int hil_mlc_serio_open(struct serio *serio) { +static int hil_mlc_serio_open(struct serio *serio) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; @@ -804,67 +870,57 @@ static int hil_mlc_serio_open(struct ser return -EBUSY; map = serio->port_data; - if (map == NULL) { - BUG(); - return -ENODEV; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return -ENODEV; - } + BUG_ON(mlc == NULL); return 0; } -static void hil_mlc_serio_close(struct serio *serio) { +static void hil_mlc_serio_close(struct serio *serio) +{ struct hil_mlc_serio_map *map; struct hil_mlc *mlc; map = serio->port_data; - if (map == NULL) { - BUG(); - return; - } + BUG_ON(map == NULL); + mlc = map->mlc; - if (mlc == NULL) { - BUG(); - return; - } + BUG_ON(mlc == NULL); serio_set_drvdata(serio, NULL); serio->drv = NULL; /* TODO wake up interruptable */ } -static struct serio_device_id hil_mlc_serio_id = { +static const struct serio_device_id hil_mlc_serio_id = { .type = SERIO_HIL_MLC, .proto = SERIO_HIL, .extra = SERIO_ANY, .id = SERIO_ANY, }; -int hil_mlc_register(hil_mlc *mlc) { +int hil_mlc_register(hil_mlc *mlc) +{ int i; - unsigned long flags; + unsigned long flags; - if (mlc == NULL) { - return -EINVAL; - } + BUG_ON(mlc == NULL); mlc->istarted = 0; - mlc->ostarted = 0; + mlc->ostarted = 0; - rwlock_init(&mlc->lock); - init_MUTEX(&(mlc->osem)); + rwlock_init(&mlc->lock); + init_MUTEX(&mlc->osem); - init_MUTEX(&(mlc->isem)); - mlc->icount = -1; - mlc->imatch = 0; + init_MUTEX(&mlc->isem); + mlc->icount = -1; + mlc->imatch = 0; mlc->opercnt = 0; - init_MUTEX_LOCKED(&(mlc->csem)); + init_MUTEX_LOCKED(&(mlc->csem)); hil_mlc_clear_di_scratch(mlc); hil_mlc_clear_di_map(mlc, 0); @@ -873,6 +929,8 @@ int hil_mlc_register(hil_mlc *mlc) { hil_mlc_copy_di_scratch(mlc, i); mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); mlc->serio[i] = mlc_serio; + snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); + snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); mlc_serio->id = hil_mlc_serio_id; mlc_serio->write = hil_mlc_serio_write; mlc_serio->open = hil_mlc_serio_open; @@ -897,19 +955,18 @@ int hil_mlc_register(hil_mlc *mlc) { return 0; } -int hil_mlc_unregister(hil_mlc *mlc) { +int hil_mlc_unregister(hil_mlc *mlc) +{ struct list_head *tmp; - unsigned long flags; + unsigned long flags; int i; - if (mlc == NULL) - return -EINVAL; + BUG_ON(mlc == NULL); write_lock_irqsave(&hil_mlcs_lock, flags); - list_for_each(tmp, &hil_mlcs) { + list_for_each(tmp, &hil_mlcs) if (list_entry(tmp, hil_mlc, list) == mlc) goto found; - } /* not found in list */ write_unlock_irqrestore(&hil_mlcs_lock, flags); @@ -918,7 +975,7 @@ int hil_mlc_unregister(hil_mlc *mlc) { found: list_del(tmp); - write_unlock_irqrestore(&hil_mlcs_lock, flags); + write_unlock_irqrestore(&hil_mlcs_lock, flags); for (i = 0; i < HIL_MLC_DEVMEM; i++) { serio_unregister_port(mlc->serio[i]); @@ -942,7 +999,7 @@ static int __init hil_mlc_init(void) return 0; } - + static void __exit hil_mlc_exit(void) { del_timer(&hil_mlcs_kicker); @@ -950,6 +1007,6 @@ static void __exit hil_mlc_exit(void) tasklet_disable(&hil_mlcs_tasklet); tasklet_kill(&hil_mlcs_tasklet); } - + module_init(hil_mlc_init); module_exit(hil_mlc_exit); diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index b57370d..31826e6 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -34,27 +34,27 @@ * * Driver theory of operation: * - * hp_sdc_put does all writing to the SDC. ISR can run on a different - * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time + * hp_sdc_put does all writing to the SDC. ISR can run on a different + * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. * - * All data coming back from the SDC is sent via interrupt and can be read - * fully in the ISR, so there are no latency/throughput problems there. - * The problem is with output, due to the slow clock speed of the SDC - * compared to the CPU. This should not be too horrible most of the time, - * but if used with HIL devices that support the multibyte transfer command, - * keeping outbound throughput flowing at the 6500KBps that the HIL is + * All data coming back from the SDC is sent via interrupt and can be read + * fully in the ISR, so there are no latency/throughput problems there. + * The problem is with output, due to the slow clock speed of the SDC + * compared to the CPU. This should not be too horrible most of the time, + * but if used with HIL devices that support the multibyte transfer command, + * keeping outbound throughput flowing at the 6500KBps that the HIL is * capable of is more than can be done at HZ=100. * - * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf - * is set to 0 when the IBF flag in the status register has cleared. ISR - * may do this, and may also access the parts of queued transactions related - * to reading data back from the SDC, but otherwise will not touch the + * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf + * is set to 0 when the IBF flag in the status register has cleared. ISR + * may do this, and may also access the parts of queued transactions related + * to reading data back from the SDC, but otherwise will not touch the * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. * * The i8042 write index and the values in the 4-byte input buffer * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, - * to minimize the amount of IO needed to the SDC. However these values + * to minimize the amount of IO needed to the SDC. However these values * do not need to be locked since they are only ever accessed by hp_sdc_put. * * A timer task schedules the tasklet once per second just to make @@ -106,33 +106,39 @@ EXPORT_SYMBOL(hp_sdc_dequeue_transaction static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ /*************** primitives for use in any context *********************/ -static inline uint8_t hp_sdc_status_in8 (void) { +static inline uint8_t hp_sdc_status_in8(void) +{ uint8_t status; unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); status = sdc_readb(hp_sdc.status_io); - if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0; + if (!(status & HP_SDC_STATUS_IBF)) + hp_sdc.ibf = 0; write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); return status; } -static inline uint8_t hp_sdc_data_in8 (void) { - return sdc_readb(hp_sdc.data_io); +static inline uint8_t hp_sdc_data_in8(void) +{ + return sdc_readb(hp_sdc.data_io); } -static inline void hp_sdc_status_out8 (uint8_t val) { +static inline void hp_sdc_status_out8(uint8_t val) +{ unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); hp_sdc.ibf = 1; - if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff; + if ((val & 0xf0) == 0xe0) + hp_sdc.wi = 0xff; sdc_writeb(val, hp_sdc.status_io); write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); } -static inline void hp_sdc_data_out8 (uint8_t val) { +static inline void hp_sdc_data_out8(uint8_t val) +{ unsigned long flags; write_lock_irqsave(&hp_sdc.ibf_lock, flags); @@ -141,11 +147,12 @@ static inline void hp_sdc_data_out8 (uin write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); } -/* Care must be taken to only invoke hp_sdc_spin_ibf when - * absolutely needed, or in rarely invoked subroutines. - * Not only does it waste CPU cycles, it also wastes bus cycles. +/* Care must be taken to only invoke hp_sdc_spin_ibf when + * absolutely needed, or in rarely invoked subroutines. + * Not only does it waste CPU cycles, it also wastes bus cycles. */ -static inline void hp_sdc_spin_ibf(void) { +static inline void hp_sdc_spin_ibf(void) +{ unsigned long flags; rwlock_t *lock; @@ -158,19 +165,21 @@ static inline void hp_sdc_spin_ibf(void) } read_unlock(lock); write_lock(lock); - while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {}; + while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) + { } hp_sdc.ibf = 0; write_unlock_irqrestore(lock, flags); } /************************ Interrupt context functions ************************/ -static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { +static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data) +{ hp_sdc_transaction *curr; read_lock(&hp_sdc.rtq_lock); if (hp_sdc.rcurr < 0) { - read_unlock(&hp_sdc.rtq_lock); + read_unlock(&hp_sdc.rtq_lock); return; } curr = hp_sdc.tq[hp_sdc.rcurr]; @@ -183,25 +192,27 @@ static void hp_sdc_take (int irq, void * if (hp_sdc.rqty <= 0) { /* All data has been gathered. */ - if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) up(curr->act.semaphore); - } - if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) { + if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) + if (curr->act.semaphore) + up(curr->act.semaphore); + + if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) if (curr->act.irqhook) curr->act.irqhook(irq, dev_id, status, data); - } + curr->actidx = curr->idx; curr->idx++; /* Return control of this transaction */ write_lock(&hp_sdc.rtq_lock); - hp_sdc.rcurr = -1; + hp_sdc.rcurr = -1; hp_sdc.rqty = 0; write_unlock(&hp_sdc.rtq_lock); tasklet_schedule(&hp_sdc.task); } } -static irqreturn_t hp_sdc_isr(int irq, void *dev_id) { +static irqreturn_t hp_sdc_isr(int irq, void *dev_id) +{ uint8_t status, data; status = hp_sdc_status_in8(); @@ -209,67 +220,74 @@ static irqreturn_t hp_sdc_isr(int irq, v data = hp_sdc_data_in8(); /* For now we are ignoring these until we get the SDC to behave. */ - if (((status & 0xf1) == 0x51) && data == 0x82) { - return IRQ_HANDLED; - } + if (((status & 0xf1) == 0x51) && data == 0x82) + return IRQ_HANDLED; - switch(status & HP_SDC_STATUS_IRQMASK) { - case 0: /* This case is not documented. */ + switch (status & HP_SDC_STATUS_IRQMASK) { + case 0: /* This case is not documented. */ break; - case HP_SDC_STATUS_USERTIMER: - case HP_SDC_STATUS_PERIODIC: - case HP_SDC_STATUS_TIMER: + + case HP_SDC_STATUS_USERTIMER: + case HP_SDC_STATUS_PERIODIC: + case HP_SDC_STATUS_TIMER: read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) + if (hp_sdc.timer != NULL) hp_sdc.timer(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; - case HP_SDC_STATUS_REG: + + case HP_SDC_STATUS_REG: hp_sdc_take(irq, dev_id, status, data); break; - case HP_SDC_STATUS_HILCMD: - case HP_SDC_STATUS_HILDATA: + + case HP_SDC_STATUS_HILCMD: + case HP_SDC_STATUS_HILDATA: read_lock(&hp_sdc.hook_lock); if (hp_sdc.hil != NULL) hp_sdc.hil(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; - case HP_SDC_STATUS_PUP: + + case HP_SDC_STATUS_PUP: read_lock(&hp_sdc.hook_lock); if (hp_sdc.pup != NULL) hp_sdc.pup(irq, dev_id, status, data); - else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); + else + printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); read_unlock(&hp_sdc.hook_lock); break; - default: + + default: read_lock(&hp_sdc.hook_lock); if (hp_sdc.cooked != NULL) hp_sdc.cooked(irq, dev_id, status, data); read_unlock(&hp_sdc.hook_lock); break; } + return IRQ_HANDLED; } -static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) { +static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) +{ int status; - + status = hp_sdc_status_in8(); printk(KERN_WARNING PREFIX "NMI !\n"); -#if 0 +#if 0 if (status & HP_SDC_NMISTATUS_FHS) { read_lock(&hp_sdc.hook_lock); - if (hp_sdc.timer != NULL) + if (hp_sdc.timer != NULL) hp_sdc.timer(irq, dev_id, status, 0); read_unlock(&hp_sdc.hook_lock); - } - else { + } else { /* TODO: pass this on to the HIL handler, or do SAK here? */ printk(KERN_WARNING PREFIX "HIL NMI\n"); } #endif + return IRQ_HANDLED; } @@ -278,13 +296,17 @@ #endif unsigned long hp_sdc_put(void); -static void hp_sdc_tasklet(unsigned long foo) { - +static void hp_sdc_tasklet(unsigned long foo) +{ write_lock_irq(&hp_sdc.rtq_lock); + if (hp_sdc.rcurr >= 0) { struct timeval tv; + do_gettimeofday(&tv); - if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000; + if (tv.tv_sec > hp_sdc.rtv.tv_sec) + tv.tv_usec += USEC_PER_SEC; + if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { hp_sdc_transaction *curr; uint8_t tmp; @@ -300,27 +322,29 @@ static void hp_sdc_tasklet(unsigned long hp_sdc.rqty = 0; tmp = curr->seq[curr->actidx]; curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; - if(tmp & HP_SDC_ACT_SEMAPHORE) { - if (curr->act.semaphore) + if (tmp & HP_SDC_ACT_SEMAPHORE) + if (curr->act.semaphore) up(curr->act.semaphore); - } - if(tmp & HP_SDC_ACT_CALLBACK) { + + if (tmp & HP_SDC_ACT_CALLBACK) { /* Note this means that irqhooks may be called * in tasklet/bh context. */ - if (curr->act.irqhook) + if (curr->act.irqhook) curr->act.irqhook(0, NULL, 0, 0); } + curr->actidx = curr->idx; curr->idx++; - hp_sdc.rcurr = -1; + hp_sdc.rcurr = -1; } } write_unlock_irq(&hp_sdc.rtq_lock); hp_sdc_put(); } -unsigned long hp_sdc_put(void) { +unsigned long hp_sdc_put(void) +{ hp_sdc_transaction *curr; uint8_t act; int idx, curridx; @@ -333,19 +357,24 @@ unsigned long hp_sdc_put(void) { requires output, so we skip to the administrativa. */ if (hp_sdc.ibf) { hp_sdc_status_in8(); - if (hp_sdc.ibf) goto finish; + if (hp_sdc.ibf) + goto finish; } anew: /* See if we are in the middle of a sequence. */ - if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr < 0) + hp_sdc.wcurr = 0; read_lock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++; + if (hp_sdc.rcurr == hp_sdc.wcurr) + hp_sdc.wcurr++; read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; curridx = hp_sdc.wcurr; - if (hp_sdc.tq[curridx] != NULL) goto start; + if (hp_sdc.tq[curridx] != NULL) + goto start; while (++curridx != hp_sdc.wcurr) { if (curridx >= HP_SDC_QUEUE_LEN) { @@ -358,7 +387,8 @@ unsigned long hp_sdc_put(void) { continue; } read_unlock_irq(&hp_sdc.rtq_lock); - if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */ + if (hp_sdc.tq[curridx] != NULL) + break; /* Found one. */ } if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ curridx = -1; @@ -374,7 +404,8 @@ unsigned long hp_sdc_put(void) { goto finish; } - if (hp_sdc.wcurr == -1) goto done; + if (hp_sdc.wcurr == -1) + goto done; curr = hp_sdc.tq[curridx]; idx = curr->actidx; @@ -383,20 +414,23 @@ unsigned long hp_sdc_put(void) { hp_sdc.tq[curridx] = NULL; /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; + goto finish; } act = curr->seq[idx]; idx++; if (curr->idx >= curr->endidx) { - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + if (act & HP_SDC_ACT_DEALLOC) + kfree(curr); hp_sdc.tq[curridx] = NULL; /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; - goto finish; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; + goto finish; } while (act & HP_SDC_ACT_PRECMD) { @@ -409,9 +443,10 @@ unsigned long hp_sdc_put(void) { curr->idx++; /* act finished? */ if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) - goto actdone; + goto actdone; /* skip quantity field if data-out sequence follows. */ - if (act & HP_SDC_ACT_DATAOUT) curr->idx++; + if (act & HP_SDC_ACT_DATAOUT) + curr->idx++; goto finish; } if (act & HP_SDC_ACT_DATAOUT) { @@ -423,15 +458,15 @@ unsigned long hp_sdc_put(void) { hp_sdc_data_out8(curr->seq[curr->idx]); curr->idx++; /* act finished? */ - if ((curr->idx - idx >= qty) && - ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)) + if (curr->idx - idx >= qty && + (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT) goto actdone; goto finish; } idx += qty; act &= ~HP_SDC_ACT_DATAOUT; - } - else while (act & HP_SDC_ACT_DATAREG) { + } else + while (act & HP_SDC_ACT_DATAREG) { int mask; uint8_t w7[4]; @@ -445,26 +480,30 @@ unsigned long hp_sdc_put(void) { act &= ~HP_SDC_ACT_DATAREG; break; } - + w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; - + if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || - w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) { + w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) { int i = 0; - /* Need to point the write index register */ - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + /* Need to point the write index register */ + while (i < 4 && w7[i] == hp_sdc.r7[i]) + i++; + if (i < 4) { hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); hp_sdc.wi = 0x70 + i; goto finish; } + idx++; if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) goto actdone; + curr->idx = idx; act &= ~HP_SDC_ACT_DATAREG; break; @@ -476,12 +515,13 @@ unsigned long hp_sdc_put(void) { { int i = 0; - while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; + while ((i < 4) && w7[i] == hp_sdc.r7[i]) + i++; if (i >= 4) { curr->idx = idx + 1; - if ((act & HP_SDC_ACT_DURING) == + if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) - goto actdone; + goto actdone; } } goto finish; @@ -497,7 +537,7 @@ unsigned long hp_sdc_put(void) { if (act & HP_SDC_ACT_POSTCMD) { - uint8_t postcmd; + uint8_t postcmd; /* curr->idx should == idx at this point. */ postcmd = curr->seq[idx]; @@ -505,12 +545,12 @@ unsigned long hp_sdc_put(void) { if (act & HP_SDC_ACT_DATAIN) { /* Start a new read */ - hp_sdc.rqty = curr->seq[curr->idx]; + hp_sdc.rqty = curr->seq[curr->idx]; do_gettimeofday(&hp_sdc.rtv); curr->idx++; /* Still need to lock here in case of spurious irq. */ write_lock_irq(&hp_sdc.rtq_lock); - hp_sdc.rcurr = curridx; + hp_sdc.rcurr = curridx; write_unlock_irq(&hp_sdc.rtq_lock); hp_sdc_status_out8(postcmd); goto finish; @@ -519,64 +559,69 @@ unsigned long hp_sdc_put(void) { goto actdone; } -actdone: - if (act & HP_SDC_ACT_SEMAPHORE) { + actdone: + if (act & HP_SDC_ACT_SEMAPHORE) up(curr->act.semaphore); - } - else if (act & HP_SDC_ACT_CALLBACK) { + else if (act & HP_SDC_ACT_CALLBACK) curr->act.irqhook(0,NULL,0,0); - } + if (curr->idx >= curr->endidx) { /* This transaction is over. */ - if (act & HP_SDC_ACT_DEALLOC) kfree(curr); + if (act & HP_SDC_ACT_DEALLOC) + kfree(curr); hp_sdc.tq[curridx] = NULL; - } - else { + } else { curr->actidx = idx + 1; curr->idx = idx + 2; } /* Interleave outbound data between the transactions. */ hp_sdc.wcurr++; - if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; + if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) + hp_sdc.wcurr = 0; finish: - /* If by some quirk IBF has cleared and our ISR has run to + /* If by some quirk IBF has cleared and our ISR has run to see that that has happened, do it all again. */ - if (!hp_sdc.ibf && limit++ < 20) goto anew; + if (!hp_sdc.ibf && limit++ < 20) + goto anew; done: - if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task); + if (hp_sdc.wcurr >= 0) + tasklet_schedule(&hp_sdc.task); write_unlock(&hp_sdc.lock); + return 0; } /******* Functions called in either user or kernel context ****/ -int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { +int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) +{ unsigned long flags; int i; if (this == NULL) { tasklet_schedule(&hp_sdc.task); return -EINVAL; - }; + } write_lock_irqsave(&hp_sdc.lock, flags); /* Can't have same transaction on queue twice */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) goto fail; + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) + goto fail; this->actidx = 0; this->idx = 1; /* Search for empty slot */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) { + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) if (hp_sdc.tq[i] == NULL) { hp_sdc.tq[i] = this; write_unlock_irqrestore(&hp_sdc.lock, flags); tasklet_schedule(&hp_sdc.task); return 0; } - } + write_unlock_irqrestore(&hp_sdc.lock, flags); printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); return -EBUSY; @@ -587,7 +632,8 @@ int hp_sdc_enqueue_transaction(hp_sdc_tr return -EINVAL; } -int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { +int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) +{ unsigned long flags; int i; @@ -595,8 +641,9 @@ int hp_sdc_dequeue_transaction(hp_sdc_tr /* TODO: don't remove it if it's not done. */ - for (i=0; i < HP_SDC_QUEUE_LEN; i++) - if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL; + for (i = 0; i < HP_SDC_QUEUE_LEN; i++) + if (hp_sdc.tq[i] == this) + hp_sdc.tq[i] = NULL; write_unlock_irqrestore(&hp_sdc.lock, flags); return 0; @@ -605,11 +652,11 @@ int hp_sdc_dequeue_transaction(hp_sdc_tr /********************** User context functions **************************/ -int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.timer != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -629,11 +676,11 @@ int hp_sdc_request_timer_irq(hp_sdc_irqh return 0; } -int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.hil != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -650,11 +697,11 @@ int hp_sdc_request_hil_irq(hp_sdc_irqhoo return 0; } -int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { - - if (callback == NULL || hp_sdc.dev == NULL) { +int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) +{ + if (callback == NULL || hp_sdc.dev == NULL) return -EINVAL; - } + write_lock_irq(&hp_sdc.hook_lock); if (hp_sdc.cooked != NULL) { write_unlock_irq(&hp_sdc.hook_lock); @@ -672,9 +719,8 @@ int hp_sdc_request_cooked_irq(hp_sdc_irq return 0; } -int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { - - +int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.timer) || (hp_sdc.timer == NULL)) { @@ -694,8 +740,8 @@ int hp_sdc_release_timer_irq(hp_sdc_irqh return 0; } -int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { - +int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.hil) || (hp_sdc.hil == NULL)) { @@ -715,8 +761,8 @@ int hp_sdc_release_hil_irq(hp_sdc_irqhoo return 0; } -int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { - +int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) +{ write_lock_irq(&hp_sdc.hook_lock); if ((callback != hp_sdc.cooked) || (hp_sdc.cooked == NULL)) { @@ -738,7 +784,8 @@ int hp_sdc_release_cooked_irq(hp_sdc_irq /************************* Keepalive timer task *********************/ -void hp_sdc_kicker (unsigned long data) { +void hp_sdc_kicker (unsigned long data) +{ tasklet_schedule(&hp_sdc.task); /* Re-insert the periodic task. */ mod_timer(&hp_sdc.kicker, jiffies + HZ); @@ -748,12 +795,12 @@ void hp_sdc_kicker (unsigned long data) #if defined(__hppa__) -static struct parisc_device_id hp_sdc_tbl[] = { +static const struct parisc_device_id hp_sdc_tbl[] = { { - .hw_type = HPHW_FIO, + .hw_type = HPHW_FIO, .hversion_rev = HVERSION_REV_ANY_ID, .hversion = HVERSION_ANY_ID, - .sversion = 0x73, + .sversion = 0x73, }, { 0, } }; @@ -772,16 +819,15 @@ #endif /* __hppa__ */ static int __init hp_sdc_init(void) { - int i; char *errstr; hp_sdc_transaction t_sync; uint8_t ts_sync[6]; struct semaphore s_sync; - rwlock_init(&hp_sdc.lock); - rwlock_init(&hp_sdc.ibf_lock); - rwlock_init(&hp_sdc.rtq_lock); - rwlock_init(&hp_sdc.hook_lock); + rwlock_init(&hp_sdc.lock); + rwlock_init(&hp_sdc.ibf_lock); + rwlock_init(&hp_sdc.rtq_lock); + rwlock_init(&hp_sdc.hook_lock); hp_sdc.timer = NULL; hp_sdc.hil = NULL; @@ -796,7 +842,8 @@ static int __init hp_sdc_init(void) hp_sdc.r7[3] = 0xff; hp_sdc.ibf = 1; - for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL; + memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq)); + hp_sdc.wcurr = -1; hp_sdc.rcurr = -1; hp_sdc.rqty = 0; @@ -804,27 +851,32 @@ static int __init hp_sdc_init(void) hp_sdc.dev_err = -ENODEV; errstr = "IO not found for"; - if (!hp_sdc.base_io) goto err0; + if (!hp_sdc.base_io) + goto err0; errstr = "IRQ not found for"; - if (!hp_sdc.irq) goto err0; + if (!hp_sdc.irq) + goto err0; hp_sdc.dev_err = -EBUSY; #if defined(__hppa__) errstr = "IO not available for"; - if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0; -#endif + if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) + goto err0; +#endif errstr = "IRQ not available for"; - if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC", - (void *) hp_sdc.base_io)) goto err1; + if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, + "HP SDC", &hp_sdc)) + goto err1; errstr = "NMI not available for"; - if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", - (void *) hp_sdc.base_io)) goto err2; + if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED, + "HP SDC NMI", &hp_sdc)) + goto err2; - printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", + printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); hp_sdc_status_in8(); @@ -854,13 +906,14 @@ #endif hp_sdc.dev_err = 0; return 0; err2: - free_irq(hp_sdc.irq, NULL); + free_irq(hp_sdc.irq, &hp_sdc); err1: release_region(hp_sdc.data_io, 2); err0: - printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", + printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); hp_sdc.dev = NULL; + return hp_sdc.dev_err; } @@ -868,8 +921,10 @@ #if defined(__hppa__) static int __init hp_sdc_init_hppa(struct parisc_device *d) { - if (!d) return 1; - if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */ + if (!d) + return 1; + if (hp_sdc.dev != NULL) + return 1; /* We only expect one SDC */ hp_sdc.dev = d; hp_sdc.irq = d->irq; @@ -898,18 +953,16 @@ #endif /* Wait until we know this has been processed by the i8042 */ hp_sdc_spin_ibf(); - free_irq(hp_sdc.nmi, NULL); - free_irq(hp_sdc.irq, NULL); + free_irq(hp_sdc.nmi, &hp_sdc); + free_irq(hp_sdc.irq, &hp_sdc); write_unlock_irq(&hp_sdc.lock); del_timer(&hp_sdc.kicker); tasklet_kill(&hp_sdc.task); -/* release_region(hp_sdc.data_io, 2); */ - #if defined(__hppa__) - if (unregister_parisc_driver(&hp_sdc_driver)) + if (unregister_parisc_driver(&hp_sdc_driver)) printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); #endif } @@ -923,7 +976,7 @@ #if defined(__mc68000__) mm_segment_t fs; unsigned char i; #endif - + hp_sdc.dev = NULL; hp_sdc.dev_err = 0; #if defined(__hppa__) @@ -960,8 +1013,8 @@ #endif tq_init.seq = tq_init_seq; tq_init.act.semaphore = &tq_init_sem; - tq_init_seq[0] = - HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; + tq_init_seq[0] = + HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; tq_init_seq[1] = HP_SDC_CMD_READ_KCC; tq_init_seq[2] = 1; tq_init_seq[3] = 0; @@ -979,13 +1032,13 @@ #endif } hp_sdc.r11 = tq_init_seq[4]; if (hp_sdc.r11 & HP_SDC_CFG_NEW) { - char *str; + const char *str; printk(KERN_INFO PREFIX "New style SDC\n"); tq_init_seq[1] = HP_SDC_CMD_READ_XTD; tq_init.actidx = 0; tq_init.idx = 1; down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); + hp_sdc_enqueue_transaction(&tq_init); down(&tq_init_sem); up(&tq_init_sem); if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { @@ -995,15 +1048,13 @@ #endif hp_sdc.r7e = tq_init_seq[4]; HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) printk(KERN_INFO PREFIX "Revision: %s\n", str); - if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) { + if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); - } - if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) { + if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); - } printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " "on next firmware reset.\n"); - tq_init_seq[0] = HP_SDC_ACT_PRECMD | + tq_init_seq[0] = HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; tq_init_seq[1] = HP_SDC_CMD_SET_STR; tq_init_seq[2] = 1; @@ -1012,14 +1063,12 @@ #endif tq_init.idx = 1; tq_init.endidx = 4; down(&tq_init_sem); - hp_sdc_enqueue_transaction(&tq_init); + hp_sdc_enqueue_transaction(&tq_init); down(&tq_init_sem); up(&tq_init_sem); - } - else { - printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", + } else + printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); - } return 0; } @@ -1027,13 +1076,13 @@ #endif module_init(hp_sdc_register); module_exit(hp_sdc_exit); -/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) +/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) * cycles cycles-adj time * between two consecutive mfctl(16)'s: 4 n/a 63ns * hp_sdc_spin_ibf when idle: 119 115 1.7us * gsc_writeb status register: 83 79 1.2us * IBF to clear after sending SET_IM: 6204 6006 93us - * IBF to clear after sending LOAD_RT: 4467 4352 68us + * IBF to clear after sending LOAD_RT: 4467 4352 68us * IBF to clear after sending two LOAD_RTs: 18974 18859 295us * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index aa4a8a4..cb0b288 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c @@ -58,12 +58,13 @@ struct hp_sdc_mlc_priv_s { } hp_sdc_mlc_priv; /************************* Interrupt context ******************************/ -static void hp_sdc_mlc_isr (int irq, void *dev_id, - uint8_t status, uint8_t data) { - int idx; +static void hp_sdc_mlc_isr (int irq, void *dev_id, + uint8_t status, uint8_t data) +{ + int idx; hil_mlc *mlc = &hp_sdc_mlc; - write_lock(&(mlc->lock)); + write_lock(&mlc->lock); if (mlc->icount < 0) { printk(KERN_WARNING PREFIX "HIL Overflow!\n"); up(&mlc->isem); @@ -73,239 +74,247 @@ static void hp_sdc_mlc_isr (int irq, voi if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { mlc->ipacket[idx] |= data | HIL_ERR_INT; mlc->icount--; - if (hp_sdc_mlc_priv.got5x) goto check; - if (!idx) goto check; - if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) != + if (hp_sdc_mlc_priv.got5x || !idx) + goto check; + if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) != (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; - mlc->ipacket[idx] |= (mlc->ipacket[idx-1] - & HIL_PKT_ADDR_MASK); + mlc->ipacket[idx] |= (mlc->ipacket[idx - 1] + & HIL_PKT_ADDR_MASK); } goto check; } /* We know status is 5X */ - if (data & HP_SDC_HIL_ISERR) goto err; - mlc->ipacket[idx] = + if (data & HP_SDC_HIL_ISERR) + goto err; + mlc->ipacket[idx] = (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; hp_sdc_mlc_priv.got5x = 1; goto out; check: hp_sdc_mlc_priv.got5x = 0; - if (mlc->imatch == 0) goto done; - if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) - && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done; - if (mlc->ipacket[idx] == mlc->imatch) goto done; + if (mlc->imatch == 0) + goto done; + if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) + && (mlc->ipacket[idx] == (mlc->imatch | idx))) + goto done; + if (mlc->ipacket[idx] == mlc->imatch) + goto done; goto out; - err: + err: printk(KERN_DEBUG PREFIX "err code %x\n", data); + switch (data) { case HP_SDC_HIL_RC_DONE: printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); break; + case HP_SDC_HIL_ERR: - mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | - HIL_ERR_FERR | HIL_ERR_FOF; + mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | + HIL_ERR_FERR | HIL_ERR_FOF; break; + case HP_SDC_HIL_TO: mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; break; + case HP_SDC_HIL_RC: printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); break; + default: printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); break; } + /* No more data will be coming due to an error. */ done: tasklet_schedule(mlc->tasklet); - up(&(mlc->isem)); + up(&mlc->isem); out: - write_unlock(&(mlc->lock)); + write_unlock(&mlc->lock); } /******************** Tasklet or userspace context functions ****************/ -static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) { +static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout) +{ unsigned long flags; struct hp_sdc_mlc_priv_s *priv; int rc = 2; priv = mlc->priv; - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); /* Try to down the semaphore */ - if (down_trylock(&(mlc->isem))) { + if (down_trylock(&mlc->isem)) { struct timeval tv; if (priv->emtestmode) { - mlc->ipacket[0] = - HIL_ERR_INT | (mlc->opacket & - (HIL_PKT_CMD | - HIL_PKT_ADDR_MASK | + mlc->ipacket[0] = + HIL_ERR_INT | (mlc->opacket & + (HIL_PKT_CMD | + HIL_PKT_ADDR_MASK | HIL_PKT_DATA_MASK)); mlc->icount = 14; /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ goto wasup; } do_gettimeofday(&tv); - tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); + tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec); if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { - /* printk("!%i %i", - tv.tv_usec - mlc->instart.tv_usec, - mlc->intimeout); - */ + /* printk("!%i %i", + tv.tv_usec - mlc->instart.tv_usec, + mlc->intimeout); + */ rc = 1; - up(&(mlc->isem)); + up(&mlc->isem); } goto done; } wasup: - up(&(mlc->isem)); + up(&mlc->isem); rc = 0; goto done; done: - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); return rc; } -static int hp_sdc_mlc_cts (hil_mlc *mlc) { +static int hp_sdc_mlc_cts(hil_mlc *mlc) +{ struct hp_sdc_mlc_priv_s *priv; unsigned long flags; - priv = mlc->priv; + priv = mlc->priv; - write_lock_irqsave(&(mlc->lock), flags); + write_lock_irqsave(&mlc->lock, flags); /* Try to down the semaphores -- they should be up. */ - if (down_trylock(&(mlc->isem))) { - BUG(); - goto busy; - } - if (down_trylock(&(mlc->osem))) { - BUG(); - up(&(mlc->isem)); - goto busy; - } - up(&(mlc->isem)); - up(&(mlc->osem)); + BUG_ON(down_trylock(&mlc->isem)); + BUG_ON(down_trylock(&mlc->osem)); + + up(&mlc->isem); + up(&mlc->osem); - if (down_trylock(&(mlc->csem))) { - if (priv->trans.act.semaphore != &(mlc->csem)) goto poll; - goto busy; + if (down_trylock(&mlc->csem)) { + if (priv->trans.act.semaphore != &mlc->csem) + goto poll; + else + goto busy; } - if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done; + + if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) + goto done; poll: - priv->trans.act.semaphore = &(mlc->csem); + priv->trans.act.semaphore = &mlc->csem; priv->trans.actidx = 0; priv->trans.idx = 1; priv->trans.endidx = 5; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = HP_SDC_CMD_READ_USE; priv->tseq[2] = 1; priv->tseq[3] = 0; priv->tseq[4] = 0; - hp_sdc_enqueue_transaction(&(priv->trans)); + hp_sdc_enqueue_transaction(&priv->trans); busy: - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); return 1; done: - priv->trans.act.semaphore = &(mlc->osem); - up(&(mlc->csem)); - write_unlock_irqrestore(&(mlc->lock), flags); + priv->trans.act.semaphore = &mlc->osem; + up(&mlc->csem); + write_unlock_irqrestore(&mlc->lock, flags); return 0; } -static void hp_sdc_mlc_out (hil_mlc *mlc) { +static void hp_sdc_mlc_out(hil_mlc *mlc) +{ struct hp_sdc_mlc_priv_s *priv; unsigned long flags; priv = mlc->priv; - write_lock_irqsave(&(mlc->lock), flags); - + write_lock_irqsave(&mlc->lock, flags); + /* Try to down the semaphore -- it should be up. */ - if (down_trylock(&(mlc->osem))) { - BUG(); - goto done; - } + BUG_ON(down_trylock(&mlc->osem)); - if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control; + if (mlc->opacket & HIL_DO_ALTER_CTRL) + goto do_control; do_data: if (priv->emtestmode) { - up(&(mlc->osem)); + up(&mlc->osem); goto done; } /* Shouldn't be sending commands when loop may be busy */ - if (down_trylock(&(mlc->csem))) { - BUG(); - goto done; - } - up(&(mlc->csem)); + BUG_ON(down_trylock(&mlc->csem)); + up(&mlc->csem); priv->trans.actidx = 0; priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); + priv->trans.act.semaphore = &mlc->osem; priv->trans.endidx = 6; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = 0x7; - priv->tseq[2] = - (mlc->opacket & + priv->tseq[2] = + (mlc->opacket & (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) >> HIL_PKT_ADDR_SHIFT; - priv->tseq[3] = - (mlc->opacket & HIL_PKT_DATA_MASK) + priv->tseq[3] = + (mlc->opacket & HIL_PKT_DATA_MASK) >> HIL_PKT_DATA_SHIFT; priv->tseq[4] = 0; /* No timeout */ - if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1; + if (priv->tseq[3] == HIL_CMD_DHR) + priv->tseq[4] = 1; priv->tseq[5] = HP_SDC_CMD_DO_HIL; goto enqueue; do_control: priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; - + /* we cannot emulate this, it should not be used. */ BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE); - - if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; - if (mlc->opacket & HIL_CTRL_APE) { - BUG(); /* Should not send command/data after engaging APE */ - goto done; - } - /* Disengaging APE this way would not be valid either since + + if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) + goto control_only; + + /* Should not send command/data after engaging APE */ + BUG_ON(mlc->opacket & HIL_CTRL_APE); + + /* Disengaging APE this way would not be valid either since * the loop must be allowed to idle. * - * So, it works out that we really never actually send control - * and data when using SDC, we just send the data. + * So, it works out that we really never actually send control + * and data when using SDC, we just send the data. */ goto do_data; control_only: priv->trans.actidx = 0; priv->trans.idx = 1; - priv->trans.act.semaphore = &(mlc->osem); + priv->trans.act.semaphore = &mlc->osem; priv->trans.endidx = 4; - priv->tseq[0] = + priv->tseq[0] = HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; priv->tseq[1] = HP_SDC_CMD_SET_LPC; priv->tseq[2] = 1; - // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; + /* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */ priv->tseq[3] = 0; if (mlc->opacket & HIL_CTRL_APE) { priv->tseq[3] |= HP_SDC_LPC_APE_IPF; - down_trylock(&(mlc->csem)); - } + down_trylock(&mlc->csem); + } enqueue: - hp_sdc_enqueue_transaction(&(priv->trans)); + hp_sdc_enqueue_transaction(&priv->trans); done: - write_unlock_irqrestore(&(mlc->lock), flags); + write_unlock_irqrestore(&mlc->lock, flags); } static int __init hp_sdc_mlc_init(void) @@ -316,18 +325,18 @@ static int __init hp_sdc_mlc_init(void) hp_sdc_mlc_priv.emtestmode = 0; hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; - hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem); + hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem; hp_sdc_mlc_priv.got5x = 0; - mlc->cts = &hp_sdc_mlc_cts; - mlc->in = &hp_sdc_mlc_in; - mlc->out = &hp_sdc_mlc_out; + mlc->cts = &hp_sdc_mlc_cts; + mlc->in = &hp_sdc_mlc_in; + mlc->out = &hp_sdc_mlc_out; + mlc->priv = &hp_sdc_mlc_priv; if (hil_mlc_register(mlc)) { printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); goto err0; } - mlc->priv = &hp_sdc_mlc_priv; if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); @@ -335,10 +344,9 @@ static int __init hp_sdc_mlc_init(void) } return 0; err1: - if (hil_mlc_unregister(mlc)) { + if (hil_mlc_unregister(mlc)) printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" "This is bad. Could cause an oops.\n"); - } err0: return -EBUSY; } @@ -346,14 +354,14 @@ static int __init hp_sdc_mlc_init(void) static void __exit hp_sdc_mlc_exit(void) { hil_mlc *mlc = &hp_sdc_mlc; - if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) { + + if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" "This is bad. Could cause an oops.\n"); - } - if (hil_mlc_unregister(mlc)) { + + if (hil_mlc_unregister(mlc)) printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" "This is bad. Could cause an oops.\n"); - } } module_init(hp_sdc_mlc_init); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 0a26e06..2f5fc80 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -39,7 +39,8 @@ #endif /* * This code has been heavily tested on a Nokia 770, and lightly * tested on other ads7846 devices (OSK/Mistral, Lubbock). - * Support for ads7843 and ads7845 has only been stubbed in. + * Support for ads7843 tested on Atmel at91sam926x-EK. + * Support for ads7845 has only been stubbed in. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -246,18 +247,16 @@ static int ads7846_read12_ser(struct dev /* REVISIT: take a few more samples, and compare ... */ - /* maybe off internal vREF */ - if (use_internal) { - req->ref_off = REF_OFF; - req->xfer[4].tx_buf = &req->ref_off; - req->xfer[4].len = 1; - spi_message_add_tail(&req->xfer[4], &req->msg); - - req->xfer[5].rx_buf = &req->scratch; - req->xfer[5].len = 2; - CS_CHANGE(req->xfer[5]); - spi_message_add_tail(&req->xfer[5], &req->msg); - } + /* converter in low power mode & enable PENIRQ */ + req->ref_off = PWRDOWN; + req->xfer[4].tx_buf = &req->ref_off; + req->xfer[4].len = 1; + spi_message_add_tail(&req->xfer[4], &req->msg); + + req->xfer[5].rx_buf = &req->scratch; + req->xfer[5].len = 2; + CS_CHANGE(req->xfer[5]); + spi_message_add_tail(&req->xfer[5], &req->msg); ts->irq_disabled = 1; disable_irq(spi->irq); @@ -536,6 +535,9 @@ static void ads7846_rx(void *ads) } else Rt = 0; + if (ts->model == 7843) + Rt = ts->pressure_max / 2; + /* Sample found inconsistent by debouncing or pressure is beyond * the maximum. Don't report it to user space, repeat at least * once more the measurement