From 6bcf67374137f433e85aa42a18fde9f0e8562901 Mon Sep 17 00:00:00 2001 From: Chen Liqin Date: Sat, 13 Jun 2009 15:24:33 +0800 Subject: score: add maintainers for score architecture Signed-off-by: Chen Liqin Signed-off-by: Arnd Bergmann --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 035df9d26609..ef643ddd5e8d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5000,6 +5000,14 @@ S: Maintained F: kernel/sched* F: include/linux/sched.h +SCORE ARCHITECTURE +P: Chen Liqin +M: liqin.chen@sunplusct.com +P: Lennox Wu +M: lennox.wu@sunplusct.com +W: http://www.sunplusct.com +S: Supported + SCSI CDROM DRIVER P: Jens Axboe M: axboe@kernel.dk -- cgit v1.2.3 From 4c5adde7943b982d22a7bf711654fbb5cb810667 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 19 Jun 2009 12:02:33 -0700 Subject: MAINTAINERS: add entry for TI DaVinci machine support Signed-off-by: Kevin Hilman --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 60299a9a7adb..86e78284394e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4590,6 +4590,12 @@ F: arch/arm/mach-s3c2410/ F: drivers/*/*s3c2410* F: drivers/*/*/*s3c2410* +TI DAVINCI MACHINE SUPPORT +P: Kevin Hilman +M: davinci-linux-open-source@linux.davincidsp.com +S: Supported +F: arch/arm/mach-davinci + SIS 190 ETHERNET DRIVER M: Francois Romieu L: netdev@vger.kernel.org -- cgit v1.2.3 From 6349d9979beba240fe7182872cb547250264b865 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 14 Aug 2009 15:07:14 -0400 Subject: SFI: Simple Firmware Interface - MAINTAINERS, Kconfig CONFIG_SFI=y enables the kernel to boot and run optimally on platforms that support the Simple Firmware Interface. Thanks to Jacob Pan for prototyping the initial Linux SFI support, and to Feng Tang for Linux bring-up and debug both in emulation and on Moorestown hardware. See http://simplefirmware.org for more information on SFI. Signed-off-by: Len Brown --- MAINTAINERS | 12 ++++++++++++ drivers/sfi/Kconfig | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 drivers/sfi/Kconfig (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 60299a9a7adb..055ba880aaec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4575,6 +4575,18 @@ L: linux-pci@vger.kernel.org S: Supported F: drivers/pci/hotplug/shpchp* +SIMPLE FIRMWARE INTERFACE (SFI) +P: Len Brown +M: lenb@kernel.org +L: sfi-devel@simplefirmware.org +W: http://simplefirmware.org/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git +S: Supported +F: arch/x86/kernel/*sfi* +F: drivers/sfi/ +F: include/linux/sfi*.h + + SIMTEC EB110ATX (Chalice CATS) P: Ben Dooks M: Vincent Sanders diff --git a/drivers/sfi/Kconfig b/drivers/sfi/Kconfig new file mode 100644 index 000000000000..dd115121e0b6 --- /dev/null +++ b/drivers/sfi/Kconfig @@ -0,0 +1,17 @@ +# +# SFI Configuration +# + +menuconfig SFI + bool "SFI (Simple Firmware Interface) Support" + ---help--- + The Simple Firmware Interface (SFI) provides a lightweight method + for platform firmware to pass information to the operating system + via static tables in memory. Kernel SFI support is required to + boot on SFI-only platforms. Currently, all SFI-only platforms are + based on the 2nd generation Intel Atom processor platform, + code-named Moorestown. + + For more information, see http://simplefirmware.org + + Say 'Y' here to enable the kernel to boot on SFI-only platforms. -- cgit v1.2.3 From 19003c18e9b41f5c3aeb81c92356f90958e1f22f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 3 Aug 2009 19:00:57 +0200 Subject: ext3: Update MAINTAINERS for ext3 and JBD Stephen agreed that he's unlikely to find time for working on ext3/JBD in the near future and is not working on it for some time already. So remove him. Added myself to JBD since after Andrew I'm probably the second most sensible contact ;). CC: Stephen Tweedie Signed-off-by: Jan Kara --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 9117b65f4ae3..424beb672aff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1967,7 +1967,6 @@ F: fs/ext2/ F: include/linux/ext2* EXT3 FILE SYSTEM -M: Stephen Tweedie M: Andrew Morton M: Andreas Dilger L: linux-ext4@vger.kernel.org @@ -2892,8 +2891,8 @@ F: fs/jffs2/ F: include/linux/jffs2.h JOURNALLING LAYER FOR BLOCK DEVICES (JBD) -M: Stephen Tweedie M: Andrew Morton +M: Jan Kara L: linux-ext4@vger.kernel.org S: Maintained F: fs/jbd*/ -- cgit v1.2.3 From b75ea16ae74e77244e134943a5676ca770036cac Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jul 2009 16:43:08 +0100 Subject: MAINTAINERS: Add entry for Wolfson PMIC drivers Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- MAINTAINERS | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 9117b65f4ae3..fba5e8141a62 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5669,6 +5669,24 @@ S: Supported F: drivers/input/touchscreen/*wm97* F: include/linux/wm97xx.h +WOLFSON MICROELECTRONICS PMIC DRIVERS +P: Mark Brown +M: broonie@opensource.wolfsonmicro.com +L: linux-kernel@vger.kernel.org +T: git git://opensource.wolfsonmicro.com/linux-2.6-audioplus +W: http://opensource.wolfsonmicro.com/node/8 +S: Supported +F: drivers/leds/leds-wm83*.c +F: drivers/mfd/wm8*.c +F: drivers/power/wm83*.c +F: drivers/rtc/rtc-wm83*.c +F: drivers/regulator/wm8*.c +F: drivers/watchdog/wm83*_wdt.c +F: include/linux/mfd/wm8350/ +F: include/linux/mfd/wm8400/ +F: sound/soc/codecs/wm8350.c +F: sound/soc/codecs/wm8400.c + X.25 NETWORK LAYER M: Henner Eisen L: linux-x25@vger.kernel.org -- cgit v1.2.3 From 3860e6c4b93d6a1c2428f0f45c77e083197da2d4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 9 Sep 2009 14:46:43 +0100 Subject: mfd: Update MAINTAINERS patterns for WM831x The WM831x PMICs added a backlight driver and a new include directory. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index fba5e8141a62..9d635f3bbc7c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5681,7 +5681,9 @@ F: drivers/mfd/wm8*.c F: drivers/power/wm83*.c F: drivers/rtc/rtc-wm83*.c F: drivers/regulator/wm8*.c +F: drivers/video/backlight/wm83*_bl.c F: drivers/watchdog/wm83*_wdt.c +F: include/linux/mfd/wm831x/ F: include/linux/mfd/wm8350/ F: include/linux/mfd/wm8400/ F: sound/soc/codecs/wm8350.c -- cgit v1.2.3 From be3652b8a253346339ce32501dd48fb033258936 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Sep 2009 10:01:07 -0700 Subject: MAINTAINTERS: remove hotplug driver entries So Kristen stops getting PCI hotplug related stuff; the maintainer switch actually happened awhile ago, but the entries were never purged. Signed-off-by: Jesse Barnes --- MAINTAINERS | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 9117b65f4ae3..5cbe07cf4ea1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -256,12 +256,6 @@ W: http://www.lesswatts.org/projects/acpi/ S: Supported F: drivers/acpi/fan.c -ACPI PCI HOTPLUG DRIVER -M: Kristen Carlson Accardi -L: linux-pci@vger.kernel.org -S: Supported -F: drivers/pci/hotplug/acpi* - ACPI THERMAL DRIVER M: Zhang Rui L: linux-acpi@vger.kernel.org @@ -3964,11 +3958,11 @@ F: Documentation/PCI/ F: drivers/pci/ F: include/linux/pci* -PCIE HOTPLUG DRIVER -M: Kristen Carlson Accardi +PCI HOTPLUG +M: Jesse Barnes L: linux-pci@vger.kernel.org S: Supported -F: drivers/pci/pcie/ +F: drivers/pci/hotplug PCMCIA SUBSYSTEM P: Linux PCMCIA Team @@ -4624,12 +4618,6 @@ F: drivers/serial/serial_lh7a40x.c F: drivers/usb/gadget/lh7a40* F: drivers/usb/host/ohci-lh7a40* -SHPC HOTPLUG DRIVER -M: Kristen Carlson Accardi -L: linux-pci@vger.kernel.org -S: Supported -F: drivers/pci/hotplug/shpchp* - SIMTEC EB110ATX (Chalice CATS) P: Ben Dooks M: Vincent Sanders -- cgit v1.2.3 From a1867d36b3bda28314fdd832a510dc9e55821c4c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 18 Sep 2009 22:45:51 +0200 Subject: MAINTAINERS: Add maintainer for AT24 and PCA9564/PCA9665 Add me as the maintainer for the i2c drivers I feel responsible for as I found patches going mainline I missed due to no Cc. Signed-off-by: Wolfram Sang Cc: David Brownell Signed-off-by: Jean Delvare --- MAINTAINERS | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index e613c6dd709f..9a1cd2ff24af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -894,6 +894,13 @@ F: drivers/dma/ F: include/linux/dmaengine.h F: include/linux/async_tx.h +AT24 EEPROM DRIVER +M: Wolfram Sang +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/misc/eeprom/at24.c +F: include/linux/i2c/at24.h + ATA OVER ETHERNET (AOE) DRIVER M: "Ed L. Cashin" W: http://www.coraid.com/support/linux @@ -3957,6 +3964,15 @@ S: Maintained F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h +PCA9564/PCA9665 I2C BUS DRIVER +M: Wolfram Sang +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/algos/i2c-algo-pca.c +F: drivers/i2c/busses/i2c-pca-* +F: include/linux/i2c-algo-pca.h +F: include/linux/i2c-pca-platform.h + PCI ERROR RECOVERY M: Linas Vepstas L: linux-pci@vger.kernel.org -- cgit v1.2.3 From 9caeb5324427990db7bc97e674794d201c1f0797 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 14 Sep 2009 21:11:21 -0300 Subject: topstar-laptop: add new driver for hotkeys support on Topstar N01 This adds Topstar Laptop Extras ACPI driver. It enables hotkeys functionality with Topstar N01 netbook. Besides hotkeys there are other functions exposed by its ACPI firmware, but for now only hotkeys reporting on Topstar N01 is supported. Topstar is a chinese manufacturer, its website can be currently reached at http://www.topstardigital.cn/ Signed-off-by: Herton Ronaldo Krzesinski Reviewed-by: Alan Jenkins Reviewed-by: Bjorn Helgaas Signed-off-by: Len Brown --- MAINTAINERS | 5 + drivers/platform/x86/Kconfig | 9 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/topstar-laptop.c | 265 ++++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 drivers/platform/x86/topstar-laptop.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 8dca9d89c6c1..d75a7a70788e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4968,6 +4968,11 @@ T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches S: Maintained F: security/tomoyo/ +TOPSTAR LAPTOP EXTRAS DRIVER +M: Herton Ronaldo Krzesinski +S: Maintained +F: drivers/platform/x86/topstar-laptop.c + TOSHIBA ACPI EXTRAS DRIVER S: Orphan F: drivers/platform/x86/toshiba_acpi.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 77c6097ced80..48315621046d 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -396,6 +396,15 @@ config ACPI_ASUS NOTE: This driver is deprecated and will probably be removed soon, use asus-laptop instead. +config TOPSTAR_LAPTOP + tristate "Topstar Laptop Extras" + depends on ACPI + depends on INPUT + ---help--- + This driver adds support for hotkeys found on Topstar laptops. + + If you have a Topstar laptop, say Y or M here. + config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 641b8bfa5538..d1c16210a512 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -19,4 +19,5 @@ obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o obj-$(CONFIG_ACPI_WMI) += wmi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o +obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c new file mode 100644 index 000000000000..02f3d4e9e666 --- /dev/null +++ b/drivers/platform/x86/topstar-laptop.c @@ -0,0 +1,265 @@ +/* + * ACPI driver for Topstar notebooks (hotkeys support only) + * + * Copyright (c) 2009 Herton Ronaldo Krzesinski + * + * Implementation inspired by existing x86 platform drivers, in special + * asus/eepc/fujitsu-laptop, thanks to their authors + * + * 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +#define ACPI_TOPSTAR_CLASS "topstar" + +struct topstar_hkey { + struct input_dev *inputdev; +}; + +struct tps_key_entry { + u8 code; + u16 keycode; +}; + +static struct tps_key_entry topstar_keymap[] = { + { 0x80, KEY_BRIGHTNESSUP }, + { 0x81, KEY_BRIGHTNESSDOWN }, + { 0x83, KEY_VOLUMEUP }, + { 0x84, KEY_VOLUMEDOWN }, + { 0x85, KEY_MUTE }, + { 0x86, KEY_SWITCHVIDEOMODE }, + { 0x87, KEY_F13 }, /* touchpad enable/disable key */ + { 0x88, KEY_WLAN }, + { 0x8a, KEY_WWW }, + { 0x8b, KEY_MAIL }, + { 0x8c, KEY_MEDIA }, + { 0x96, KEY_F14 }, /* G key? */ + { } +}; + +static struct tps_key_entry *tps_get_key_by_scancode(int code) +{ + struct tps_key_entry *key; + + for (key = topstar_keymap; key->code; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct tps_key_entry *tps_get_key_by_keycode(int code) +{ + struct tps_key_entry *key; + + for (key = topstar_keymap; key->code; key++) + if (code == key->keycode) + return key; + + return NULL; +} + +static void acpi_topstar_notify(struct acpi_device *device, u32 event) +{ + struct tps_key_entry *key; + static bool dup_evnt[2]; + bool *dup; + struct topstar_hkey *hkey = acpi_driver_data(device); + + /* 0x83 and 0x84 key events comes duplicated... */ + if (event == 0x83 || event == 0x84) { + dup = &dup_evnt[event - 0x83]; + if (*dup) { + *dup = false; + return; + } + *dup = true; + } + + /* + * 'G key' generate two event codes, convert to only + * one event/key code for now (3G switch?) + */ + if (event == 0x97) + event = 0x96; + + key = tps_get_key_by_scancode(event); + if (key) { + input_report_key(hkey->inputdev, key->keycode, 1); + input_sync(hkey->inputdev); + input_report_key(hkey->inputdev, key->keycode, 0); + input_sync(hkey->inputdev); + return; + } + + /* Known non hotkey events don't handled or that we don't care yet */ + if (event == 0x8e || event == 0x8f || event == 0x90) + return; + + pr_info("unknown event = 0x%02x\n", event); +} + +static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) +{ + acpi_status status; + union acpi_object fncx_params[1] = { + { .type = ACPI_TYPE_INTEGER } + }; + struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] }; + + fncx_params[0].integer.value = state ? 0x86 : 0x87; + status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL); + if (ACPI_FAILURE(status)) { + pr_err("Unable to switch FNCX notifications\n"); + return -ENODEV; + } + + return 0; +} + +static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct tps_key_entry *key = tps_get_key_by_scancode(scancode); + + if (!key) + return -EINVAL; + + *keycode = key->keycode; + return 0; +} + +static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct tps_key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = tps_get_key_by_scancode(scancode); + + if (!key) + return -EINVAL; + + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!tps_get_key_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; +} + +static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) +{ + struct tps_key_entry *key; + + hkey->inputdev = input_allocate_device(); + if (!hkey->inputdev) { + pr_err("Unable to allocate input device\n"); + return -ENODEV; + } + hkey->inputdev->name = "Topstar Laptop extra buttons"; + hkey->inputdev->phys = "topstar/input0"; + hkey->inputdev->id.bustype = BUS_HOST; + hkey->inputdev->getkeycode = topstar_getkeycode; + hkey->inputdev->setkeycode = topstar_setkeycode; + for (key = topstar_keymap; key->code; key++) { + set_bit(EV_KEY, hkey->inputdev->evbit); + set_bit(key->keycode, hkey->inputdev->keybit); + } + if (input_register_device(hkey->inputdev)) { + pr_err("Unable to register input device\n"); + input_free_device(hkey->inputdev); + return -ENODEV; + } + + return 0; +} + +static int acpi_topstar_add(struct acpi_device *device) +{ + struct topstar_hkey *tps_hkey; + + tps_hkey = kzalloc(sizeof(struct topstar_hkey), GFP_KERNEL); + if (!tps_hkey) + return -ENOMEM; + + strcpy(acpi_device_name(device), "Topstar TPSACPI"); + strcpy(acpi_device_class(device), ACPI_TOPSTAR_CLASS); + + if (acpi_topstar_fncx_switch(device, true)) + goto add_err; + + if (acpi_topstar_init_hkey(tps_hkey)) + goto add_err; + + device->driver_data = tps_hkey; + return 0; + +add_err: + kfree(tps_hkey); + return -ENODEV; +} + +static int acpi_topstar_remove(struct acpi_device *device, int type) +{ + struct topstar_hkey *tps_hkey = acpi_driver_data(device); + + acpi_topstar_fncx_switch(device, false); + + input_unregister_device(tps_hkey->inputdev); + kfree(tps_hkey); + + return 0; +} + +static const struct acpi_device_id topstar_device_ids[] = { + { "TPSACPI01", 0 }, + { "", 0 }, +}; +MODULE_DEVICE_TABLE(acpi, topstar_device_ids); + +static struct acpi_driver acpi_topstar_driver = { + .name = "Topstar laptop ACPI driver", + .class = ACPI_TOPSTAR_CLASS, + .ids = topstar_device_ids, + .ops = { + .add = acpi_topstar_add, + .remove = acpi_topstar_remove, + .notify = acpi_topstar_notify, + }, +}; + +static int __init topstar_laptop_init(void) +{ + int ret; + + ret = acpi_bus_register_driver(&acpi_topstar_driver); + if (ret < 0) + return ret; + + printk(KERN_INFO "Topstar Laptop ACPI extras driver loaded\n"); + + return 0; +} + +static void __exit topstar_laptop_exit(void) +{ + acpi_bus_unregister_driver(&acpi_topstar_driver); +} + +module_init(topstar_laptop_init); +module_exit(topstar_laptop_exit); + +MODULE_AUTHOR("Herton Ronaldo Krzesinski"); +MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 57c0c15b5244320065374ad2c54f4fbec77a6428 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 21 Sep 2009 12:20:38 +0200 Subject: perf: Tidy up after the big rename - provide compatibility Kconfig entry for existing PERF_COUNTERS .config's - provide courtesy copy of old perf_counter.h, for user-space projects - small indentation fixups - fix up MAINTAINERS - fix small x86 printout fallout - fix up small PowerPC comment fallout (use 'counter' as in register) Reviewed-by: Arjan van de Ven Acked-by: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Frederic Weisbecker LKML-Reference: Signed-off-by: Ingo Molnar --- MAINTAINERS | 2 +- arch/powerpc/include/asm/paca.h | 2 +- arch/powerpc/kernel/perf_event.c | 12 +- arch/x86/kernel/cpu/perf_event.c | 14 +- include/linux/perf_counter.h | 441 +++++++++++++++++++++++++++++++++++++++ include/linux/perf_event.h | 98 ++++----- init/Kconfig | 37 +++- kernel/perf_event.c | 4 +- 8 files changed, 534 insertions(+), 76 deletions(-) create mode 100644 include/linux/perf_counter.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 43761a00e3f1..751a307dc44e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4000,7 +4000,7 @@ S: Maintained F: include/linux/delayacct.h F: kernel/delayacct.c -PERFORMANCE COUNTER SUBSYSTEM +PERFORMANCE EVENTS SUBSYSTEM M: Peter Zijlstra M: Paul Mackerras M: Ingo Molnar diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 154f405b642f..7d8514ceceae 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -122,7 +122,7 @@ struct paca_struct { u8 soft_enabled; /* irq soft-enable flag */ u8 hard_enabled; /* set if irqs are enabled in MSR */ u8 io_sync; /* writel() needs spin_unlock sync */ - u8 perf_event_pending; /* PM interrupt while soft-disabled */ + u8 perf_event_pending; /* PM interrupt while soft-disabled */ /* Stuff for accurate time accounting */ u64 user_time; /* accumulated usermode TB ticks */ diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index c98321fcb459..197b7d958796 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -41,7 +41,7 @@ DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); struct power_pmu *ppmu; /* - * Normally, to ignore kernel events we set the FCS (freeze events + * Normally, to ignore kernel events we set the FCS (freeze counters * in supervisor mode) bit in MMCR0, but if the kernel runs with the * hypervisor bit set in the MSR, or if we are running on a processor * where the hypervisor bit is forced to 1 (as on Apple G5 processors), @@ -159,7 +159,7 @@ void perf_event_print_debug(void) } /* - * Read one performance monitor event (PMC). + * Read one performance monitor counter (PMC). */ static unsigned long read_pmc(int idx) { @@ -409,7 +409,7 @@ static void power_pmu_read(struct perf_event *event) val = read_pmc(event->hw.idx); } while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev); - /* The events are only 32 bits wide */ + /* The counters are only 32 bits wide */ delta = (val - prev) & 0xfffffffful; atomic64_add(delta, &event->count); atomic64_sub(delta, &event->hw.period_left); @@ -543,7 +543,7 @@ void hw_perf_disable(void) } /* - * Set the 'freeze events' bit. + * Set the 'freeze counters' bit. * The barrier is to make sure the mtspr has been * executed and the PMU has frozen the events * before we return. @@ -1124,7 +1124,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) } /* - * A event has overflowed; update its count and record + * A counter has overflowed; update its count and record * things if requested. Note that interrupts are hard-disabled * here so there is no possibility of being interrupted. */ @@ -1271,7 +1271,7 @@ static void perf_event_interrupt(struct pt_regs *regs) /* * Reset MMCR0 to its normal value. This will set PMXE and - * clear FC (freeze events) and PMAO (perf mon alert occurred) + * clear FC (freeze counters) and PMAO (perf mon alert occurred) * and thus allow interrupts to occur again. * XXX might want to use MSR.PM to keep the events frozen until * we get back out of this interrupt. diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 0d03629fb1a5..a3c7adb06b78 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -2081,13 +2081,13 @@ void __init init_hw_perf_events(void) perf_events_lapic_init(); register_die_notifier(&perf_event_nmi_notifier); - pr_info("... version: %d\n", x86_pmu.version); - pr_info("... bit width: %d\n", x86_pmu.event_bits); - pr_info("... generic events: %d\n", x86_pmu.num_events); - pr_info("... value mask: %016Lx\n", x86_pmu.event_mask); - pr_info("... max period: %016Lx\n", x86_pmu.max_period); - pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); - pr_info("... event mask: %016Lx\n", perf_event_mask); + pr_info("... version: %d\n", x86_pmu.version); + pr_info("... bit width: %d\n", x86_pmu.event_bits); + pr_info("... generic registers: %d\n", x86_pmu.num_events); + pr_info("... value mask: %016Lx\n", x86_pmu.event_mask); + pr_info("... max period: %016Lx\n", x86_pmu.max_period); + pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); + pr_info("... event mask: %016Lx\n", perf_event_mask); } static inline void x86_pmu_read(struct perf_event *event) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h new file mode 100644 index 000000000000..368bd70f1d2d --- /dev/null +++ b/include/linux/perf_counter.h @@ -0,0 +1,441 @@ +/* + * NOTE: this file will be removed in a future kernel release, it is + * provided as a courtesy copy of user-space code that relies on the + * old (pre-rename) symbols and constants. + * + * Performance events: + * + * Copyright (C) 2008-2009, Thomas Gleixner + * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar + * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra + * + * Data type definitions, declarations, prototypes. + * + * Started by: Thomas Gleixner and Ingo Molnar + * + * For licencing details see kernel-base/COPYING + */ +#ifndef _LINUX_PERF_COUNTER_H +#define _LINUX_PERF_COUNTER_H + +#include +#include +#include + +/* + * User-space ABI bits: + */ + +/* + * attr.type + */ +enum perf_type_id { + PERF_TYPE_HARDWARE = 0, + PERF_TYPE_SOFTWARE = 1, + PERF_TYPE_TRACEPOINT = 2, + PERF_TYPE_HW_CACHE = 3, + PERF_TYPE_RAW = 4, + + PERF_TYPE_MAX, /* non-ABI */ +}; + +/* + * Generalized performance counter event types, used by the + * attr.event_id parameter of the sys_perf_counter_open() + * syscall: + */ +enum perf_hw_id { + /* + * Common hardware events, generalized by the kernel: + */ + PERF_COUNT_HW_CPU_CYCLES = 0, + PERF_COUNT_HW_INSTRUCTIONS = 1, + PERF_COUNT_HW_CACHE_REFERENCES = 2, + PERF_COUNT_HW_CACHE_MISSES = 3, + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4, + PERF_COUNT_HW_BRANCH_MISSES = 5, + PERF_COUNT_HW_BUS_CYCLES = 6, + + PERF_COUNT_HW_MAX, /* non-ABI */ +}; + +/* + * Generalized hardware cache counters: + * + * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x + * { read, write, prefetch } x + * { accesses, misses } + */ +enum perf_hw_cache_id { + PERF_COUNT_HW_CACHE_L1D = 0, + PERF_COUNT_HW_CACHE_L1I = 1, + PERF_COUNT_HW_CACHE_LL = 2, + PERF_COUNT_HW_CACHE_DTLB = 3, + PERF_COUNT_HW_CACHE_ITLB = 4, + PERF_COUNT_HW_CACHE_BPU = 5, + + PERF_COUNT_HW_CACHE_MAX, /* non-ABI */ +}; + +enum perf_hw_cache_op_id { + PERF_COUNT_HW_CACHE_OP_READ = 0, + PERF_COUNT_HW_CACHE_OP_WRITE = 1, + PERF_COUNT_HW_CACHE_OP_PREFETCH = 2, + + PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */ +}; + +enum perf_hw_cache_op_result_id { + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0, + PERF_COUNT_HW_CACHE_RESULT_MISS = 1, + + PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */ +}; + +/* + * Special "software" counters provided by the kernel, even if the hardware + * does not support performance counters. These counters measure various + * physical and sw events of the kernel (and allow the profiling of them as + * well): + */ +enum perf_sw_ids { + PERF_COUNT_SW_CPU_CLOCK = 0, + PERF_COUNT_SW_TASK_CLOCK = 1, + PERF_COUNT_SW_PAGE_FAULTS = 2, + PERF_COUNT_SW_CONTEXT_SWITCHES = 3, + PERF_COUNT_SW_CPU_MIGRATIONS = 4, + PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, + + PERF_COUNT_SW_MAX, /* non-ABI */ +}; + +/* + * Bits that can be set in attr.sample_type to request information + * in the overflow packets. + */ +enum perf_counter_sample_format { + PERF_SAMPLE_IP = 1U << 0, + PERF_SAMPLE_TID = 1U << 1, + PERF_SAMPLE_TIME = 1U << 2, + PERF_SAMPLE_ADDR = 1U << 3, + PERF_SAMPLE_READ = 1U << 4, + PERF_SAMPLE_CALLCHAIN = 1U << 5, + PERF_SAMPLE_ID = 1U << 6, + PERF_SAMPLE_CPU = 1U << 7, + PERF_SAMPLE_PERIOD = 1U << 8, + PERF_SAMPLE_STREAM_ID = 1U << 9, + PERF_SAMPLE_RAW = 1U << 10, + + PERF_SAMPLE_MAX = 1U << 11, /* non-ABI */ +}; + +/* + * The format of the data returned by read() on a perf counter fd, + * as specified by attr.read_format: + * + * struct read_format { + * { u64 value; + * { u64 time_enabled; } && PERF_FORMAT_ENABLED + * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 id; } && PERF_FORMAT_ID + * } && !PERF_FORMAT_GROUP + * + * { u64 nr; + * { u64 time_enabled; } && PERF_FORMAT_ENABLED + * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 value; + * { u64 id; } && PERF_FORMAT_ID + * } cntr[nr]; + * } && PERF_FORMAT_GROUP + * }; + */ +enum perf_counter_read_format { + PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0, + PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, + PERF_FORMAT_ID = 1U << 2, + PERF_FORMAT_GROUP = 1U << 3, + + PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ +}; + +#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ + +/* + * Hardware event to monitor via a performance monitoring counter: + */ +struct perf_counter_attr { + + /* + * Major type: hardware/software/tracepoint/etc. + */ + __u32 type; + + /* + * Size of the attr structure, for fwd/bwd compat. + */ + __u32 size; + + /* + * Type specific configuration information. + */ + __u64 config; + + union { + __u64 sample_period; + __u64 sample_freq; + }; + + __u64 sample_type; + __u64 read_format; + + __u64 disabled : 1, /* off by default */ + inherit : 1, /* children inherit it */ + pinned : 1, /* must always be on PMU */ + exclusive : 1, /* only group on PMU */ + exclude_user : 1, /* don't count user */ + exclude_kernel : 1, /* ditto kernel */ + exclude_hv : 1, /* ditto hypervisor */ + exclude_idle : 1, /* don't count when idle */ + mmap : 1, /* include mmap data */ + comm : 1, /* include comm data */ + freq : 1, /* use freq, not period */ + inherit_stat : 1, /* per task counts */ + enable_on_exec : 1, /* next exec enables */ + task : 1, /* trace fork/exit */ + watermark : 1, /* wakeup_watermark */ + + __reserved_1 : 49; + + union { + __u32 wakeup_events; /* wakeup every n events */ + __u32 wakeup_watermark; /* bytes before wakeup */ + }; + __u32 __reserved_2; + + __u64 __reserved_3; +}; + +/* + * Ioctls that can be done on a perf counter fd: + */ +#define PERF_COUNTER_IOC_ENABLE _IO ('$', 0) +#define PERF_COUNTER_IOC_DISABLE _IO ('$', 1) +#define PERF_COUNTER_IOC_REFRESH _IO ('$', 2) +#define PERF_COUNTER_IOC_RESET _IO ('$', 3) +#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) +#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) + +enum perf_counter_ioc_flags { + PERF_IOC_FLAG_GROUP = 1U << 0, +}; + +/* + * Structure of the page that can be mapped via mmap + */ +struct perf_counter_mmap_page { + __u32 version; /* version number of this structure */ + __u32 compat_version; /* lowest version this is compat with */ + + /* + * Bits needed to read the hw counters in user-space. + * + * u32 seq; + * s64 count; + * + * do { + * seq = pc->lock; + * + * barrier() + * if (pc->index) { + * count = pmc_read(pc->index - 1); + * count += pc->offset; + * } else + * goto regular_read; + * + * barrier(); + * } while (pc->lock != seq); + * + * NOTE: for obvious reason this only works on self-monitoring + * processes. + */ + __u32 lock; /* seqlock for synchronization */ + __u32 index; /* hardware counter identifier */ + __s64 offset; /* add to hardware counter value */ + __u64 time_enabled; /* time counter active */ + __u64 time_running; /* time counter on cpu */ + + /* + * Hole for extension of the self monitor capabilities + */ + + __u64 __reserved[123]; /* align to 1k */ + + /* + * Control data for the mmap() data buffer. + * + * User-space reading the @data_head value should issue an rmb(), on + * SMP capable platforms, after reading this value -- see + * perf_counter_wakeup(). + * + * When the mapping is PROT_WRITE the @data_tail value should be + * written by userspace to reflect the last read data. In this case + * the kernel will not over-write unread data. + */ + __u64 data_head; /* head in the data section */ + __u64 data_tail; /* user-space written tail */ +}; + +#define PERF_EVENT_MISC_CPUMODE_MASK (3 << 0) +#define PERF_EVENT_MISC_CPUMODE_UNKNOWN (0 << 0) +#define PERF_EVENT_MISC_KERNEL (1 << 0) +#define PERF_EVENT_MISC_USER (2 << 0) +#define PERF_EVENT_MISC_HYPERVISOR (3 << 0) + +struct perf_event_header { + __u32 type; + __u16 misc; + __u16 size; +}; + +enum perf_event_type { + + /* + * The MMAP events record the PROT_EXEC mappings so that we can + * correlate userspace IPs to code. They have the following structure: + * + * struct { + * struct perf_event_header header; + * + * u32 pid, tid; + * u64 addr; + * u64 len; + * u64 pgoff; + * char filename[]; + * }; + */ + PERF_EVENT_MMAP = 1, + + /* + * struct { + * struct perf_event_header header; + * u64 id; + * u64 lost; + * }; + */ + PERF_EVENT_LOST = 2, + + /* + * struct { + * struct perf_event_header header; + * + * u32 pid, tid; + * char comm[]; + * }; + */ + PERF_EVENT_COMM = 3, + + /* + * struct { + * struct perf_event_header header; + * u32 pid, ppid; + * u32 tid, ptid; + * u64 time; + * }; + */ + PERF_EVENT_EXIT = 4, + + /* + * struct { + * struct perf_event_header header; + * u64 time; + * u64 id; + * u64 stream_id; + * }; + */ + PERF_EVENT_THROTTLE = 5, + PERF_EVENT_UNTHROTTLE = 6, + + /* + * struct { + * struct perf_event_header header; + * u32 pid, ppid; + * u32 tid, ptid; + * { u64 time; } && PERF_SAMPLE_TIME + * }; + */ + PERF_EVENT_FORK = 7, + + /* + * struct { + * struct perf_event_header header; + * u32 pid, tid; + * + * struct read_format values; + * }; + */ + PERF_EVENT_READ = 8, + + /* + * struct { + * struct perf_event_header header; + * + * { u64 ip; } && PERF_SAMPLE_IP + * { u32 pid, tid; } && PERF_SAMPLE_TID + * { u64 time; } && PERF_SAMPLE_TIME + * { u64 addr; } && PERF_SAMPLE_ADDR + * { u64 id; } && PERF_SAMPLE_ID + * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID + * { u32 cpu, res; } && PERF_SAMPLE_CPU + * { u64 period; } && PERF_SAMPLE_PERIOD + * + * { struct read_format values; } && PERF_SAMPLE_READ + * + * { u64 nr, + * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN + * + * # + * # The RAW record below is opaque data wrt the ABI + * # + * # That is, the ABI doesn't make any promises wrt to + * # the stability of its content, it may vary depending + * # on event, hardware, kernel version and phase of + * # the moon. + * # + * # In other words, PERF_SAMPLE_RAW contents are not an ABI. + * # + * + * { u32 size; + * char data[size];}&& PERF_SAMPLE_RAW + * }; + */ + PERF_EVENT_SAMPLE = 9, + + PERF_EVENT_MAX, /* non-ABI */ +}; + +enum perf_callchain_context { + PERF_CONTEXT_HV = (__u64)-32, + PERF_CONTEXT_KERNEL = (__u64)-128, + PERF_CONTEXT_USER = (__u64)-512, + + PERF_CONTEXT_GUEST = (__u64)-2048, + PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176, + PERF_CONTEXT_GUEST_USER = (__u64)-2560, + + PERF_CONTEXT_MAX = (__u64)-4095, +}; + +#define PERF_FLAG_FD_NO_GROUP (1U << 0) +#define PERF_FLAG_FD_OUTPUT (1U << 1) + +/* + * In case some app still references the old symbols: + */ + +#define __NR_perf_counter_open __NR_perf_event_open + +#define PR_TASK_PERF_COUNTERS_DISABLE PR_TASK_PERF_EVENTS_DISABLE +#define PR_TASK_PERF_COUNTERS_ENABLE PR_TASK_PERF_EVENTS_ENABLE + +#endif /* _LINUX_PERF_COUNTER_H */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ae9d9ed6df2a..acefaf71e6dd 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1,15 +1,15 @@ /* - * Performance events: + * Performance events: * * Copyright (C) 2008-2009, Thomas Gleixner * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra * - * Data type definitions, declarations, prototypes. + * Data type definitions, declarations, prototypes. * * Started by: Thomas Gleixner and Ingo Molnar * - * For licencing details see kernel-base/COPYING + * For licencing details see kernel-base/COPYING */ #ifndef _LINUX_PERF_EVENT_H #define _LINUX_PERF_EVENT_H @@ -131,19 +131,19 @@ enum perf_event_sample_format { * as specified by attr.read_format: * * struct read_format { - * { u64 value; - * { u64 time_enabled; } && PERF_FORMAT_ENABLED - * { u64 time_running; } && PERF_FORMAT_RUNNING - * { u64 id; } && PERF_FORMAT_ID - * } && !PERF_FORMAT_GROUP + * { u64 value; + * { u64 time_enabled; } && PERF_FORMAT_ENABLED + * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 id; } && PERF_FORMAT_ID + * } && !PERF_FORMAT_GROUP * - * { u64 nr; - * { u64 time_enabled; } && PERF_FORMAT_ENABLED - * { u64 time_running; } && PERF_FORMAT_RUNNING - * { u64 value; - * { u64 id; } && PERF_FORMAT_ID - * } cntr[nr]; - * } && PERF_FORMAT_GROUP + * { u64 nr; + * { u64 time_enabled; } && PERF_FORMAT_ENABLED + * { u64 time_running; } && PERF_FORMAT_RUNNING + * { u64 value; + * { u64 id; } && PERF_FORMAT_ID + * } cntr[nr]; + * } && PERF_FORMAT_GROUP * }; */ enum perf_event_read_format { @@ -152,7 +152,7 @@ enum perf_event_read_format { PERF_FORMAT_ID = 1U << 2, PERF_FORMAT_GROUP = 1U << 3, - PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ + PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ }; #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ @@ -216,8 +216,8 @@ struct perf_event_attr { * Ioctls that can be done on a perf event fd: */ #define PERF_EVENT_IOC_ENABLE _IO ('$', 0) -#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) -#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) +#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) +#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) #define PERF_EVENT_IOC_RESET _IO ('$', 3) #define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64) #define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) @@ -314,9 +314,9 @@ enum perf_event_type { /* * struct { - * struct perf_event_header header; - * u64 id; - * u64 lost; + * struct perf_event_header header; + * u64 id; + * u64 lost; * }; */ PERF_RECORD_LOST = 2, @@ -383,23 +383,23 @@ enum perf_event_type { * { u64 id; } && PERF_SAMPLE_ID * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID * { u32 cpu, res; } && PERF_SAMPLE_CPU - * { u64 period; } && PERF_SAMPLE_PERIOD + * { u64 period; } && PERF_SAMPLE_PERIOD * * { struct read_format values; } && PERF_SAMPLE_READ * * { u64 nr, * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN * - * # - * # The RAW record below is opaque data wrt the ABI - * # - * # That is, the ABI doesn't make any promises wrt to - * # the stability of its content, it may vary depending - * # on event_id, hardware, kernel version and phase of - * # the moon. - * # - * # In other words, PERF_SAMPLE_RAW contents are not an ABI. - * # + * # + * # The RAW record below is opaque data wrt the ABI + * # + * # That is, the ABI doesn't make any promises wrt to + * # the stability of its content, it may vary depending + * # on event, hardware, kernel version and phase of + * # the moon. + * # + * # In other words, PERF_SAMPLE_RAW contents are not an ABI. + * # * * { u32 size; * char data[size];}&& PERF_SAMPLE_RAW @@ -503,10 +503,10 @@ struct pmu { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { - PERF_EVENT_STATE_ERROR = -2, + PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, PERF_EVENT_STATE_INACTIVE = 0, - PERF_EVENT_STATE_ACTIVE = 1, + PERF_EVENT_STATE_ACTIVE = 1, }; struct file; @@ -529,7 +529,7 @@ struct perf_mmap_data { long watermark; /* wakeup watermark */ - struct perf_event_mmap_page *user_page; + struct perf_event_mmap_page *user_page; void *data_pages[0]; }; @@ -694,14 +694,14 @@ struct perf_cpu_context { }; struct perf_output_handle { - struct perf_event *event; - struct perf_mmap_data *data; - unsigned long head; - unsigned long offset; - int nmi; - int sample; - int locked; - unsigned long flags; + struct perf_event *event; + struct perf_mmap_data *data; + unsigned long head; + unsigned long offset; + int nmi; + int sample; + int locked; + unsigned long flags; }; #ifdef CONFIG_PERF_EVENTS @@ -829,22 +829,22 @@ static inline void perf_event_task_sched_out(struct task_struct *task, struct task_struct *next, int cpu) { } static inline void -perf_event_task_tick(struct task_struct *task, int cpu) { } +perf_event_task_tick(struct task_struct *task, int cpu) { } static inline int perf_event_init_task(struct task_struct *child) { return 0; } static inline void perf_event_exit_task(struct task_struct *child) { } static inline void perf_event_free_task(struct task_struct *task) { } -static inline void perf_event_do_pending(void) { } -static inline void perf_event_print_debug(void) { } +static inline void perf_event_do_pending(void) { } +static inline void perf_event_print_debug(void) { } static inline void perf_disable(void) { } static inline void perf_enable(void) { } -static inline int perf_event_task_disable(void) { return -EINVAL; } -static inline int perf_event_task_enable(void) { return -EINVAL; } +static inline int perf_event_task_disable(void) { return -EINVAL; } +static inline int perf_event_task_enable(void) { return -EINVAL; } static inline void perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) { } -static inline void perf_event_mmap(struct vm_area_struct *vma) { } +static inline void perf_event_mmap(struct vm_area_struct *vma) { } static inline void perf_event_comm(struct task_struct *tsk) { } static inline void perf_event_fork(struct task_struct *tsk) { } static inline void perf_event_init(void) { } diff --git a/init/Kconfig b/init/Kconfig index cfdf5c322806..706728be312f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -920,26 +920,31 @@ config HAVE_PERF_EVENTS help See tools/perf/design.txt for details. -menu "Performance Counters" +menu "Kernel Performance Events And Counters" config PERF_EVENTS - bool "Kernel Performance Counters" - default y if PROFILING + bool "Kernel performance events and counters" + default y if (PROFILING || PERF_COUNTERS) depends on HAVE_PERF_EVENTS select ANON_INODES help - Enable kernel support for performance counter hardware. + Enable kernel support for various performance events provided + by software and hardware. - Performance counters are special hardware registers available - on most modern CPUs. These registers count the number of certain + Software events are supported either build-in or via the + use of generic tracepoints. + + Most modern CPUs support performance events via performance + counter registers. These registers count the number of certain types of hw events: such as instructions executed, cachemisses suffered, or branches mis-predicted - without slowing down the kernel or applications. These registers can also trigger interrupts when a threshold number of events have passed - and can thus be used to profile the code that runs on that CPU. - The Linux Performance Counter subsystem provides an abstraction of - these hardware capabilities, available via a system call. It + The Linux Performance Event subsystem provides an abstraction of + these software and hardware cevent apabilities, available via a + system call and used by the "perf" utility in tools/perf/. It provides per task and per CPU counters, and it provides event capabilities on top of those. @@ -950,14 +955,26 @@ config EVENT_PROFILE depends on PERF_EVENTS && EVENT_TRACING default y help - Allow the use of tracepoints as software performance counters. + Allow the use of tracepoints as software performance events. - When this is enabled, you can create perf counters based on + When this is enabled, you can create perf events based on tracepoints using PERF_TYPE_TRACEPOINT and the tracepoint ID found in debugfs://tracing/events/*/*/id. (The -e/--events option to the perf tool can parse and interpret symbolic tracepoints, in the subsystem:tracepoint_name format.) +config PERF_COUNTERS + bool "Kernel performance counters (old config option)" + depends on HAVE_PERF_EVENTS + help + This config has been obsoleted by the PERF_EVENTS + config option - please see that one for details. + + It has no effect on the kernel whether you enable + it or not, it is a compatibility placeholder. + + Say N if unsure. + endmenu config VM_EVENT_COUNTERS diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 6e8b99a04e1e..76ac4db405e9 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1,12 +1,12 @@ /* - * Performance event core code + * Performance events core code: * * Copyright (C) 2008 Thomas Gleixner * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra * Copyright © 2009 Paul Mackerras, IBM Corp. * - * For licensing details see kernel-base/COPYING + * For licensing details see kernel-base/COPYING */ #include -- cgit v1.2.3 From cf83011d8faec99de51d6ba8879c0c61cf31e836 Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Fri, 12 Jun 2009 01:00:28 +0200 Subject: trivial: update the Kernel Janitors' web-page URL The former address cannot be resolved. Signed-off-by: Markus Heidelberg Signed-off-by: Jiri Kosina --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 43761a00e3f1..64d41776c783 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2955,7 +2955,7 @@ F: scripts/Makefile.* KERNEL JANITORS L: kernel-janitors@vger.kernel.org W: http://www.kerneljanitors.org/ -S: Odd fixes +S: Maintained KERNEL NFSD, SUNRPC, AND LOCKD SERVERS M: "J. Bruce Fields" -- cgit v1.2.3 From dfdd8cc903288bb2e2ad6731545be3db7304c133 Mon Sep 17 00:00:00 2001 From: Krzysztof HaÅ‚asa Date: Mon, 21 Sep 2009 18:31:24 +0200 Subject: Add MAINTAINERS entry for ARM/INTEL IXP4xx arch support. Signed-off-by: Krzysztof HaÅ‚asa --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 751a307dc44e..7bf7045337e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -685,6 +685,13 @@ M: Lennert Buytenhek L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +ARM/INTEL IXP4XX ARM ARCHITECTURE +M: Imre Kaloz +M: Krzysztof Halasa +L: linux-arm-kernel@lists.infradead.org +S: Maintained +F: arch/arm/mach-ixp4xx/ + ARM/INTEL XSC3 (MANZANO) ARM CORE M: Lennert Buytenhek M: Dan Williams -- cgit v1.2.3 From 5be461657be65460ad92be3527e3bb1dd11c49ea Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 21 Sep 2009 17:00:59 -0700 Subject: sdhci: orphan driver and list Remove myself as maintainer from the sdhci driver and steer people towards the new MMC list for discussing it. Signed-off-by: Pierre Ossman Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 751a307dc44e..b212f55b6a2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4533,20 +4533,20 @@ S: Maintained F: drivers/mmc/host/sdricoh_cs.c SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER -M: Pierre Ossman -L: sdhci-devel@lists.ossman.eu -S: Maintained +S: Orphan +L: linux-mmc@vger.kernel.org +F: drivers/mmc/host/sdhci.* SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) M: Anton Vorontsov L: linuxppc-dev@ozlabs.org -L: sdhci-devel@lists.ossman.eu +L: linux-mmc@vger.kernel.org S: Maintained -F: drivers/mmc/host/sdhci.* +F: drivers/mmc/host/sdhci-of.* SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER M: Ben Dooks -L: sdhci-devel@lists.ossman.eu +L: linux-mmc@vger.kernel.org S: Maintained F: drivers/mmc/host/sdhci-s3c.c -- cgit v1.2.3 From b61d4a71e483fe1aa1c4b170c28d85be77edce4f Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Mon, 21 Sep 2009 17:04:12 -0700 Subject: MAINTAINERS: add IPVS include files Signed-off-by: Hannes Eder Cc: Joe Perches Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index b212f55b6a2e..ee58af192c40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2803,6 +2803,8 @@ L: netdev@vger.kernel.org L: lvs-devel@vger.kernel.org S: Maintained F: Documentation/networking/ipvs-sysctl.txt +F: include/net/ip_vs.h +F: include/linux/ip_vs.h F: net/netfilter/ipvs/ IPWIRELESS DRIVER -- cgit v1.2.3 From 43368e74d126f8e874fce2c248f094edfcf0baa6 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Mon, 21 Sep 2009 17:04:24 -0700 Subject: MAINTAINERS: acpi: add 'include/acpi' Signed-off-by: Felipe Contreras Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index ee58af192c40..8d30ce808d63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -233,6 +233,7 @@ S: Supported F: drivers/acpi/ F: drivers/pnp/pnpacpi/ F: include/linux/acpi.h +F: include/acpi/ ACPI BATTERY DRIVERS M: Alexey Starikovskiy -- cgit v1.2.3 From 4e04d5a3d57accb0b05d381aa84d93d3749b15e2 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Mon, 21 Sep 2009 17:04:25 -0700 Subject: MAINTAINERS: omap: fix regex Otherwise 'arch/arm/*omap*/foo.c' wouldn't match Signed-off-by: Felipe Contreras Cc: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 8d30ce808d63..4dd43f8621ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3737,7 +3737,7 @@ W: http://www.muru.com/linux/omap/ W: http://linux.omap.com/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git S: Maintained -F: arch/arm/*omap* +F: arch/arm/*omap*/ OMAP CLOCK FRAMEWORK SUPPORT M: Paul Walmsley -- cgit v1.2.3 From 076cfaaece1c4e57ea7d924f38b911b9a5502365 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 21 Sep 2009 17:04:26 -0700 Subject: MAINTAINERS: integrate P:/M: lines A couple of new uses of separate "P: name" "M: address" lines are converted to single line "M: name
" Signed-off-by: Joe Perches Cc: Anil Ravindranath Cc: Kalle Valo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 4dd43f8621ec..7e54faf992cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4028,8 +4028,7 @@ F: drivers/block/pktcdvd.c F: include/linux/pktcdvd.h PMC SIERRA MaxRAID DRIVER -P: Anil Ravindranath -M: anil_ravindranath@pmc-sierra.com +M: Anil Ravindranath L: linux-scsi@vger.kernel.org W: http://www.pmc-sierra.com/ S: Supported @@ -5660,8 +5659,7 @@ S: Maintained F: drivers/input/misc/wistron_btns.c WL1251 WIRELESS DRIVER -P: Kalle Valo -M: kalle.valo@nokia.com +M: Kalle Valo L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git -- cgit v1.2.3 From efc03ecb9d674588a13aee27289c2af2afe5e6b4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 21 Sep 2009 17:04:27 -0700 Subject: MAINTAINERS: move ARM lists to infradead Signed-off-by: Joe Perches Cc: Sebastian Andrzej Siewior Cc: Krzysztof Halasa Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 106 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 53 insertions(+), 53 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 7e54faf992cb..379db50951d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -498,7 +498,7 @@ F: arch/arm/include/asm/floppy.h ARM PORT M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/ @@ -509,36 +509,36 @@ F: drivers/mmc/host/mmci.* ARM/ADI ROADRUNNER MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ixp23xx/ F: arch/arm/mach-ixp23xx/include/mach/ ARM/ADS SPHERE MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/AFEB9260 MACHINE SUPPORT M: Sergey Lapin -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/AJECO 1ARM MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/ATMEL AT91RM9200 ARM ARCHITECTURE M: Andrew Victor -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://maxim.org.za/at91_26.html S: Maintained ARM/BCMRING ARM ARCHITECTURE M: Leo Chen M: Scott Branden -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-bcmring @@ -555,25 +555,25 @@ F: drivers/mtd/nand/nand_bcm_umi.h ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE M: Hartley Sweeten M: Ryan Mallon -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ep93xx/ F: arch/arm/mach-ep93xx/include/mach/ ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/CLKDEV SUPPORT M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) F: arch/arm/common/clkdev.c F: arch/arm/include/asm/clkdev.h ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT M: Mike Rapoport -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/CORGI MACHINE SUPPORT @@ -582,14 +582,14 @@ S: Maintained ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE M: Paulius Zaleckas -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://gitorious.org/linux-gemini/mainline.git S: Maintained F: arch/arm/mach-gemini/ ARM/EBSA110 MACHINE SUPPORT M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/mach-ebsa110/ @@ -607,13 +607,13 @@ F: arch/arm/mach-pxa/ezx.c ARM/FARADAY FA526 PORT M: Paulius Zaleckas -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mm/*-fa* ARM/FOOTBRIDGE ARCHITECTURE M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/include/asm/hardware/dec21285.h @@ -621,17 +621,17 @@ F: arch/arm/mach-footbridge/ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE M: Sascha Hauer -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/GLOMATION GESBC9312SX MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/GUMSTIX MACHINE SUPPORT M: Steve Sakoman -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT @@ -651,55 +651,55 @@ F: arch/arm/mach-sa1100/include/mach/jornada720.h ARM/INTEL IOP32X ARM ARCHITECTURE M: Lennert Buytenhek M: Dan Williams -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported ARM/INTEL IOP33X ARM ARCHITECTURE M: Dan Williams -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported ARM/INTEL IOP13XX ARM ARCHITECTURE M: Lennert Buytenhek M: Dan Williams -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported ARM/INTEL IQ81342EX MACHINE SUPPORT M: Lennert Buytenhek M: Dan Williams -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported ARM/INTEL IXP2000 ARM ARCHITECTURE M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IXDP2850 MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL IXP23XX ARM ARCHITECTURE M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/INTEL XSC3 (MANZANO) ARM CORE M: Lennert Buytenhek M: Dan Williams -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/LOGICPD PXA270 MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/MAGICIAN MACHINE SUPPORT @@ -709,7 +709,7 @@ S: Maintained ARM/Marvell Loki/Kirkwood/MV78xx0/Orion SOC support M: Lennert Buytenhek M: Nicolas Pitre -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://git.marvell.com/orion S: Maintained F: arch/arm/mach-loki/ @@ -720,7 +720,7 @@ F: arch/arm/plat-orion/ ARM/MIOA701 MACHINE SUPPORT M: Robert Jarzmik -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) F: arch/arm/mach-pxa/mioa701.c S: Maintained @@ -761,18 +761,18 @@ S: Maintained ARM/PT DIGITAL BOARD PORT M: Stefan Eletzhofer -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained ARM/RADISYS ENP2611 MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/RISCPC ARCHITECTURE M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/common/time-acorn.c @@ -791,7 +791,7 @@ S: Maintained ARM/SAMSUNG ARM ARCHITECTURES M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/plat-s3c/ @@ -799,65 +799,65 @@ F: arch/arm/plat-s3c24xx/ ARM/S3C2410 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2410/ ARM/S3C2440 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2440/ ARM/S3C2442 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2442/ ARM/S3C2443 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c2443/ ARM/S3C6400 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c6400/ ARM/S3C6410 ARM ARCHITECTURE M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.fluff.org/ben/linux/ S: Maintained F: arch/arm/mach-s3c6410/ ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/THECUS N2100 MACHINE SUPPORT M: Lennert Buytenhek -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained ARM/NUVOTON W90X900 ARM ARCHITECTURE M: Wan ZongShun -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.mcuos.com S: Maintained ARM/VFP SUPPORT M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/vfp/ @@ -964,7 +964,7 @@ F: include/linux/atm* ATMEL AT91 MCI DRIVER M: Nicolas Ferre -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.atmel.com/products/AT91/ W: http://www.at91.com/ S: Maintained @@ -1542,7 +1542,7 @@ F: drivers/infiniband/hw/cxgb3/ CYBERPRO FB DRIVER M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.arm.linux.org.uk/ S: Maintained F: drivers/video/cyber2000fb.* @@ -2086,7 +2086,7 @@ F: drivers/i2c/busses/i2c-cpm.c FREESCALE IMX / MXC FRAMEBUFFER DRIVER M: Sascha Hauer L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/plat-mxc/include/mach/imxfb.h F: drivers/video/imxfb.c @@ -3452,7 +3452,7 @@ F: include/linux/meye.h MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER M: Pavel Pisa -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: drivers/mmc/host/imxmmc.* @@ -4170,7 +4170,7 @@ F: drivers/media/video/pvrusb2/ PXA2xx/PXA3xx SUPPORT M: Eric Miao M: Russell King -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-pxa/ F: drivers/pcmcia/pxa2xx* @@ -4183,13 +4183,13 @@ F: sound/soc/pxa PXA168 SUPPORT M: Eric Miao M: Jason Chagas -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Maintained PXA910 SUPPORT M: Eric Miao -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Maintained @@ -4430,7 +4430,7 @@ F: net/iucv/ S3C24XX SD/MMC Driver M: Ben Dooks -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported F: drivers/mmc/host/s3cmci.* @@ -4634,7 +4634,7 @@ F: drivers/misc/sgi-xp/ SHARP LH SUPPORT (LH7952X & LH7A40X) M: Marc Singer W: http://projects.buici.com/arm -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen F: arch/arm/mach-lh7a40x/ -- cgit v1.2.3 From e258b80e691f1f3ae83a60aa80eaf7322bd55ec4 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 21 Sep 2009 17:04:53 -0700 Subject: input: add a driver for the Winbond WPCD376I Consumer IR hardware Add a driver for the the Consumer IR (CIR) functionality of the Winbond WPCD376I chipset (found on e.g. Intel DG45FC motherboards). Signed-off-by: David Härdeman Reviewed-by: Jesse Barnes Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 6 + drivers/input/misc/Kconfig | 16 + drivers/input/misc/Makefile | 1 + drivers/input/misc/winbond-cir.c | 1614 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 1637 insertions(+) create mode 100644 drivers/input/misc/winbond-cir.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 379db50951d3..da7a811f76a6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5640,6 +5640,12 @@ L: linux-scsi@vger.kernel.org S: Maintained F: drivers/scsi/wd7000.c +WINBOND CIR DRIVER +P: David Härdeman +M: david@hardeman.nu +S: Maintained +F: drivers/input/misc/winbond-cir.c + WIMAX STACK M: Inaky Perez-Gonzalez M: linux-wimax@intel.com diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1a50be379cbc..76d6751f89a7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -222,6 +222,22 @@ config INPUT_SGI_BTNS To compile this driver as a module, choose M here: the module will be called sgi_btns. +config INPUT_WINBOND_CIR + tristate "Winbond IR remote control" + depends on X86 && PNP + select LEDS_CLASS + select BITREVERSE + help + Say Y here if you want to use the IR remote functionality found + in some Winbond SuperI/O chips. Currently only the WPCD376I + chip is supported (included in some Intel Media series motherboards). + + IR Receive and wake-on-IR from suspend and power-off is currently + supported. + + To compile this driver as a module, choose M here: the module will be + called winbond_cir. + config HP_SDC_RTC tristate "HP SDC Real Time Clock" depends on (GSC || HP300) && SERIO diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index bf4db626c313..a8b84854fb7b 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o +obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c new file mode 100644 index 000000000000..33309fe44e20 --- /dev/null +++ b/drivers/input/misc/winbond-cir.c @@ -0,0 +1,1614 @@ +/* + * winbond-cir.c - Driver for the Consumer IR functionality of Winbond + * SuperI/O chips. + * + * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but + * could probably support others (Winbond WEC102X, NatSemi, etc) + * with minor modifications. + * + * Original Author: David Härdeman + * Copyright (C) 2009 David Härdeman + * + * Dedicated to Matilda, my newborn daughter, without whose loving attention + * this driver would have been finished in half the time and with a fraction + * of the bugs. + * + * Written using: + * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel + * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff) + * o DSDT dumps + * + * Supported features: + * o RC6 + * o Wake-On-CIR functionality + * + * To do: + * o Test NEC and RC5 + * + * Left as an exercise for the reader: + * o Learning (I have neither the hardware, nor the need) + * o IR Transmit (ibid) + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "winbond-cir" + +/* CEIR Wake-Up Registers, relative to data->wbase */ +#define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */ +#define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */ +#define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */ +#define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */ +#define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */ +#define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */ +#define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */ +#define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */ +#define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */ +#define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */ + +/* CEIR Enhanced Functionality Registers, relative to data->ebase */ +#define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */ +#define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */ +#define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */ +#define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */ +#define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */ + +/* SP3 Banked Registers, relative to data->sbase */ +#define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */ + /* Bank 0 */ +#define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */ +#define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */ +#define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */ +#define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */ +#define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */ +#define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */ +#define WBCIR_REG_SP3_LSR 0x05 /* Link Status */ +#define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */ +#define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */ + /* Bank 2 */ +#define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */ +#define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */ +#define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */ +#define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */ +#define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */ +#define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */ + /* Bank 3 */ +#define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */ +#define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */ +#define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */ + /* Bank 4 */ +#define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */ + /* Bank 5 */ +#define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */ + /* Bank 6 */ +#define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */ +#define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */ + /* Bank 7 */ +#define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */ +#define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */ +#define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */ +#define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */ +#define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ + +/* + * Magic values follow + */ + +/* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_NONE 0x00 +/* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_RX 0x01 +/* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ +#define WBCIR_IRQ_ERR 0x04 +/* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ +#define WBCIR_LED_ENABLE 0x80 +/* RX data available bit for WBCIR_REG_SP3_LSR */ +#define WBCIR_RX_AVAIL 0x01 +/* RX disable bit for WBCIR_REG_SP3_ASCR */ +#define WBCIR_RX_DISABLE 0x20 +/* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ +#define WBCIR_EXT_ENABLE 0x01 +/* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ +#define WBCIR_REGSEL_COMPARE 0x10 +/* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ +#define WBCIR_REGSEL_MASK 0x20 +/* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */ +#define WBCIR_REG_ADDR0 0x00 + +/* Valid banks for the SP3 UART */ +enum wbcir_bank { + WBCIR_BANK_0 = 0x00, + WBCIR_BANK_1 = 0x80, + WBCIR_BANK_2 = 0xE0, + WBCIR_BANK_3 = 0xE4, + WBCIR_BANK_4 = 0xE8, + WBCIR_BANK_5 = 0xEC, + WBCIR_BANK_6 = 0xF0, + WBCIR_BANK_7 = 0xF4, +}; + +/* Supported IR Protocols */ +enum wbcir_protocol { + IR_PROTOCOL_RC5 = 0x0, + IR_PROTOCOL_NEC = 0x1, + IR_PROTOCOL_RC6 = 0x2, +}; + +/* Misc */ +#define WBCIR_NAME "Winbond CIR" +#define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ +#define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ +#define IR_KEYPRESS_TIMEOUT 250 /* FIXME: should be per-protocol? */ +#define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ +#define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ +#define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ +#define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ +#define WBCIR_MAX_IDLE_BYTES 10 + +static DEFINE_SPINLOCK(wbcir_lock); +static DEFINE_RWLOCK(keytable_lock); + +struct wbcir_key { + u32 scancode; + unsigned int keycode; +}; + +struct wbcir_keyentry { + struct wbcir_key key; + struct list_head list; +}; + +static struct wbcir_key rc6_def_keymap[] = { + { 0x800F0400, KEY_NUMERIC_0 }, + { 0x800F0401, KEY_NUMERIC_1 }, + { 0x800F0402, KEY_NUMERIC_2 }, + { 0x800F0403, KEY_NUMERIC_3 }, + { 0x800F0404, KEY_NUMERIC_4 }, + { 0x800F0405, KEY_NUMERIC_5 }, + { 0x800F0406, KEY_NUMERIC_6 }, + { 0x800F0407, KEY_NUMERIC_7 }, + { 0x800F0408, KEY_NUMERIC_8 }, + { 0x800F0409, KEY_NUMERIC_9 }, + { 0x800F041D, KEY_NUMERIC_STAR }, + { 0x800F041C, KEY_NUMERIC_POUND }, + { 0x800F0410, KEY_VOLUMEUP }, + { 0x800F0411, KEY_VOLUMEDOWN }, + { 0x800F0412, KEY_CHANNELUP }, + { 0x800F0413, KEY_CHANNELDOWN }, + { 0x800F040E, KEY_MUTE }, + { 0x800F040D, KEY_VENDOR }, /* Vista Logo Key */ + { 0x800F041E, KEY_UP }, + { 0x800F041F, KEY_DOWN }, + { 0x800F0420, KEY_LEFT }, + { 0x800F0421, KEY_RIGHT }, + { 0x800F0422, KEY_OK }, + { 0x800F0423, KEY_ESC }, + { 0x800F040F, KEY_INFO }, + { 0x800F040A, KEY_CLEAR }, + { 0x800F040B, KEY_ENTER }, + { 0x800F045B, KEY_RED }, + { 0x800F045C, KEY_GREEN }, + { 0x800F045D, KEY_YELLOW }, + { 0x800F045E, KEY_BLUE }, + { 0x800F045A, KEY_TEXT }, + { 0x800F0427, KEY_SWITCHVIDEOMODE }, + { 0x800F040C, KEY_POWER }, + { 0x800F0450, KEY_RADIO }, + { 0x800F0448, KEY_PVR }, + { 0x800F0447, KEY_AUDIO }, + { 0x800F0426, KEY_EPG }, + { 0x800F0449, KEY_CAMERA }, + { 0x800F0425, KEY_TV }, + { 0x800F044A, KEY_VIDEO }, + { 0x800F0424, KEY_DVD }, + { 0x800F0416, KEY_PLAY }, + { 0x800F0418, KEY_PAUSE }, + { 0x800F0419, KEY_STOP }, + { 0x800F0414, KEY_FASTFORWARD }, + { 0x800F041A, KEY_NEXT }, + { 0x800F041B, KEY_PREVIOUS }, + { 0x800F0415, KEY_REWIND }, + { 0x800F0417, KEY_RECORD }, +}; + +/* Registers and other state is protected by wbcir_lock */ +struct wbcir_data { + unsigned long wbase; /* Wake-Up Baseaddr */ + unsigned long ebase; /* Enhanced Func. Baseaddr */ + unsigned long sbase; /* Serial Port Baseaddr */ + unsigned int irq; /* Serial Port IRQ */ + + struct input_dev *input_dev; + struct timer_list timer_keyup; + struct led_trigger *rxtrigger; + struct led_trigger *txtrigger; + struct led_classdev led; + + u32 last_scancode; + unsigned int last_keycode; + u8 last_toggle; + u8 keypressed; + unsigned long keyup_jiffies; + unsigned int idle_count; + + /* RX irdata and parsing state */ + unsigned long irdata[30]; + unsigned int irdata_count; + unsigned int irdata_idle; + unsigned int irdata_off; + unsigned int irdata_error; + + /* Protected by keytable_lock */ + struct list_head keytable; +}; + +static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; +module_param(protocol, uint, 0444); +MODULE_PARM_DESC(protocol, "IR protocol to use " + "(0 = RC5, 1 = NEC, 2 = RC6A, default)"); + +static int invert; /* default = 0 */ +module_param(invert, bool, 0444); +MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); + +static unsigned int wake_sc = 0x800F040C; +module_param(wake_sc, uint, 0644); +MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); + +static unsigned int wake_rc6mode = 6; +module_param(wake_rc6mode, uint, 0644); +MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command " + "(0 = 0, 6 = 6A, default)"); + + + +/***************************************************************************** + * + * UTILITY FUNCTIONS + * + *****************************************************************************/ + +/* Caller needs to hold wbcir_lock */ +static void +wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) +{ + u8 val; + + val = inb(addr); + val = ((val & ~mask) | (bits & mask)); + outb(val, addr); +} + +/* Selects the register bank for the serial port */ +static inline void +wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) +{ + outb(bank, data->sbase + WBCIR_REG_SP3_BSR); +} + +static enum led_brightness +wbcir_led_brightness_get(struct led_classdev *led_cdev) +{ + struct wbcir_data *data = container_of(led_cdev, + struct wbcir_data, + led); + + if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE) + return LED_FULL; + else + return LED_OFF; +} + +static void +wbcir_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct wbcir_data *data = container_of(led_cdev, + struct wbcir_data, + led); + + wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, + brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE, + WBCIR_LED_ENABLE); +} + +/* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */ +static u8 +wbcir_to_rc6cells(u8 val) +{ + u8 coded = 0x00; + int i; + + val &= 0x0F; + for (i = 0; i < 4; i++) { + if (val & 0x01) + coded |= 0x02 << (i * 2); + else + coded |= 0x01 << (i * 2); + val >>= 1; + } + + return coded; +} + + + +/***************************************************************************** + * + * INPUT FUNCTIONS + * + *****************************************************************************/ + +static unsigned int +wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) +{ + struct wbcir_keyentry *keyentry; + unsigned int keycode = KEY_RESERVED; + unsigned long flags; + + read_lock_irqsave(&keytable_lock, flags); + + list_for_each_entry(keyentry, &data->keytable, list) { + if (keyentry->key.scancode == scancode) { + keycode = keyentry->key.keycode; + break; + } + } + + read_unlock_irqrestore(&keytable_lock, flags); + return keycode; +} + +static int +wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct wbcir_data *data = input_get_drvdata(dev); + + *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); + return 0; +} + +static int +wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) +{ + struct wbcir_data *data = input_get_drvdata(dev); + struct wbcir_keyentry *keyentry; + struct wbcir_keyentry *new_keyentry; + unsigned long flags; + unsigned int old_keycode = KEY_RESERVED; + u32 scancode = (u32)sscancode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); + if (!new_keyentry) + return -ENOMEM; + + write_lock_irqsave(&keytable_lock, flags); + + list_for_each_entry(keyentry, &data->keytable, list) { + if (keyentry->key.scancode != scancode) + continue; + + old_keycode = keyentry->key.keycode; + keyentry->key.keycode = keycode; + + if (keyentry->key.keycode == KEY_RESERVED) { + list_del(&keyentry->list); + kfree(keyentry); + } + + break; + } + + set_bit(keycode, dev->keybit); + + if (old_keycode == KEY_RESERVED) { + new_keyentry->key.scancode = scancode; + new_keyentry->key.keycode = keycode; + list_add(&new_keyentry->list, &data->keytable); + } else { + kfree(new_keyentry); + clear_bit(old_keycode, dev->keybit); + list_for_each_entry(keyentry, &data->keytable, list) { + if (keyentry->key.keycode == old_keycode) { + set_bit(old_keycode, dev->keybit); + break; + } + } + } + + write_unlock_irqrestore(&keytable_lock, flags); + return 0; +} + +/* + * Timer function to report keyup event some time after keydown is + * reported by the ISR. + */ +static void +wbcir_keyup(unsigned long cookie) +{ + struct wbcir_data *data = (struct wbcir_data *)cookie; + unsigned long flags; + + /* + * data->keyup_jiffies is used to prevent a race condition if a + * hardware interrupt occurs at this point and the keyup timer + * event is moved further into the future as a result. + * + * The timer will then be reactivated and this function called + * again in the future. We need to exit gracefully in that case + * to allow the input subsystem to do its auto-repeat magic or + * a keyup event might follow immediately after the keydown. + */ + + spin_lock_irqsave(&wbcir_lock, flags); + + if (time_is_after_eq_jiffies(data->keyup_jiffies) && data->keypressed) { + data->keypressed = 0; + led_trigger_event(data->rxtrigger, LED_OFF); + input_report_key(data->input_dev, data->last_keycode, 0); + input_sync(data->input_dev); + } + + spin_unlock_irqrestore(&wbcir_lock, flags); +} + +static void +wbcir_keydown(struct wbcir_data *data, u32 scancode, u8 toggle) +{ + unsigned int keycode; + + /* Repeat? */ + if (data->last_scancode == scancode && + data->last_toggle == toggle && + data->keypressed) + goto set_timer; + data->last_scancode = scancode; + + /* Do we need to release an old keypress? */ + if (data->keypressed) { + input_report_key(data->input_dev, data->last_keycode, 0); + input_sync(data->input_dev); + data->keypressed = 0; + } + + /* Report scancode */ + input_event(data->input_dev, EV_MSC, MSC_SCAN, (int)scancode); + + /* Do we know this scancode? */ + keycode = wbcir_do_getkeycode(data, scancode); + if (keycode == KEY_RESERVED) + goto set_timer; + + /* Register a keypress */ + input_report_key(data->input_dev, keycode, 1); + data->keypressed = 1; + data->last_keycode = keycode; + data->last_toggle = toggle; + +set_timer: + input_sync(data->input_dev); + led_trigger_event(data->rxtrigger, + data->keypressed ? LED_FULL : LED_OFF); + data->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&data->timer_keyup, data->keyup_jiffies); +} + + + +/***************************************************************************** + * + * IR PARSING FUNCTIONS + * + *****************************************************************************/ + +/* Resets all irdata */ +static void +wbcir_reset_irdata(struct wbcir_data *data) +{ + memset(data->irdata, 0, sizeof(data->irdata)); + data->irdata_count = 0; + data->irdata_off = 0; + data->irdata_error = 0; +} + +/* Adds one bit of irdata */ +static void +add_irdata_bit(struct wbcir_data *data, int set) +{ + if (data->irdata_count >= sizeof(data->irdata) * 8) { + data->irdata_error = 1; + return; + } + + if (set) + __set_bit(data->irdata_count, data->irdata); + data->irdata_count++; +} + +/* Gets count bits of irdata */ +static u16 +get_bits(struct wbcir_data *data, int count) +{ + u16 val = 0x0; + + if (data->irdata_count - data->irdata_off < count) { + data->irdata_error = 1; + return 0x0; + } + + while (count > 0) { + val <<= 1; + if (test_bit(data->irdata_off, data->irdata)) + val |= 0x1; + count--; + data->irdata_off++; + } + + return val; +} + +/* Reads 16 cells and converts them to a byte */ +static u8 +wbcir_rc6cells_to_byte(struct wbcir_data *data) +{ + u16 raw = get_bits(data, 16); + u8 val = 0x00; + int bit; + + for (bit = 0; bit < 8; bit++) { + switch (raw & 0x03) { + case 0x01: + break; + case 0x02: + val |= (0x01 << bit); + break; + default: + data->irdata_error = 1; + break; + } + raw >>= 2; + } + + return val; +} + +/* Decodes a number of bits from raw RC5 data */ +static u8 +wbcir_get_rc5bits(struct wbcir_data *data, unsigned int count) +{ + u16 raw = get_bits(data, count * 2); + u8 val = 0x00; + int bit; + + for (bit = 0; bit < count; bit++) { + switch (raw & 0x03) { + case 0x01: + val |= (0x01 << bit); + break; + case 0x02: + break; + default: + data->irdata_error = 1; + break; + } + raw >>= 2; + } + + return val; +} + +static void +wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) +{ + /* + * Normal bits are manchester coded as follows: + * cell0 + cell1 = logic "0" + * cell1 + cell0 = logic "1" + * + * The IR pulse has the following components: + * + * Leader - 6 * cell1 - discarded + * Gap - 2 * cell0 - discarded + * Start bit - Normal Coding - always "1" + * Mode Bit 2 - 0 - Normal Coding + * Toggle bit - Normal Coding with double bit time, + * e.g. cell0 + cell0 + cell1 + cell1 + * means logic "0". + * + * The rest depends on the mode, the following modes are known: + * + * MODE 0: + * Address Bit 7 - 0 - Normal Coding + * Command Bit 7 - 0 - Normal Coding + * + * MODE 6: + * The above Toggle Bit is used as a submode bit, 0 = A, 1 = B. + * Submode B is for pointing devices, only remotes using submode A + * are supported. + * + * Customer range bit - 0 => Customer = 7 bits, 0...127 + * 1 => Customer = 15 bits, 32768...65535 + * Customer Bits - Normal Coding + * + * Customer codes are allocated by Philips. The rest of the bits + * are customer dependent. The following is commonly used (and the + * only supported config): + * + * Toggle Bit - Normal Coding + * Address Bit 6 - 0 - Normal Coding + * Command Bit 7 - 0 - Normal Coding + * + * All modes are followed by at least 6 * cell0. + * + * MODE 0 msglen: + * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (toggle) + + * 8 * 2 (address) + 8 * 2 (command) = + * 44 cells + * + * MODE 6A msglen: + * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (submode) + + * 1 * 2 (customer range bit) + 7/15 * 2 (customer bits) + + * 1 * 2 (toggle bit) + 7 * 2 (address) + 8 * 2 (command) = + * 60 - 76 cells + */ + u8 mode; + u8 toggle; + u16 customer = 0x0; + u8 address; + u8 command; + u32 scancode; + + /* Leader mark */ + while (get_bits(data, 1) && !data->irdata_error) + /* Do nothing */; + + /* Leader space */ + if (get_bits(data, 1)) { + dev_dbg(dev, "RC6 - Invalid leader space\n"); + return; + } + + /* Start bit */ + if (get_bits(data, 2) != 0x02) { + dev_dbg(dev, "RC6 - Invalid start bit\n"); + return; + } + + /* Mode */ + mode = get_bits(data, 6); + switch (mode) { + case 0x15: /* 010101 = b000 */ + mode = 0; + break; + case 0x29: /* 101001 = b110 */ + mode = 6; + break; + default: + dev_dbg(dev, "RC6 - Invalid mode\n"); + return; + } + + /* Toggle bit / Submode bit */ + toggle = get_bits(data, 4); + switch (toggle) { + case 0x03: + toggle = 0; + break; + case 0x0C: + toggle = 1; + break; + default: + dev_dbg(dev, "RC6 - Toggle bit error\n"); + break; + } + + /* Customer */ + if (mode == 6) { + if (toggle != 0) { + dev_dbg(dev, "RC6B - Not Supported\n"); + return; + } + + customer = wbcir_rc6cells_to_byte(data); + + if (customer & 0x80) { + /* 15 bit customer value */ + customer <<= 8; + customer |= wbcir_rc6cells_to_byte(data); + } + } + + /* Address */ + address = wbcir_rc6cells_to_byte(data); + if (mode == 6) { + toggle = address >> 7; + address &= 0x7F; + } + + /* Command */ + command = wbcir_rc6cells_to_byte(data); + + /* Create scancode */ + scancode = command; + scancode |= address << 8; + scancode |= customer << 16; + + /* Last sanity check */ + if (data->irdata_error) { + dev_dbg(dev, "RC6 - Cell error(s)\n"); + return; + } + + dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " + "toggle %u mode %u scan 0x%08X\n", + address, + command, + customer, + (unsigned int)toggle, + (unsigned int)mode, + scancode); + + wbcir_keydown(data, scancode, toggle); +} + +static void +wbcir_parse_rc5(struct device *dev, struct wbcir_data *data) +{ + /* + * Bits are manchester coded as follows: + * cell1 + cell0 = logic "0" + * cell0 + cell1 = logic "1" + * (i.e. the reverse of RC6) + * + * Start bit 1 - "1" - discarded + * Start bit 2 - Must be inverted to get command bit 6 + * Toggle bit + * Address Bit 4 - 0 + * Command Bit 5 - 0 + */ + u8 toggle; + u8 address; + u8 command; + u32 scancode; + + /* Start bit 1 */ + if (!get_bits(data, 1)) { + dev_dbg(dev, "RC5 - Invalid start bit\n"); + return; + } + + /* Start bit 2 */ + if (!wbcir_get_rc5bits(data, 1)) + command = 0x40; + else + command = 0x00; + + toggle = wbcir_get_rc5bits(data, 1); + address = wbcir_get_rc5bits(data, 5); + command |= wbcir_get_rc5bits(data, 6); + scancode = address << 7 | command; + + /* Last sanity check */ + if (data->irdata_error) { + dev_dbg(dev, "RC5 - Invalid message\n"); + return; + } + + dev_dbg(dev, "IR-RC5 ad %u cm %u t %u s %u\n", + (unsigned int)address, + (unsigned int)command, + (unsigned int)toggle, + (unsigned int)scancode); + + wbcir_keydown(data, scancode, toggle); +} + +static void +wbcir_parse_nec(struct device *dev, struct wbcir_data *data) +{ + /* + * Each bit represents 560 us. + * + * Leader - 9 ms burst + * Gap - 4.5 ms silence + * Address1 bit 0 - 7 - Address 1 + * Address2 bit 0 - 7 - Address 2 + * Command1 bit 0 - 7 - Command 1 + * Command2 bit 0 - 7 - Command 2 + * + * Note the bit order! + * + * With the old NEC protocol, Address2 was the inverse of Address1 + * and Command2 was the inverse of Command1 and were used as + * an error check. + * + * With NEC extended, Address1 is the LSB of the Address and + * Address2 is the MSB, Command parsing remains unchanged. + * + * A repeat message is coded as: + * Leader - 9 ms burst + * Gap - 2.25 ms silence + * Repeat - 560 us active + */ + u8 address1; + u8 address2; + u8 command1; + u8 command2; + u16 address; + u32 scancode; + + /* Leader mark */ + while (get_bits(data, 1) && !data->irdata_error) + /* Do nothing */; + + /* Leader space */ + if (get_bits(data, 4)) { + dev_dbg(dev, "NEC - Invalid leader space\n"); + return; + } + + /* Repeat? */ + if (get_bits(data, 1)) { + if (!data->keypressed) { + dev_dbg(dev, "NEC - Stray repeat message\n"); + return; + } + + dev_dbg(dev, "IR-NEC repeat s %u\n", + (unsigned int)data->last_scancode); + + wbcir_keydown(data, data->last_scancode, data->last_toggle); + return; + } + + /* Remaining leader space */ + if (get_bits(data, 3)) { + dev_dbg(dev, "NEC - Invalid leader space\n"); + return; + } + + address1 = bitrev8(get_bits(data, 8)); + address2 = bitrev8(get_bits(data, 8)); + command1 = bitrev8(get_bits(data, 8)); + command2 = bitrev8(get_bits(data, 8)); + + /* Sanity check */ + if (data->irdata_error) { + dev_dbg(dev, "NEC - Invalid message\n"); + return; + } + + /* Check command validity */ + if (command1 != ~command2) { + dev_dbg(dev, "NEC - Command bytes mismatch\n"); + return; + } + + /* Check for extended NEC protocol */ + address = address1; + if (address1 != ~address2) + address |= address2 << 8; + + scancode = address << 8 | command1; + + dev_dbg(dev, "IR-NEC ad %u cm %u s %u\n", + (unsigned int)address, + (unsigned int)command1, + (unsigned int)scancode); + + wbcir_keydown(data, scancode, !data->last_toggle); +} + + + +/***************************************************************************** + * + * INTERRUPT FUNCTIONS + * + *****************************************************************************/ + +static irqreturn_t +wbcir_irq_handler(int irqno, void *cookie) +{ + struct pnp_dev *device = cookie; + struct wbcir_data *data = pnp_get_drvdata(device); + struct device *dev = &device->dev; + u8 status; + unsigned long flags; + u8 irdata[8]; + int i; + unsigned int hw; + + spin_lock_irqsave(&wbcir_lock, flags); + + wbcir_select_bank(data, WBCIR_BANK_0); + + status = inb(data->sbase + WBCIR_REG_SP3_EIR); + + if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { + spin_unlock_irqrestore(&wbcir_lock, flags); + return IRQ_NONE; + } + + if (status & WBCIR_IRQ_ERR) + data->irdata_error = 1; + + if (!(status & WBCIR_IRQ_RX)) + goto out; + + /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ + insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); + + for (i = 0; i < sizeof(irdata); i++) { + hw = hweight8(irdata[i]); + if (hw > 4) + add_irdata_bit(data, 0); + else + add_irdata_bit(data, 1); + + if (hw == 8) + data->idle_count++; + else + data->idle_count = 0; + } + + if (data->idle_count > WBCIR_MAX_IDLE_BYTES) { + /* Set RXINACTIVE... */ + outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); + + /* ...and drain the FIFO */ + while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) + inb(data->sbase + WBCIR_REG_SP3_RXDATA); + + dev_dbg(dev, "IRDATA:\n"); + for (i = 0; i < data->irdata_count; i += BITS_PER_LONG) + dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]); + + switch (protocol) { + case IR_PROTOCOL_RC5: + wbcir_parse_rc5(dev, data); + break; + case IR_PROTOCOL_RC6: + wbcir_parse_rc6(dev, data); + break; + case IR_PROTOCOL_NEC: + wbcir_parse_nec(dev, data); + break; + } + + wbcir_reset_irdata(data); + data->idle_count = 0; + } + +out: + spin_unlock_irqrestore(&wbcir_lock, flags); + return IRQ_HANDLED; +} + + + +/***************************************************************************** + * + * SUSPEND/RESUME FUNCTIONS + * + *****************************************************************************/ + +static void +wbcir_shutdown(struct pnp_dev *device) +{ + struct device *dev = &device->dev; + struct wbcir_data *data = pnp_get_drvdata(device); + int do_wake = 1; + u8 match[11]; + u8 mask[11]; + u8 rc6_csl = 0; + int i; + + memset(match, 0, sizeof(match)); + memset(mask, 0, sizeof(mask)); + + if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { + do_wake = 0; + goto finish; + } + + switch (protocol) { + case IR_PROTOCOL_RC5: + if (wake_sc > 0xFFF) { + do_wake = 0; + dev_err(dev, "RC5 - Invalid wake scancode\n"); + break; + } + + /* Mask = 13 bits, ex toggle */ + mask[0] = 0xFF; + mask[1] = 0x17; + + match[0] = (wake_sc & 0x003F); /* 6 command bits */ + match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ + match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ + if (!(wake_sc & 0x0040)) /* 2nd start bit */ + match[1] |= 0x10; + + break; + + case IR_PROTOCOL_NEC: + if (wake_sc > 0xFFFFFF) { + do_wake = 0; + dev_err(dev, "NEC - Invalid wake scancode\n"); + break; + } + + mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; + + match[1] = bitrev8((wake_sc & 0xFF)); + match[0] = ~match[1]; + + match[3] = bitrev8((wake_sc & 0xFF00) >> 8); + if (wake_sc > 0xFFFF) + match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); + else + match[2] = ~match[3]; + + break; + + case IR_PROTOCOL_RC6: + + if (wake_rc6mode == 0) { + if (wake_sc > 0xFFFF) { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake scancode\n"); + break; + } + + /* Command */ + match[0] = wbcir_to_rc6cells(wake_sc >> 0); + mask[0] = 0xFF; + match[1] = wbcir_to_rc6cells(wake_sc >> 4); + mask[1] = 0xFF; + + /* Address */ + match[2] = wbcir_to_rc6cells(wake_sc >> 8); + mask[2] = 0xFF; + match[3] = wbcir_to_rc6cells(wake_sc >> 12); + mask[3] = 0xFF; + + /* Header */ + match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ + mask[4] = 0xF0; + match[5] = 0x09; /* start bit = 1, mode2 = 0 */ + mask[5] = 0x0F; + + rc6_csl = 44; + + } else if (wake_rc6mode == 6) { + i = 0; + + /* Command */ + match[i] = wbcir_to_rc6cells(wake_sc >> 0); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 4); + mask[i++] = 0xFF; + + /* Address + Toggle */ + match[i] = wbcir_to_rc6cells(wake_sc >> 8); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 12); + mask[i++] = 0x3F; + + /* Customer bits 7 - 0 */ + match[i] = wbcir_to_rc6cells(wake_sc >> 16); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 20); + mask[i++] = 0xFF; + + if (wake_sc & 0x80000000) { + /* Customer range bit and bits 15 - 8 */ + match[i] = wbcir_to_rc6cells(wake_sc >> 24); + mask[i++] = 0xFF; + match[i] = wbcir_to_rc6cells(wake_sc >> 28); + mask[i++] = 0xFF; + rc6_csl = 76; + } else if (wake_sc <= 0x007FFFFF) { + rc6_csl = 60; + } else { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake scancode\n"); + break; + } + + /* Header */ + match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */ + mask[i++] = 0xFF; + match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ + mask[i++] = 0x0F; + + } else { + do_wake = 0; + dev_err(dev, "RC6 - Invalid wake mode\n"); + } + + break; + + default: + do_wake = 0; + break; + } + +finish: + if (do_wake) { + /* Set compare and compare mask */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, + WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0, + 0x3F); + outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11); + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, + WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0, + 0x3F); + outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11); + + /* RC6 Compare String Len */ + outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); + + /* Set CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); + + } else { + /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* Clear CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); + } + + /* Disable interrupts */ + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); +} + +static int +wbcir_suspend(struct pnp_dev *device, pm_message_t state) +{ + wbcir_shutdown(device); + return 0; +} + +static int +wbcir_resume(struct pnp_dev *device) +{ + struct wbcir_data *data = pnp_get_drvdata(device); + + /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* Clear CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); + + /* Enable interrupts */ + wbcir_reset_irdata(data); + outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); + + return 0; +} + + + +/***************************************************************************** + * + * SETUP/INIT FUNCTIONS + * + *****************************************************************************/ + +static void +wbcir_cfg_ceir(struct wbcir_data *data) +{ + u8 tmp; + + /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ + tmp = protocol << 4; + if (invert) + tmp |= 0x08; + outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* Set RC5 cell time to correspond to 36 kHz */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F); + + /* Set IRTX_INV */ + if (invert) + outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL); + else + outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); + + /* + * Clear IR LED, set SP3 clock to 24Mhz + * set SP3_IRRX_SW to binary 01, helpfully not documented + */ + outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); +} + +static int __devinit +wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) +{ + struct device *dev = &device->dev; + struct wbcir_data *data; + int err; + + if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN && + pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN && + pnp_port_len(device, 2) == SP_IOMEM_LEN)) { + dev_err(dev, "Invalid resources\n"); + return -ENODEV; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + pnp_set_drvdata(device, data); + + data->ebase = pnp_port_start(device, 0); + data->wbase = pnp_port_start(device, 1); + data->sbase = pnp_port_start(device, 2); + data->irq = pnp_irq(device, 0); + + if (data->wbase == 0 || data->ebase == 0 || + data->sbase == 0 || data->irq == 0) { + err = -ENODEV; + dev_err(dev, "Invalid resources\n"); + goto exit_free_data; + } + + dev_dbg(&device->dev, "Found device " + "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", + data->wbase, data->ebase, data->sbase, data->irq); + + if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_free_data; + } + + if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_release_wbase; + } + + if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { + dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", + data->sbase, data->sbase + SP_IOMEM_LEN - 1); + err = -EBUSY; + goto exit_release_ebase; + } + + err = request_irq(data->irq, wbcir_irq_handler, + IRQF_DISABLED, DRVNAME, device); + if (err) { + dev_err(dev, "Failed to claim IRQ %u\n", data->irq); + err = -EBUSY; + goto exit_release_sbase; + } + + led_trigger_register_simple("cir-tx", &data->txtrigger); + if (!data->txtrigger) { + err = -ENOMEM; + goto exit_free_irq; + } + + led_trigger_register_simple("cir-rx", &data->rxtrigger); + if (!data->rxtrigger) { + err = -ENOMEM; + goto exit_unregister_txtrigger; + } + + data->led.name = "cir::activity"; + data->led.default_trigger = "cir-rx"; + data->led.brightness_set = wbcir_led_brightness_set; + data->led.brightness_get = wbcir_led_brightness_get; + err = led_classdev_register(&device->dev, &data->led); + if (err) + goto exit_unregister_rxtrigger; + + data->input_dev = input_allocate_device(); + if (!data->input_dev) { + err = -ENOMEM; + goto exit_unregister_led; + } + + data->input_dev->evbit[0] = BIT(EV_KEY); + data->input_dev->name = WBCIR_NAME; + data->input_dev->phys = "wbcir/cir0"; + data->input_dev->id.bustype = BUS_HOST; + data->input_dev->id.vendor = PCI_VENDOR_ID_WINBOND; + data->input_dev->id.product = WBCIR_ID_FAMILY; + data->input_dev->id.version = WBCIR_ID_CHIP; + data->input_dev->getkeycode = wbcir_getkeycode; + data->input_dev->setkeycode = wbcir_setkeycode; + input_set_capability(data->input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(data->input_dev, data); + + err = input_register_device(data->input_dev); + if (err) + goto exit_free_input; + + data->last_scancode = INVALID_SCANCODE; + INIT_LIST_HEAD(&data->keytable); + setup_timer(&data->timer_keyup, wbcir_keyup, (unsigned long)data); + + /* Load default keymaps */ + if (protocol == IR_PROTOCOL_RC6) { + int i; + for (i = 0; i < ARRAY_SIZE(rc6_def_keymap); i++) { + err = wbcir_setkeycode(data->input_dev, + (int)rc6_def_keymap[i].scancode, + (int)rc6_def_keymap[i].keycode); + if (err) + goto exit_unregister_keys; + } + } + + device_init_wakeup(&device->dev, 1); + + wbcir_cfg_ceir(data); + + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + /* Enable extended mode */ + wbcir_select_bank(data, WBCIR_BANK_2); + outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); + + /* + * Configure baud generator, IR data will be sampled at + * a bitrate of: (24Mhz * prescaler) / (divisor * 16). + * + * The ECIR registers include a flag to change the + * 24Mhz clock freq to 48Mhz. + * + * It's not documented in the specs, but fifo levels + * other than 16 seems to be unsupported. + */ + + /* prescaler 1.0, tx/rx fifo lvl 16 */ + outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); + + /* Set baud divisor to generate one byte per bit/cell */ + switch (protocol) { + case IR_PROTOCOL_RC5: + outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_RC6: + outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_NEC: + outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); + break; + } + outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); + + /* Set CEIR mode */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); + inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ + inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ + + /* Disable RX demod, run-length encoding/decoding, set freq span */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); + + /* Disable timer */ + wbcir_select_bank(data, WBCIR_BANK_4); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); + + /* Enable MSR interrupt, Clear AUX_IRX */ + wbcir_select_bank(data, WBCIR_BANK_5); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); + + /* Disable CRC */ + wbcir_select_bank(data, WBCIR_BANK_6); + outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); + + /* Set RX/TX (de)modulation freq, not really used */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); + outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); + + /* Set invert and pin direction */ + if (invert) + outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); + else + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); + + /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); + + /* Clear AUX status bits */ + outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); + + /* Enable interrupts */ + outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); + + return 0; + +exit_unregister_keys: + if (!list_empty(&data->keytable)) { + struct wbcir_keyentry *key; + struct wbcir_keyentry *keytmp; + + list_for_each_entry_safe(key, keytmp, &data->keytable, list) { + list_del(&key->list); + kfree(key); + } + } + input_unregister_device(data->input_dev); + /* Can't call input_free_device on an unregistered device */ + data->input_dev = NULL; +exit_free_input: + input_free_device(data->input_dev); +exit_unregister_led: + led_classdev_unregister(&data->led); +exit_unregister_rxtrigger: + led_trigger_unregister_simple(data->rxtrigger); +exit_unregister_txtrigger: + led_trigger_unregister_simple(data->txtrigger); +exit_free_irq: + free_irq(data->irq, device); +exit_release_sbase: + release_region(data->sbase, SP_IOMEM_LEN); +exit_release_ebase: + release_region(data->ebase, EHFUNC_IOMEM_LEN); +exit_release_wbase: + release_region(data->wbase, WAKEUP_IOMEM_LEN); +exit_free_data: + kfree(data); + pnp_set_drvdata(device, NULL); +exit: + return err; +} + +static void __devexit +wbcir_remove(struct pnp_dev *device) +{ + struct wbcir_data *data = pnp_get_drvdata(device); + struct wbcir_keyentry *key; + struct wbcir_keyentry *keytmp; + + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + del_timer_sync(&data->timer_keyup); + + free_irq(data->irq, device); + + /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); + + /* Clear CEIR_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); + + /* Clear BUFF_EN, END_EN, MATCH_EN */ + wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); + + /* This will generate a keyup event if necessary */ + input_unregister_device(data->input_dev); + + led_trigger_unregister_simple(data->rxtrigger); + led_trigger_unregister_simple(data->txtrigger); + led_classdev_unregister(&data->led); + + /* This is ok since &data->led isn't actually used */ + wbcir_led_brightness_set(&data->led, LED_OFF); + + release_region(data->wbase, WAKEUP_IOMEM_LEN); + release_region(data->ebase, EHFUNC_IOMEM_LEN); + release_region(data->sbase, SP_IOMEM_LEN); + + list_for_each_entry_safe(key, keytmp, &data->keytable, list) { + list_del(&key->list); + kfree(key); + } + + kfree(data); + + pnp_set_drvdata(device, NULL); +} + +static const struct pnp_device_id wbcir_ids[] = { + { "WEC1022", 0 }, + { "", 0 } +}; +MODULE_DEVICE_TABLE(pnp, wbcir_ids); + +static struct pnp_driver wbcir_driver = { + .name = WBCIR_NAME, + .id_table = wbcir_ids, + .probe = wbcir_probe, + .remove = __devexit_p(wbcir_remove), + .suspend = wbcir_suspend, + .resume = wbcir_resume, + .shutdown = wbcir_shutdown +}; + +static int __init +wbcir_init(void) +{ + int ret; + + switch (protocol) { + case IR_PROTOCOL_RC5: + case IR_PROTOCOL_NEC: + case IR_PROTOCOL_RC6: + break; + default: + printk(KERN_ERR DRVNAME ": Invalid protocol argument\n"); + return -EINVAL; + } + + ret = pnp_register_driver(&wbcir_driver); + if (ret) + printk(KERN_ERR DRVNAME ": Unable to register driver\n"); + + return ret; +} + +static void __exit +wbcir_exit(void) +{ + pnp_unregister_driver(&wbcir_driver); +} + +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); +MODULE_LICENSE("GPL"); + +module_init(wbcir_init); +module_exit(wbcir_exit); + + -- cgit v1.2.3 From 7e483865612568268773317219d07b38a8c4d62d Mon Sep 17 00:00:00 2001 From: Chen Liqin Date: Wed, 23 Sep 2009 11:40:15 +0800 Subject: score: update email address in MAINTAINERS. Signed-off-by: Chen Liqin --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d24c8823a8cb..4467da2a4d7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4460,7 +4460,7 @@ SCORE ARCHITECTURE P: Chen Liqin M: liqin.chen@sunplusct.com P: Lennox Wu -M: lennox.wu@sunplusct.com +M: lennox.wu@gmail.com W: http://www.sunplusct.com S: Supported -- cgit v1.2.3 From 5429c7316577fcd859f6b53e10884bb8e1e3bcef Mon Sep 17 00:00:00 2001 From: Li Yang Date: Tue, 11 Aug 2009 11:11:11 +0800 Subject: USB: gadget: Update Freescale UDC entry in MAINTAINERS Change the F entry for file rename, and make it also cover fsl_qe_udc driver. Update the name accordingly. Signed-off-by: Li Yang Acked-by: Guennadi Liakhovetski Cc: Joe Perches Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d24c8823a8cb..5e1bf0ce1d59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2107,12 +2107,12 @@ S: Supported F: arch/powerpc/sysdev/qe_lib/ F: arch/powerpc/include/asm/*qe.h -FREESCALE HIGHSPEED USB DEVICE DRIVER +FREESCALE USB PERIPHERIAL DRIVERS M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained -F: drivers/usb/gadget/fsl_usb2_udc.c +F: drivers/usb/gadget/fsl* FREESCALE QUICC ENGINE UCC ETHERNET DRIVER M: Li Yang -- cgit v1.2.3 From 515350b6fd041396f425180589e08812dd13615f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 22 Sep 2009 16:43:54 -0700 Subject: MAINTAINERS: remove dead ncpfs list On Saturday 01 August 2009 00:30:39 Mail Delivery Subsystem wrote: > Delivery to the following recipient failed permanently: > > linware@sh.cvut.cz > > Technical details of permanent failure: > Google tried to deliver your message, but it was rejected by the recipient > domain. We recommend contacting the other email provider for further > information about the cause of this error. The error that the other server > returned was: 450 450 : Recipient address rejected: > undeliverable address: unknown user: "linware" (state 14). Cc: Petr Vandrovec Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index d24c8823a8cb..017cf691bb03 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3527,7 +3527,6 @@ F: drivers/net/natsemi.c NCP FILESYSTEM M: Petr Vandrovec -L: linware@sh.cvut.cz S: Maintained F: fs/ncpfs/ -- cgit v1.2.3 From 653f41b52dfc63fecf4a2333f13be28b159a918c Mon Sep 17 00:00:00 2001 From: Madhusudhan Chikkature Date: Tue, 22 Sep 2009 16:45:06 -0700 Subject: MAINTAINERS: update for TI OMAP hsmmc driver Update maintainers entry for TI OMAP HS MMC support. Signed-off-by: Madhusudhan Chikkature Acked-by: Kevin Hilman Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 017cf691bb03..d8973ca86f2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3768,7 +3768,13 @@ OMAP MMC SUPPORT M: Jarkko Lavinen L: linux-omap@vger.kernel.org S: Maintained -F: drivers/mmc/host/*omap* +F: drivers/mmc/host/omap.c + +OMAP HS MMC SUPPORT +M: Madhusudhan Chikkature +L: linux-omap@vger.kernel.org +S: Maintained +F: drivers/mmc/host/omap_hsmmc.c OMAP RANDOM NUMBER GENERATOR SUPPORT M: Deepak Saxena -- cgit v1.2.3 From c0d0787b6d47d9f4d5e8bd321921104e854a9135 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 23 Sep 2009 15:57:17 -0700 Subject: MAINTAINERS: add Matt Mackall and Herbert Xu to HARDWARE RANDOM NUMBER GENERATOR Signed-off-by: Joe Perches Cc: David Daney Cc: Herbert Xu Cc: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 7c1c0b05b298..0c138ba86526 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2331,7 +2331,9 @@ S: Orphan F: drivers/hwmon/ HARDWARE RANDOM NUMBER GENERATOR CORE -S: Orphan +M: Matt Mackall +M: Herbert Xu +S: Odd fixes F: Documentation/hw_random.txt F: drivers/char/hw_random/ F: include/linux/hw_random.h -- cgit v1.2.3