arch/x86/acpigen: Add OperationRegion & Field method
Add acpigen_write_opregion that generates ACPI AML code for OperationRegion, region name, region space, region length & region size are inputs. Add acpigen_write_field that generates ACPI AML code for Field. Operation region name & field list are inputs. Change-Id: I578834217d39aa3b0d409eb8ba4b5f7a31969fa8 Signed-off-by: Naresh G Solanki <naresh.solanki@intel.com> Reviewed-on: https://review.coreboot.org/17113 Reviewed-by: Furquan Shaikh <furquan@google.com> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
463f46eb61
commit
8535c66873
2 changed files with 188 additions and 0 deletions
|
@ -351,6 +351,122 @@ void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len)
|
||||||
acpigen_emit_byte(pblock_len);
|
acpigen_emit_byte(pblock_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate ACPI AML code for OperationRegion
|
||||||
|
* Arg0: Pointer to struct opregion opreg = OPREGION(rname, space, offset, len)
|
||||||
|
* where rname is region name, space is region space, offset is region offset &
|
||||||
|
* len is region length.
|
||||||
|
* OperationRegion(regionname, regionspace, regionoffset, regionlength)
|
||||||
|
*/
|
||||||
|
void acpigen_write_opregion(struct opregion *opreg)
|
||||||
|
{
|
||||||
|
/* OpregionOp */
|
||||||
|
acpigen_emit_ext_op(OPREGION_OP);
|
||||||
|
/* NameString 4 chars only */
|
||||||
|
acpigen_emit_simple_namestring(opreg->name);
|
||||||
|
/* RegionSpace */
|
||||||
|
acpigen_emit_byte(opreg->regionspace);
|
||||||
|
/* RegionOffset & RegionLen, it can be byte word or double word */
|
||||||
|
acpigen_write_integer(opreg->regionoffset);
|
||||||
|
acpigen_write_integer(opreg->regionlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void acpigen_write_field_offset(uint32_t offset,
|
||||||
|
uint32_t current_bit_pos)
|
||||||
|
{
|
||||||
|
uint32_t diff_bits;
|
||||||
|
uint8_t i, j;
|
||||||
|
uint8_t emit[4];
|
||||||
|
|
||||||
|
if (offset < current_bit_pos) {
|
||||||
|
printk(BIOS_WARNING, "%s: Cannot move offset backward",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff_bits = offset - current_bit_pos;
|
||||||
|
/* Upper limit */
|
||||||
|
if (diff_bits > 0xFFFFFFF) {
|
||||||
|
printk(BIOS_WARNING, "%s: Offset very large to encode",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 1;
|
||||||
|
if (diff_bits < 0x40) {
|
||||||
|
emit[0] = diff_bits & 0x3F;
|
||||||
|
} else {
|
||||||
|
emit[0] = diff_bits & 0xF;
|
||||||
|
diff_bits >>= 4;
|
||||||
|
while (diff_bits) {
|
||||||
|
emit[i] = diff_bits & 0xFF;
|
||||||
|
i++;
|
||||||
|
diff_bits >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update bit 7:6 : Number of bytes followed by emit[0] */
|
||||||
|
emit[0] |= (i - 1) << 6;
|
||||||
|
|
||||||
|
acpigen_emit_byte(0);
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
acpigen_emit_byte(emit[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate ACPI AML code for Field
|
||||||
|
* Arg0: region name
|
||||||
|
* Arg1: Pointer to struct fieldlist.
|
||||||
|
* Arg2: no. of entries in Arg1
|
||||||
|
* Arg3: flags which indicate filed access type, lock rule & update rule.
|
||||||
|
* Example with fieldlist
|
||||||
|
* struct fieldlist l[] = {
|
||||||
|
* FIELDLIST_OFFSET(0x84),
|
||||||
|
* FIELDLIST_NAMESTR("PMCS", 2),
|
||||||
|
* };
|
||||||
|
* acpigen_write_field("UART", l ,ARRAY_SIZE(l), FIELD_ANYACC | FIELD_NOLOCK |
|
||||||
|
* FIELD_PRESERVE);
|
||||||
|
* Output:
|
||||||
|
* Field (UART, AnyAcc, NoLock, Preserve)
|
||||||
|
* {
|
||||||
|
* Offset (0x84),
|
||||||
|
* PMCS, 2
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
void acpigen_write_field(const char *name, struct fieldlist *l, size_t count,
|
||||||
|
uint8_t flags)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint32_t current_bit_pos = 0;
|
||||||
|
|
||||||
|
/* FieldOp */
|
||||||
|
acpigen_emit_ext_op(FIELD_OP);
|
||||||
|
/* Package Length */
|
||||||
|
acpigen_write_len_f();
|
||||||
|
/* NameString 4 chars only */
|
||||||
|
acpigen_emit_simple_namestring(name);
|
||||||
|
/* Field Flag */
|
||||||
|
acpigen_emit_byte(flags);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
switch (l[i].type) {
|
||||||
|
case NAME_STRING:
|
||||||
|
acpigen_emit_simple_namestring(l[i].name);
|
||||||
|
acpigen_emit_byte(l[i].bits);
|
||||||
|
current_bit_pos += l[i].bits;
|
||||||
|
break;
|
||||||
|
case OFFSET:
|
||||||
|
acpigen_write_field_offset(l[i].bits, current_bit_pos);
|
||||||
|
current_bit_pos = l[i].bits;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk(BIOS_ERR, "%s: Invalid field type 0x%X\n"
|
||||||
|
, __func__, l[i].type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acpigen_pop_len();
|
||||||
|
}
|
||||||
|
|
||||||
void acpigen_write_empty_PCT(void)
|
void acpigen_write_empty_PCT(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -53,6 +53,8 @@ enum {
|
||||||
EXT_OP_PREFIX = 0x5B,
|
EXT_OP_PREFIX = 0x5B,
|
||||||
SLEEP_OP = 0x22,
|
SLEEP_OP = 0x22,
|
||||||
DEBUG_OP = 0x31,
|
DEBUG_OP = 0x31,
|
||||||
|
OPREGION_OP = 0x80,
|
||||||
|
FIELD_OP = 0x81,
|
||||||
DEVICE_OP = 0x82,
|
DEVICE_OP = 0x82,
|
||||||
PROCESSOR_OP = 0x83,
|
PROCESSOR_OP = 0x83,
|
||||||
POWER_RES_OP = 0x84,
|
POWER_RES_OP = 0x84,
|
||||||
|
@ -84,6 +86,64 @@ enum {
|
||||||
ONES_OP = 0xFF,
|
ONES_OP = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FIELDLIST_OFFSET(X) { .type = OFFSET, \
|
||||||
|
.name = "",\
|
||||||
|
.bits = X * 8, \
|
||||||
|
}
|
||||||
|
#define FIELDLIST_NAMESTR(X, Y) { .type = NAME_STRING, \
|
||||||
|
.name = X, \
|
||||||
|
.bits = Y, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIELD_ANYACC 0
|
||||||
|
#define FIELD_BYTEACC 1
|
||||||
|
#define FIELD_WORDACC 2
|
||||||
|
#define FIELD_DWORDACC 3
|
||||||
|
#define FIELD_QWORDACC 4
|
||||||
|
#define FIELD_BUFFERACC 5
|
||||||
|
#define FIELD_NOLOCK (0<<4)
|
||||||
|
#define FIELD_LOCK (1<<4)
|
||||||
|
#define FIELD_PRESERVE (0<<5)
|
||||||
|
#define FIELD_WRITEASONES (1<<5)
|
||||||
|
#define FIELD_WRITEASZEROS (2<<5)
|
||||||
|
|
||||||
|
enum field_type {
|
||||||
|
OFFSET,
|
||||||
|
NAME_STRING,
|
||||||
|
FIELD_TYPE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fieldlist {
|
||||||
|
enum field_type type;
|
||||||
|
const char *name;
|
||||||
|
u32 bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define OPREGION(rname, space, offset, len) {.name = rname, \
|
||||||
|
.regionspace = space, \
|
||||||
|
.regionoffset = offset, \
|
||||||
|
.regionlen = len, \
|
||||||
|
}
|
||||||
|
|
||||||
|
enum region_space {
|
||||||
|
SYSTEMMEMORY,
|
||||||
|
SYSTEMIO,
|
||||||
|
PCI_CONFIG,
|
||||||
|
EMBEDDEDCONTROL,
|
||||||
|
SMBUS,
|
||||||
|
CMOS,
|
||||||
|
PCIBARTARGET,
|
||||||
|
IPMI,
|
||||||
|
REGION_SPACE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct opregion {
|
||||||
|
const char *name;
|
||||||
|
enum region_space regionspace;
|
||||||
|
unsigned long regionoffset;
|
||||||
|
unsigned long regionlen;
|
||||||
|
};
|
||||||
|
|
||||||
void acpigen_write_len_f(void);
|
void acpigen_write_len_f(void);
|
||||||
void acpigen_pop_len(void);
|
void acpigen_pop_len(void);
|
||||||
void acpigen_set_current(char *curr);
|
void acpigen_set_current(char *curr);
|
||||||
|
@ -175,6 +235,18 @@ void acpigen_write_return_byte(uint8_t arg);
|
||||||
*/
|
*/
|
||||||
void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
|
void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
|
||||||
size_t count, void *arg);
|
size_t count, void *arg);
|
||||||
|
/*
|
||||||
|
* Generate ACPI AML code for OperationRegion
|
||||||
|
* This function takes input region name, region space, region offset & region
|
||||||
|
* length.
|
||||||
|
*/
|
||||||
|
void acpigen_write_opregion(struct opregion *opreg);
|
||||||
|
/*
|
||||||
|
* Generate ACPI AML code for Field
|
||||||
|
* This function takes input region name, fieldlist, count & flags.
|
||||||
|
*/
|
||||||
|
void acpigen_write_field(const char *name, struct fieldlist *l, size_t count,
|
||||||
|
uint8_t flags);
|
||||||
|
|
||||||
int get_cst_entries(acpi_cstate_t **);
|
int get_cst_entries(acpi_cstate_t **);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue