superio/common/conf_mode: Add op to write SSDT

Add functions to write ACPI SSDT code for entering and leaving
the config mode.
To be used by ACPI generators.

Tested on Linux 5.2 using the Aspeed SSDT generator.

Change-Id: I14b55b885f1c384536bafafed39ad399639868e4
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/37639
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Patrick Rudolph 2019-12-10 13:15:42 +01:00 committed by Felix Held
parent 0142d441c6
commit 7db16ddc88
3 changed files with 171 additions and 1 deletions

View File

@ -31,6 +31,19 @@ void pnp_exit_conf_mode(struct device *dev)
dev->ops->ops_pnp_mode->exit_conf_mode(dev); dev->ops->ops_pnp_mode->exit_conf_mode(dev);
} }
#if CONFIG(HAVE_ACPI_TABLES)
void pnp_ssdt_enter_conf_mode(struct device *dev, const char *idx, const char *data)
{
if (dev->ops->ops_pnp_mode && dev->ops->ops_pnp_mode->ssdt_enter_conf_mode)
dev->ops->ops_pnp_mode->ssdt_enter_conf_mode(dev, idx, data);
}
void pnp_ssdt_exit_conf_mode(struct device *dev, const char *idx, const char *data)
{
if (dev->ops->ops_pnp_mode && dev->ops->ops_pnp_mode->ssdt_exit_conf_mode)
dev->ops->ops_pnp_mode->ssdt_exit_conf_mode(dev, idx, data);
}
#endif
/* PNP fundamental operations */ /* PNP fundamental operations */
void pnp_write_config(struct device *dev, u8 reg, u8 value) void pnp_write_config(struct device *dev, u8 reg, u8 value)

View File

@ -67,13 +67,34 @@ struct resource *pnp_get_resource(struct device *dev, unsigned int index);
void pnp_enable_devices(struct device *dev, struct device_operations *ops, void pnp_enable_devices(struct device *dev, struct device_operations *ops,
unsigned int functions, struct pnp_info *info); unsigned int functions, struct pnp_info *info);
struct pnp_mode_ops { struct pnp_mode_ops {
void (*enter_conf_mode)(struct device *dev); void (*enter_conf_mode)(struct device *dev);
void (*exit_conf_mode)(struct device *dev); void (*exit_conf_mode)(struct device *dev);
#if CONFIG(HAVE_ACPI_TABLES)
/*
* Generates ASL code to enter/exit config mode.
*
* @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'.
* @param data The ACPI name of the SuperIO data port register. eg. 'DATA'.
*/
void (*ssdt_enter_conf_mode)(struct device *dev, const char *idx, const char *data);
void (*ssdt_exit_conf_mode)(struct device *dev, const char *idx, const char *data);
#endif
}; };
void pnp_enter_conf_mode(struct device *dev); void pnp_enter_conf_mode(struct device *dev);
void pnp_exit_conf_mode(struct device *dev); void pnp_exit_conf_mode(struct device *dev);
#if CONFIG(HAVE_ACPI_TABLES)
/*
* Generates ASL code to enter/exit config mode if supported.
* The calling code has to place this within an ASL MethodOP.
*
* @param idx The ACPI name of the SuperIO index port register. eg. 'INDX'.
* @param data The ACPI name of the SuperIO data port register. eg. 'DATA'.
*/
void pnp_ssdt_enter_conf_mode(struct device *dev, const char *idx, const char *data);
void pnp_ssdt_exit_conf_mode(struct device *dev, const char *idx, const char *data);
#endif
/* PNP indexed I/O operations */ /* PNP indexed I/O operations */
/* /*

View File

@ -17,6 +17,7 @@
#include <arch/io.h> #include <arch/io.h>
#include <device/device.h> #include <device/device.h>
#include <superio/conf_mode.h> #include <superio/conf_mode.h>
#include <arch/acpigen.h>
/* Common enter/exit implementations */ /* Common enter/exit implementations */
@ -77,38 +78,173 @@ void pnp_exit_conf_mode_0202(struct device *dev)
pnp_write_config(dev, 0x02, (1 << 1)); pnp_write_config(dev, 0x02, (1 << 1));
} }
/* Functions for ACPI */
#if CONFIG(HAVE_ACPI_TABLES)
static void pnp_ssdt_enter_conf_mode_55(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x55);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_6767(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x67);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x67);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_7777(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x77);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x77);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_8787(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x87);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x87);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_a0a0(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0xa0);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0xa0);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_a5a5(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0xa5);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0xa5);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_enter_conf_mode_870155aa(struct device *dev,
const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x87);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x01);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x55);
acpigen_emit_namestring(idx);
acpigen_write_store();
if (dev->path.pnp.port == 0x4e)
acpigen_write_byte(0xaa);
else
acpigen_write_byte(0x55);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_exit_conf_mode_aa(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0xaa);
acpigen_emit_namestring(idx);
}
static void pnp_ssdt_exit_conf_mode_0202(struct device *dev, const char *idx, const char *data)
{
acpigen_write_store();
acpigen_write_byte(0x02);
acpigen_emit_namestring(idx);
acpigen_write_store();
acpigen_write_byte(0x02);
acpigen_emit_namestring(data);
}
#endif
const struct pnp_mode_ops pnp_conf_mode_55_aa = { const struct pnp_mode_ops pnp_conf_mode_55_aa = {
.enter_conf_mode = pnp_enter_conf_mode_55, .enter_conf_mode = pnp_enter_conf_mode_55,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_55,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_6767_aa = { const struct pnp_mode_ops pnp_conf_mode_6767_aa = {
.enter_conf_mode = pnp_enter_conf_mode_6767, .enter_conf_mode = pnp_enter_conf_mode_6767,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_6767,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_7777_aa = { const struct pnp_mode_ops pnp_conf_mode_7777_aa = {
.enter_conf_mode = pnp_enter_conf_mode_7777, .enter_conf_mode = pnp_enter_conf_mode_7777,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_7777,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_8787_aa = { const struct pnp_mode_ops pnp_conf_mode_8787_aa = {
.enter_conf_mode = pnp_enter_conf_mode_8787, .enter_conf_mode = pnp_enter_conf_mode_8787,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_8787,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_a0a0_aa = { const struct pnp_mode_ops pnp_conf_mode_a0a0_aa = {
.enter_conf_mode = pnp_enter_conf_mode_a0a0, .enter_conf_mode = pnp_enter_conf_mode_a0a0,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_a0a0,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_a5a5_aa = { const struct pnp_mode_ops pnp_conf_mode_a5a5_aa = {
.enter_conf_mode = pnp_enter_conf_mode_a5a5, .enter_conf_mode = pnp_enter_conf_mode_a5a5,
.exit_conf_mode = pnp_exit_conf_mode_aa, .exit_conf_mode = pnp_exit_conf_mode_aa,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_a5a5,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_aa,
#endif
}; };
const struct pnp_mode_ops pnp_conf_mode_870155_aa = { const struct pnp_mode_ops pnp_conf_mode_870155_aa = {
.enter_conf_mode = pnp_enter_conf_mode_870155aa, .enter_conf_mode = pnp_enter_conf_mode_870155aa,
.exit_conf_mode = pnp_exit_conf_mode_0202, .exit_conf_mode = pnp_exit_conf_mode_0202,
#if CONFIG(HAVE_ACPI_TABLES)
.ssdt_enter_conf_mode = pnp_ssdt_enter_conf_mode_870155aa,
.ssdt_exit_conf_mode = pnp_ssdt_exit_conf_mode_0202,
#endif
}; };