Commit 3136d340 authored by Len Brown's avatar Len Brown

[ACPI] change hard-coded IO width to programmable width

	http://bugzilla.kernel.org/show_bug.cgi?id=1349
	from David Shaohua Li and Venatesh Pallipadi
parent 11afe463
...@@ -108,7 +108,7 @@ acpi_processor_get_performance_control ( ...@@ -108,7 +108,7 @@ acpi_processor_get_performance_control (
} }
perf->control_register = (u16) reg->address; perf->control_register = (u16) reg->address;
perf->control_register_bit_width = reg->bit_width;
/* /*
* status_register * status_register
*/ */
...@@ -135,6 +135,7 @@ acpi_processor_get_performance_control ( ...@@ -135,6 +135,7 @@ acpi_processor_get_performance_control (
} }
perf->status_register = (u16) reg->address; perf->status_register = (u16) reg->address;
perf->status_register_bit_width = reg->bit_width;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"control_register[0x%04x] status_register[0x%04x]\n", "control_register[0x%04x] status_register[0x%04x]\n",
...@@ -224,6 +225,42 @@ acpi_processor_get_performance_states ( ...@@ -224,6 +225,42 @@ acpi_processor_get_performance_states (
return_VALUE(result); return_VALUE(result);
} }
static int
acpi_processor_write_port(
u16 port,
u8 bit_width,
u32 value)
{
if (bit_width <= 8) {
outb(value, port);
} else if (bit_width <= 16) {
outw(value, port);
} else if (bit_width <= 32) {
outl(value, port);
} else {
return -ENODEV;
}
return 0;
}
static int
acpi_processor_read_port(
u16 port,
u8 bit_width,
u32 *ret)
{
*ret = 0;
if (bit_width <= 8) {
*ret = inb(port);
} else if (bit_width <= 16) {
*ret = inw(port);
} else if (bit_width <= 32) {
*ret = inl(port);
} else {
return -ENODEV;
}
return 0;
}
static int static int
acpi_processor_set_performance ( acpi_processor_set_performance (
...@@ -231,7 +268,9 @@ acpi_processor_set_performance ( ...@@ -231,7 +268,9 @@ acpi_processor_set_performance (
int state) int state)
{ {
u16 port = 0; u16 port = 0;
u16 value = 0; u8 bit_width = 0;
int ret = 0;
u32 value = 0;
int i = 0; int i = 0;
struct cpufreq_freqs cpufreq_freqs; struct cpufreq_freqs cpufreq_freqs;
...@@ -279,12 +318,18 @@ acpi_processor_set_performance ( ...@@ -279,12 +318,18 @@ acpi_processor_set_performance (
*/ */
port = perf->control_register; port = perf->control_register;
value = (u16) perf->states[state].control; bit_width = perf->control_register_bit_width;
value = (u32) perf->states[state].control;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing 0x%04x to port 0x%04x\n", value, port)); "Writing 0x%08x to port 0x%04x\n", value, port));
outw(value, port); ret = acpi_processor_write_port(port, bit_width, value);
if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width));
return_VALUE(ret);
}
/* /*
* Then we read the 'status_register' and compare the value with the * Then we read the 'status_register' and compare the value with the
...@@ -294,14 +339,20 @@ acpi_processor_set_performance ( ...@@ -294,14 +339,20 @@ acpi_processor_set_performance (
*/ */
port = perf->status_register; port = perf->status_register;
bit_width = perf->status_register_bit_width;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Looking for 0x%04x from port 0x%04x\n", "Looking for 0x%08x from port 0x%04x\n",
(u16) perf->states[state].status, port)); (u32) perf->states[state].status, port));
for (i=0; i<100; i++) { for (i=0; i<100; i++) {
value = inw(port); ret = acpi_processor_read_port(port, bit_width, &value);
if (value == (u16) perf->states[state].status) if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width));
return_VALUE(ret);
}
if (value == (u32) perf->states[state].status)
break; break;
udelay(10); udelay(10);
} }
...@@ -309,7 +360,7 @@ acpi_processor_set_performance ( ...@@ -309,7 +360,7 @@ acpi_processor_set_performance (
/* notify cpufreq */ /* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u16) perf->states[state].status) { if (value != (u32) perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new; unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old; cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp; cpufreq_freqs.old = tmp;
......
...@@ -72,6 +72,8 @@ struct acpi_processor_performance { ...@@ -72,6 +72,8 @@ struct acpi_processor_performance {
int platform_limit; int platform_limit;
u16 control_register; u16 control_register;
u16 status_register; u16 status_register;
u8 control_register_bit_width;
u8 status_register_bit_width;
int state_count; int state_count;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE]; struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment