Skip to content

Commit

Permalink
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/mjg59/platform-drivers-x86

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86: (88 commits)
  ips driver: make it less chatty
  intel_scu_ipc: fix size field for intel_scu_ipc_command
  intel_scu_ipc: return -EIO for error condition in busy_loop
  intel_scu_ipc: fix data packing of PMIC command on Moorestown
  Clean up command packing on MRST.
  zero the stack buffer before giving random garbage to the SCU
  Fix stack buffer size for IPC writev messages
  intel_scu_ipc: Use the new cpu identification function
  intel_scu_ipc: tidy up unused bits
  Remove indirect read write api support.
  intel_scu_ipc: Support Medfield processors
  intel_scu_ipc: detect CPU type automatically
  x86 plat: limit x86 platform driver menu to X86
  acpi ec_sys: Be more cautious about ec write access
  acpi ec: Fix possible double io port registration
  hp-wmi: acpi_drivers.h is already included through acpi.h two lines below
  hp-wmi: Fix mixing up of and/or directive
  dell-laptop: make dell_laptop_i8042_filter() static
  asus-laptop: fix asus_input_init error path
  msi-wmi: make needlessly global symbols static
  ...
  • Loading branch information
Linus Torvalds committed Aug 4, 2010
2 parents 5e83f6f + 1a14703 commit c145307
Show file tree
Hide file tree
Showing 43 changed files with 3,830 additions and 743 deletions.
20 changes: 20 additions & 0 deletions Documentation/ABI/testing/debugfs-ec
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
What: /sys/kernel/debug/ec/*/{gpe,use_global_lock,io}
Date: July 2010
Contact: Thomas Renninger <trenn@suse.de>
Description:

General information like which GPE is assigned to the EC and whether
the global lock should get used.
Knowing the EC GPE one can watch the amount of HW events related to
the EC here (XY -> GPE number from /sys/kernel/debug/ec/*/gpe):
/sys/firmware/acpi/interrupts/gpeXY

The io file is binary and a userspace tool located here:
ftp://ftp.suse.com/pub/people/trenn/sources/ec/
should get used to read out the 256 Embedded Controller registers
or writing to them.

CAUTION: Do not write to the Embedded Controller if you don't know
what you are doing! Rebooting afterwards also is a good idea.
This can influence the way your machine is cooled and fans may
not get switched on again after you did a wrong write.
71 changes: 11 additions & 60 deletions Documentation/laptops/thinkpad-acpi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -960,70 +960,21 @@ Sysfs notes:
subsystem, and follow all of the hwmon guidelines at
Documentation/hwmon.

EXPERIMENTAL: Embedded controller register dump
-----------------------------------------------

EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
------------------------------------------------------------------------

This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
WITH CAUTION! To use this feature, you need to supply the
experimental=1 parameter when loading the module.

This feature dumps the values of 256 embedded controller
registers. Values which have changed since the last time the registers
were dumped are marked with a star:

[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
EC 0x30: 01 07 1a 00 30 04 00 00 *85 00 00 10 00 50 00 00
EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 *bc *02 *bc
EC 0x60: *02 *bc *02 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0x70: 00 00 00 00 00 12 30 40 *24 *26 *2c *27 *20 80 *1f 80
EC 0x80: 00 00 00 06 *37 *0e 03 00 00 00 0e 07 00 00 00 00
EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xa0: *ff 09 ff 09 ff ff *64 00 *00 *00 *a2 41 *ff *ff *e0 00
EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a

This feature can be used to determine the register holding the fan
speed on some models. To do that, do the following:
This feature is not included in the thinkpad driver anymore.
Instead the EC can be accessed through /sys/kernel/debug/ec with
a userspace tool which can be found here:
ftp://ftp.suse.com/pub/people/trenn/sources/ec

Use it to determine the register holding the fan
speed on some models. To do that, do the following:
- make sure the battery is fully charged
- make sure the fan is running
- run 'cat /proc/acpi/ibm/ecdump' several times, once per second or so

The first step makes sure various charging-related values don't
vary. The second ensures that the fan-related values do vary, since
the fan speed fluctuates a bit. The third will (hopefully) mark the
fan register with a star:

[root@x40 ibm-acpi]# cat /proc/acpi/ibm/ecdump
EC +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +0a +0b +0c +0d +0e +0f
EC 0x00: a7 47 87 01 fe 96 00 08 01 00 cb 00 00 00 40 00
EC 0x10: 00 00 ff ff f4 3c 87 09 01 ff 42 01 ff ff 0d 00
EC 0x20: 00 00 00 00 00 00 00 00 00 00 00 03 43 00 00 80
EC 0x30: 01 07 1a 00 30 04 00 00 85 00 00 10 00 50 00 00
EC 0x40: 00 00 00 00 00 00 14 01 00 04 00 00 00 00 00 00
EC 0x50: 00 c0 02 0d 00 01 01 02 02 03 03 03 03 bc 02 bc
EC 0x60: 02 bc 02 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0x70: 00 00 00 00 00 12 30 40 24 27 2c 27 21 80 1f 80
EC 0x80: 00 00 00 06 *be 0d 03 00 00 00 0e 07 00 00 00 00
EC 0x90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xa0: ff 09 ff 09 ff ff 64 00 00 00 a2 41 ff ff e0 00
EC 0xb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xd0: 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EC 0xe0: 00 00 00 00 00 00 00 00 11 20 49 04 24 06 55 03
EC 0xf0: 31 55 48 54 35 38 57 57 08 2f 45 73 07 65 6c 1a

Another set of values that varies often is the temperature
- use above mentioned tool to read out the EC

Often fan and temperature values vary between
readings. Since temperatures don't change vary fast, you can take
several quick dumps to eliminate them.

Expand Down
20 changes: 6 additions & 14 deletions arch/x86/include/asm/intel_scu_ipc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#ifndef _ASM_X86_INTEL_SCU_IPC_H_
#define _ASM_X86_INTEL_SCU_IPC_H_

#define IPCMSG_VRTC 0xFA /* Set vRTC device */

/* Command id associated with message IPCMSG_VRTC */
#define IPC_CMD_VRTC_SETTIME 1 /* Set time */
#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */

/* Read single register */
int intel_scu_ipc_ioread8(u16 addr, u8 *data);

Expand Down Expand Up @@ -28,20 +34,6 @@ int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);
/* Update single register based on the mask */
int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);

/*
* Indirect register read
* Can be used when SCCB(System Controller Configuration Block) register
* HRIM(Honor Restricted IPC Messages) is set (bit 23)
*/
int intel_scu_ipc_register_read(u32 addr, u32 *data);

/*
* Indirect register write
* Can be used when SCCB(System Controller Configuration Block) register
* HRIM(Honor Restricted IPC Messages) is set (bit 23)
*/
int intel_scu_ipc_register_write(u32 addr, u32 data);

/* Issue commands to the SCU with or without data */
int intel_scu_ipc_simple_command(int cmd, int sub);
int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
Expand Down
18 changes: 18 additions & 0 deletions drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ config ACPI_SYSFS_POWER
help
Say N to disable power /sys interface

config ACPI_EC_DEBUGFS
tristate "EC read/write access through /sys/kernel/debug/ec"
default n
help
Say N to disable Embedded Controller /sys/kernel/debug interface

Be aware that using this interface can confuse your Embedded
Controller in a way that a normal reboot is not enough. You then
have to power of your system, and remove the laptop battery for
some seconds.
An Embedded Controller typically is available on laptops and reads
sensor values like battery state and temperature.
The kernel accesses the EC through ACPI parsed code provided by BIOS
tables. This option allows to access the EC directly without ACPI
code being involved.
Thus this option is a debug option that helps to write ACPI drivers
and can be used to identify ACPI code or EC firmware bugs.

config ACPI_PROC_EVENT
bool "Deprecated /proc/acpi/event support"
depends on PROC_FS
Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ obj-$(CONFIG_ACPI_SBS) += sbshc.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o

# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o
Expand Down
107 changes: 14 additions & 93 deletions drivers/acpi/ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
Expand All @@ -45,10 +43,13 @@
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>

#include "internal.h"

#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"

#undef PREFIX
#define PREFIX "ACPI: EC: "

/* EC status register */
Expand Down Expand Up @@ -106,19 +107,8 @@ struct transaction {
bool done;
};

static struct acpi_ec {
acpi_handle handle;
unsigned long gpe;
unsigned long command_addr;
unsigned long data_addr;
unsigned long global_lock;
unsigned long flags;
struct mutex lock;
wait_queue_head_t wait;
struct list_head list;
struct transaction *curr;
spinlock_t curr_lock;
} *boot_ec, *first_ec;
struct acpi_ec *boot_ec, *first_ec;
EXPORT_SYMBOL(first_ec);

static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
Expand Down Expand Up @@ -678,72 +668,6 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
}
}

/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */

static struct proc_dir_entry *acpi_ec_dir;

static int acpi_ec_read_info(struct seq_file *seq, void *offset)
{
struct acpi_ec *ec = seq->private;

if (!ec)
goto end;

seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
(unsigned)ec->command_addr, (unsigned)ec->data_addr);
seq_printf(seq, "use global lock:\t%s\n",
ec->global_lock ? "yes" : "no");
end:
return 0;
}

static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_ec_read_info, PDE(inode)->data);
}

static const struct file_operations acpi_ec_info_ops = {
.open = acpi_ec_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
};

static int acpi_ec_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;

if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_ec_dir);
if (!acpi_device_dir(device))
return -ENODEV;
}

entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
acpi_device_dir(device),
&acpi_ec_info_ops, acpi_driver_data(device));
if (!entry)
return -ENODEV;
return 0;
}

static int acpi_ec_remove_fs(struct acpi_device *device)
{

if (acpi_device_dir(device)) {
remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
acpi_device_dir(device) = NULL;
}

return 0;
}

/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
Expand Down Expand Up @@ -894,7 +818,12 @@ static int acpi_ec_add(struct acpi_device *device)
if (!first_ec)
first_ec = ec;
device->driver_data = ec;
acpi_ec_add_fs(device);

WARN(!request_region(ec->data_addr, 1, "EC data"),
"Could not request EC data io port 0x%lx", ec->data_addr);
WARN(!request_region(ec->command_addr, 1, "EC cmd"),
"Could not request EC cmd io port 0x%lx", ec->command_addr);

pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);

Expand All @@ -921,7 +850,8 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
kfree(handler);
}
mutex_unlock(&ec->lock);
acpi_ec_remove_fs(device);
release_region(ec->data_addr, 1);
release_region(ec->command_addr, 1);
device->driver_data = NULL;
if (ec == first_ec)
first_ec = NULL;
Expand Down Expand Up @@ -1120,16 +1050,10 @@ int __init acpi_ec_init(void)
{
int result = 0;

acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
if (!acpi_ec_dir)
return -ENODEV;

/* Now register the driver for the EC */
result = acpi_bus_register_driver(&acpi_ec_driver);
if (result < 0) {
remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
if (result < 0)
return -ENODEV;
}

return result;
}
Expand All @@ -1140,9 +1064,6 @@ static void __exit acpi_ec_exit(void)
{

acpi_bus_unregister_driver(&acpi_ec_driver);

remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);

return;
}
#endif /* 0 */
Loading

0 comments on commit c145307

Please sign in to comment.