Merge branches 'acpi-pci', 'acpi-soc', 'acpi-ec' and 'acpi-osl'
* acpi-pci: ACPI, PCI: Penalize legacy IRQ used by ACPI SCI * acpi-soc: ACPI / LPSS: Ignore 10ms delay for Braswell * acpi-ec: ACPI / EC: Fix an issue caused by the serialized _Qxx evaluations * acpi-osl: ACPI / osl: replace custom implementation of readq / writeq
This commit is contained in:
@@ -445,6 +445,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
|
|||||||
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||||
|
|
||||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||||
|
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stash over-ride to indicate we've been here
|
* stash over-ride to indicate we've been here
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ ACPI_MODULE_NAME("acpi_lpss");
|
|||||||
#define LPSS_CLK_DIVIDER BIT(2)
|
#define LPSS_CLK_DIVIDER BIT(2)
|
||||||
#define LPSS_LTR BIT(3)
|
#define LPSS_LTR BIT(3)
|
||||||
#define LPSS_SAVE_CTX BIT(4)
|
#define LPSS_SAVE_CTX BIT(4)
|
||||||
|
#define LPSS_NO_D3_DELAY BIT(5)
|
||||||
|
|
||||||
struct lpss_private_data;
|
struct lpss_private_data;
|
||||||
|
|
||||||
@@ -156,6 +157,10 @@ static const struct lpss_device_desc byt_pwm_dev_desc = {
|
|||||||
.flags = LPSS_SAVE_CTX,
|
.flags = LPSS_SAVE_CTX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct lpss_device_desc bsw_pwm_dev_desc = {
|
||||||
|
.flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct lpss_device_desc byt_uart_dev_desc = {
|
static const struct lpss_device_desc byt_uart_dev_desc = {
|
||||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
||||||
.clk_con_id = "baudclk",
|
.clk_con_id = "baudclk",
|
||||||
@@ -163,6 +168,14 @@ static const struct lpss_device_desc byt_uart_dev_desc = {
|
|||||||
.setup = lpss_uart_setup,
|
.setup = lpss_uart_setup,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct lpss_device_desc bsw_uart_dev_desc = {
|
||||||
|
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
|
||||||
|
| LPSS_NO_D3_DELAY,
|
||||||
|
.clk_con_id = "baudclk",
|
||||||
|
.prv_offset = 0x800,
|
||||||
|
.setup = lpss_uart_setup,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct lpss_device_desc byt_spi_dev_desc = {
|
static const struct lpss_device_desc byt_spi_dev_desc = {
|
||||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
||||||
.prv_offset = 0x400,
|
.prv_offset = 0x400,
|
||||||
@@ -178,8 +191,15 @@ static const struct lpss_device_desc byt_i2c_dev_desc = {
|
|||||||
.setup = byt_i2c_setup,
|
.setup = byt_i2c_setup,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct lpss_device_desc bsw_i2c_dev_desc = {
|
||||||
|
.flags = LPSS_CLK | LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
|
||||||
|
.prv_offset = 0x800,
|
||||||
|
.setup = byt_i2c_setup,
|
||||||
|
};
|
||||||
|
|
||||||
static struct lpss_device_desc bsw_spi_dev_desc = {
|
static struct lpss_device_desc bsw_spi_dev_desc = {
|
||||||
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
|
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
|
||||||
|
| LPSS_NO_D3_DELAY,
|
||||||
.prv_offset = 0x400,
|
.prv_offset = 0x400,
|
||||||
.setup = lpss_deassert_reset,
|
.setup = lpss_deassert_reset,
|
||||||
};
|
};
|
||||||
@@ -214,11 +234,12 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
|||||||
{ "INT33FC", },
|
{ "INT33FC", },
|
||||||
|
|
||||||
/* Braswell LPSS devices */
|
/* Braswell LPSS devices */
|
||||||
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
|
{ "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
|
||||||
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
|
{ "8086228A", LPSS_ADDR(bsw_uart_dev_desc) },
|
||||||
{ "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
|
{ "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
|
||||||
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
|
{ "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) },
|
||||||
|
|
||||||
|
/* Broadwell LPSS devices */
|
||||||
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
|
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
|
||||||
{ "INT3431", LPSS_ADDR(lpt_dev_desc) },
|
{ "INT3431", LPSS_ADDR(lpt_dev_desc) },
|
||||||
{ "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
|
{ "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
|
||||||
@@ -558,9 +579,14 @@ static void acpi_lpss_restore_ctx(struct device *dev,
|
|||||||
* The following delay is needed or the subsequent write operations may
|
* The following delay is needed or the subsequent write operations may
|
||||||
* fail. The LPSS devices are actually PCI devices and the PCI spec
|
* fail. The LPSS devices are actually PCI devices and the PCI spec
|
||||||
* expects 10ms delay before the device can be accessed after D3 to D0
|
* expects 10ms delay before the device can be accessed after D3 to D0
|
||||||
* transition.
|
* transition. However some platforms like BSW does not need this delay.
|
||||||
*/
|
*/
|
||||||
msleep(10);
|
unsigned int delay = 10; /* default 10ms delay */
|
||||||
|
|
||||||
|
if (pdata->dev_desc->flags & LPSS_NO_D3_DELAY)
|
||||||
|
delay = 0;
|
||||||
|
|
||||||
|
msleep(delay);
|
||||||
|
|
||||||
for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
|
for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
|
||||||
unsigned long offset = i * sizeof(u32);
|
unsigned long offset = i * sizeof(u32);
|
||||||
|
|||||||
+60
-22
@@ -161,8 +161,16 @@ struct transaction {
|
|||||||
u8 flags;
|
u8 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct acpi_ec_query {
|
||||||
|
struct transaction transaction;
|
||||||
|
struct work_struct work;
|
||||||
|
struct acpi_ec_query_handler *handler;
|
||||||
|
};
|
||||||
|
|
||||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
|
static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
|
||||||
static void advance_transaction(struct acpi_ec *ec);
|
static void advance_transaction(struct acpi_ec *ec);
|
||||||
|
static void acpi_ec_event_handler(struct work_struct *work);
|
||||||
|
static void acpi_ec_event_processor(struct work_struct *work);
|
||||||
|
|
||||||
struct acpi_ec *boot_ec, *first_ec;
|
struct acpi_ec *boot_ec, *first_ec;
|
||||||
EXPORT_SYMBOL(first_ec);
|
EXPORT_SYMBOL(first_ec);
|
||||||
@@ -974,60 +982,90 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||||
|
|
||||||
static void acpi_ec_run(void *cxt)
|
static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
|
||||||
{
|
{
|
||||||
struct acpi_ec_query_handler *handler = cxt;
|
struct acpi_ec_query *q;
|
||||||
|
struct transaction *t;
|
||||||
|
|
||||||
|
q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL);
|
||||||
|
if (!q)
|
||||||
|
return NULL;
|
||||||
|
INIT_WORK(&q->work, acpi_ec_event_processor);
|
||||||
|
t = &q->transaction;
|
||||||
|
t->command = ACPI_EC_COMMAND_QUERY;
|
||||||
|
t->rdata = pval;
|
||||||
|
t->rlen = 1;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acpi_ec_delete_query(struct acpi_ec_query *q)
|
||||||
|
{
|
||||||
|
if (q) {
|
||||||
|
if (q->handler)
|
||||||
|
acpi_ec_put_query_handler(q->handler);
|
||||||
|
kfree(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acpi_ec_event_processor(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work);
|
||||||
|
struct acpi_ec_query_handler *handler = q->handler;
|
||||||
|
|
||||||
if (!handler)
|
|
||||||
return;
|
|
||||||
ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
|
ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
|
||||||
if (handler->func)
|
if (handler->func)
|
||||||
handler->func(handler->data);
|
handler->func(handler->data);
|
||||||
else if (handler->handle)
|
else if (handler->handle)
|
||||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||||
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
|
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
|
||||||
acpi_ec_put_query_handler(handler);
|
acpi_ec_delete_query(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
||||||
{
|
{
|
||||||
u8 value = 0;
|
u8 value = 0;
|
||||||
int result;
|
int result;
|
||||||
acpi_status status;
|
|
||||||
struct acpi_ec_query_handler *handler;
|
struct acpi_ec_query_handler *handler;
|
||||||
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
struct acpi_ec_query *q;
|
||||||
.wdata = NULL, .rdata = &value,
|
|
||||||
.wlen = 0, .rlen = 1};
|
q = acpi_ec_create_query(&value);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Query the EC to find out which _Qxx method we need to evaluate.
|
* Query the EC to find out which _Qxx method we need to evaluate.
|
||||||
* Note that successful completion of the query causes the ACPI_EC_SCI
|
* Note that successful completion of the query causes the ACPI_EC_SCI
|
||||||
* bit to be cleared (and thus clearing the interrupt source).
|
* bit to be cleared (and thus clearing the interrupt source).
|
||||||
*/
|
*/
|
||||||
result = acpi_ec_transaction(ec, &t);
|
result = acpi_ec_transaction(ec, &q->transaction);
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
if (data)
|
|
||||||
*data = value;
|
|
||||||
if (!value)
|
if (!value)
|
||||||
return -ENODATA;
|
result = -ENODATA;
|
||||||
|
if (result)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
mutex_lock(&ec->mutex);
|
mutex_lock(&ec->mutex);
|
||||||
list_for_each_entry(handler, &ec->list, node) {
|
list_for_each_entry(handler, &ec->list, node) {
|
||||||
if (value == handler->query_bit) {
|
if (value == handler->query_bit) {
|
||||||
/* have custom handler for this bit */
|
q->handler = acpi_ec_get_query_handler(handler);
|
||||||
handler = acpi_ec_get_query_handler(handler);
|
|
||||||
ec_dbg_evt("Query(0x%02x) scheduled",
|
ec_dbg_evt("Query(0x%02x) scheduled",
|
||||||
handler->query_bit);
|
q->handler->query_bit);
|
||||||
status = acpi_os_execute((handler->func) ?
|
/*
|
||||||
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
|
* It is reported that _Qxx are evaluated in a
|
||||||
acpi_ec_run, handler);
|
* parallel way on Windows:
|
||||||
if (ACPI_FAILURE(status))
|
* https://bugzilla.kernel.org/show_bug.cgi?id=94411
|
||||||
|
*/
|
||||||
|
if (!schedule_work(&q->work))
|
||||||
result = -EBUSY;
|
result = -EBUSY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&ec->mutex);
|
mutex_unlock(&ec->mutex);
|
||||||
|
|
||||||
|
err_exit:
|
||||||
|
if (result && q)
|
||||||
|
acpi_ec_delete_query(q);
|
||||||
|
if (data)
|
||||||
|
*data = value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-30
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm-generic/io-64-nonatomic-lo-hi.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -944,21 +945,6 @@ acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(acpi_os_write_port);
|
EXPORT_SYMBOL(acpi_os_write_port);
|
||||||
|
|
||||||
#ifdef readq
|
|
||||||
static inline u64 read64(const volatile void __iomem *addr)
|
|
||||||
{
|
|
||||||
return readq(addr);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline u64 read64(const volatile void __iomem *addr)
|
|
||||||
{
|
|
||||||
u64 l, h;
|
|
||||||
l = readl(addr);
|
|
||||||
h = readl(addr+4);
|
|
||||||
return l | (h << 32);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
||||||
{
|
{
|
||||||
@@ -991,7 +977,7 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
|||||||
*(u32 *) value = readl(virt_addr);
|
*(u32 *) value = readl(virt_addr);
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
*(u64 *) value = read64(virt_addr);
|
*(u64 *) value = readq(virt_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
@@ -1005,19 +991,6 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
|
|||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef writeq
|
|
||||||
static inline void write64(u64 val, volatile void __iomem *addr)
|
|
||||||
{
|
|
||||||
writeq(val, addr);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline void write64(u64 val, volatile void __iomem *addr)
|
|
||||||
{
|
|
||||||
writel(val, addr);
|
|
||||||
writel(val>>32, addr+4);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
||||||
{
|
{
|
||||||
@@ -1046,7 +1019,7 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
|
|||||||
writel(value, virt_addr);
|
writel(value, virt_addr);
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
write64(value, virt_addr);
|
writeq(value, virt_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
|
|||||||
@@ -821,6 +821,22 @@ void acpi_penalize_isa_irq(int irq, int active)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
|
||||||
|
* PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
|
||||||
|
* PCI IRQs.
|
||||||
|
*/
|
||||||
|
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
|
||||||
|
{
|
||||||
|
if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
|
||||||
|
if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
|
||||||
|
polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
|
||||||
|
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
|
||||||
|
else
|
||||||
|
acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Over-ride default table to reserve additional IRQs for use by ISA
|
* Over-ride default table to reserve additional IRQs for use by ISA
|
||||||
* e.g. acpi_irq_isa=5
|
* e.g. acpi_irq_isa=5
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ struct pci_dev;
|
|||||||
|
|
||||||
int acpi_pci_irq_enable (struct pci_dev *dev);
|
int acpi_pci_irq_enable (struct pci_dev *dev);
|
||||||
void acpi_penalize_isa_irq(int irq, int active);
|
void acpi_penalize_isa_irq(int irq, int active);
|
||||||
|
void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
|
||||||
void acpi_pci_irq_disable (struct pci_dev *dev);
|
void acpi_pci_irq_disable (struct pci_dev *dev);
|
||||||
|
|
||||||
extern int ec_read(u8 addr, u8 *val);
|
extern int ec_read(u8 addr, u8 *val);
|
||||||
|
|||||||
Reference in New Issue
Block a user