Changes v2 -> v1: - dropped patches which are under discussion to make the merge easy. The updated one on top of this patch series will be posted as Part II. - moved cpu_to_le{16, 32}() to util.h
Patch descriontion: This patch set abstract out chipset specific operation, and spit out i440fx specific operation into dev-i440fx.c with it. Thus q35 specific register value/operation will be added easily.
Isaku Yamahata (5): seabios: pci: introduce helper function to find device from table and initialize it. seabios: acpi: move out endian conversion helper function. seabios: acpi: move acpi definitions to acpi.h from acpi.c seabios: acpi: split out piix4 pm logic. seabios: acpi: clean up of finding pm device.
src/acpi.c | 107 +++++++++--------------------------------------------- src/acpi.h | 76 ++++++++++++++++++++++++++++++++++++++ src/dev-i440fx.c | 15 ++++++++ src/dev-i440fx.h | 1 + src/pci.c | 12 ++++++ src/pci.h | 1 + src/util.h | 10 +++++ 7 files changed, 133 insertions(+), 89 deletions(-)
introduce helper function to find device from table and initialize it. pci_find_init_device(). This will be used later.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pci.c | 12 ++++++++++++ src/pci.h | 1 + 2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/src/pci.c b/src/pci.c index c54b084..611d0e2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -203,3 +203,15 @@ int pci_init_device(const struct pci_device_id *ids, u16 bdf, void *arg) } return -1; } + +int pci_find_init_device(const struct pci_device_id *ids, void *arg) +{ + int bdf, max; + + foreachpci(bdf, max) { + if (pci_init_device(ids, bdf, arg) == 0) { + return bdf; + } + } + return -1; +} diff --git a/src/pci.h b/src/pci.h index fa6a32d..9c3108c 100644 --- a/src/pci.h +++ b/src/pci.h @@ -93,6 +93,7 @@ struct pci_device_id { }
int pci_init_device(const struct pci_device_id *table, u16 bdf, void *arg); +int pci_find_init_device(const struct pci_device_id *ids, void *arg);
// pirtable.c void create_pirtable(void);
move out cpu_to_le{32, 16} from acpi.c to util.h. Those will be used by other files later.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/acpi.c | 10 ---------- src/util.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 0559443..8de2696 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -270,16 +270,6 @@ struct srat_memory_affinity
#include "acpi-dsdt.hex"
-static inline u16 cpu_to_le16(u16 x) -{ - return x; -} - -static inline u32 cpu_to_le32(u32 x) -{ - return x; -} - static void build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) { diff --git a/src/util.h b/src/util.h index 92b3e5c..6c08a3c 100644 --- a/src/util.h +++ b/src/util.h @@ -110,6 +110,16 @@ static inline u32 __htonl(u32 val) { #define htons(x) __htons_constant(x) #define ntohs(x) htons(x)
+static inline u16 cpu_to_le16(u16 x) +{ + return x; +} + +static inline u32 cpu_to_le32(u32 x) +{ + return x; +} + static inline u32 getesp(void) { u32 esp; asm("movl %%esp, %0" : "=rm"(esp));
Move ACPI_TABLE_HEADER_DEF and struct fadt_descriptor_rev1 from acpi.h to acpi.c for later use.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/acpi.c | 73 --------------------------------------------------------- src/acpi.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 73 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 8de2696..97b496d 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -19,18 +19,6 @@ /* Table structure from Linux kernel (the ACPI tables are under the BSD license) */
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ - u32 signature; /* ACPI signature (4 ASCII characters) */ \ - u32 length; /* Length of table, in bytes, including header */ \ - u8 revision; /* ACPI Specification minor version # */ \ - u8 checksum; /* To make sum of entire table == 0 */ \ - u8 oem_id [6]; /* OEM identification */ \ - u8 oem_table_id [8]; /* OEM table identification */ \ - u32 oem_revision; /* OEM revision number */ \ - u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \ - u32 asl_compiler_revision; /* ASL compiler revision number */ - - struct acpi_table_header /* ACPI common table header */ { ACPI_TABLE_HEADER_DEF @@ -65,67 +53,6 @@ struct facs_descriptor_rev1
/* - * ACPI 1.0 Fixed ACPI Description Table (FADT) - */ -#define FACP_SIGNATURE 0x50434146 // FACP -struct fadt_descriptor_rev1 -{ - ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - u32 firmware_ctrl; /* Physical address of FACS */ - u32 dsdt; /* Physical address of DSDT */ - u8 model; /* System Interrupt Model */ - u8 reserved1; /* Reserved */ - u16 sci_int; /* System vector of SCI interrupt */ - u32 smi_cmd; /* Port address of SMI command port */ - u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ - u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ - u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ - u8 reserved2; /* Reserved - must be zero */ - u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ - u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ - u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ - u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ - u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ - u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ - u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ - u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ - u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ - u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ - u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ - u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ - u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ - u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ - u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ - u8 reserved3; /* Reserved */ - u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ - u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ - u16 flush_size; /* Size of area read to flush caches */ - u16 flush_stride; /* Stride used in flushing caches */ - u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ - u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ - u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ - u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ - u8 century; /* Index to century in RTC CMOS RAM */ - u8 reserved4; /* Reserved */ - u8 reserved4a; /* Reserved */ - u8 reserved4b; /* Reserved */ -#if 0 - u32 wb_invd : 1; /* The wbinvd instruction works properly */ - u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ - u32 proc_c1 : 1; /* All processors support C1 state */ - u32 plvl2_up : 1; /* C2 state works on MP system */ - u32 pwr_button : 1; /* Power button is handled as a generic feature */ - u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ - u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ - u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ - u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ - u32 reserved5 : 23; /* Reserved - must be zero */ -#else - u32 flags; -#endif -} PACKED; - -/* * MADT values and structures */
diff --git a/src/acpi.h b/src/acpi.h index c3ae84c..e01315a 100644 --- a/src/acpi.h +++ b/src/acpi.h @@ -22,4 +22,80 @@ struct rsdp_descriptor { /* Root System Descriptor Pointer */
extern struct rsdp_descriptor *RsdpAddr;
+/* Table structure from Linux kernel (the ACPI tables are under the + BSD license) */ + +#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ + u32 signature; /* ACPI signature (4 ASCII characters) */ \ + u32 length; /* Length of table, in bytes, including header */ \ + u8 revision; /* ACPI Specification minor version # */ \ + u8 checksum; /* To make sum of entire table == 0 */ \ + u8 oem_id [6]; /* OEM identification */ \ + u8 oem_table_id [8]; /* OEM table identification */ \ + u32 oem_revision; /* OEM revision number */ \ + u8 asl_compiler_id [4]; /* ASL compiler vendor ID */ \ + u32 asl_compiler_revision; /* ASL compiler revision number */ + + +/* + * ACPI 1.0 Fixed ACPI Description Table (FADT) + */ +#define FACP_SIGNATURE 0x50434146 // FACP +struct fadt_descriptor_rev1 +{ + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + u32 firmware_ctrl; /* Physical address of FACS */ + u32 dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 reserved1; /* Reserved */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ + u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ + u8 reserved2; /* Reserved - must be zero */ + u32 pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ + u32 pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ + u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ + u32 gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ + u8 reserved3; /* Reserved */ + u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* Size of area read to flush caches */ + u16 flush_stride; /* Stride used in flushing caches */ + u8 duty_offset; /* Bit location of duty cycle field in p_cnt reg */ + u8 duty_width; /* Bit width of duty cycle field in p_cnt reg */ + u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* Index to century in RTC CMOS RAM */ + u8 reserved4; /* Reserved */ + u8 reserved4a; /* Reserved */ + u8 reserved4b; /* Reserved */ +#if 0 + u32 wb_invd : 1; /* The wbinvd instruction works properly */ + u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ + u32 proc_c1 : 1; /* All processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ + u32 reserved5 : 23; /* Reserved - must be zero */ +#else + u32 flags; +#endif +} PACKED; + #endif // acpi.h
split out piix4 pm logic.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp
--- Changes v2 -> v3 - eliminated cpu_to_le32() stuff. The code move is done by another patch. --- src/acpi.c | 14 ++++++++++---- src/dev-i440fx.c | 15 +++++++++++++++ src/dev-i440fx.h | 1 + 3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 97b496d..5818d4c 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -12,6 +12,7 @@ #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "paravirt.h" +#include "dev-i440fx.h" // piix4_fadt_init
/****************************************************/ /* ACPI tables init */ @@ -212,6 +213,14 @@ build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) h->checksum -= checksum(h, len); }
+static const struct pci_device_id fadt_init_tbl[] = { + /* PIIX4 Power Management device (for ACPI) */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + piix4_fadt_init), + + PCI_DEVICE_END +}; + static void* build_fadt(int bdf) { @@ -241,8 +250,6 @@ build_fadt(int bdf) int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE); fadt->sci_int = cpu_to_le16(pm_sci_int); fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD); - fadt->acpi_enable = 0xf1; - fadt->acpi_disable = 0xf0; fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE); fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04); fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08); @@ -251,8 +258,7 @@ build_fadt(int bdf) fadt->pm_tmr_len = 4; fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported - fadt->gpe0_blk = cpu_to_le32(0xafe0); - fadt->gpe0_blk_len = 4; + pci_init_device(fadt_init_tbl, bdf, fadt); /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
diff --git a/src/dev-i440fx.c b/src/dev-i440fx.c index 864a52c..15c6cac 100644 --- a/src/dev-i440fx.c +++ b/src/dev-i440fx.c @@ -14,6 +14,7 @@ #include "ioport.h" // outb #include "pci.h" // pci_config_writeb #include "pci_regs.h" // PCI_INTERRUPT_LINE +#include "acpi.h" #include "dev-i440fx.h"
/* PIIX3/PIIX4 PCI to ISA bridge */ @@ -55,3 +56,17 @@ void piix4_pm_init(u16 bdf, void *arg) pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ } + +#define PIIX4_ACPI_ENABLE 0xf1 +#define PIIX4_ACPI_DISABLE 0xf0 +#define PIIX4_GPE0_BLK 0xafe0 +#define PIIX4_GPE0_BLK_LEN 4 + +void piix4_fadt_init(u16 bdf, void *arg) +{ + struct fadt_descriptor_rev1 *fadt = arg; + fadt->acpi_enable = PIIX4_ACPI_ENABLE; + fadt->acpi_disable = PIIX4_ACPI_DISABLE; + fadt->gpe0_blk = cpu_to_le32(PIIX4_GPE0_BLK); + fadt->gpe0_blk_len = PIIX4_GPE0_BLK_LEN; +} diff --git a/src/dev-i440fx.h b/src/dev-i440fx.h index ded5740..661860a 100644 --- a/src/dev-i440fx.h +++ b/src/dev-i440fx.h @@ -6,5 +6,6 @@ void piix_isa_bridge_init(u16 bdf, void *arg); void piix_ide_init(u16 bdf, void *arg); void piix4_pm_init(u16 bdf, void *arg); +void piix4_fadt_init(u16 bdf, void *arg);
#endif // __I440FX_H
Make it table driven to other chip set.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/acpi.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/acpi.c b/src/acpi.c index 5818d4c..e91f8e0 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -522,6 +522,13 @@ build_srat(void) return srat; }
+static const struct pci_device_id acpi_find_tbl[] = { + /* PIIX4 Power Management device. */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL), + + PCI_DEVICE_END, +}; + struct rsdp_descriptor *RsdpAddr;
#define MAX_ACPI_TABLES 20 @@ -534,8 +541,7 @@ acpi_bios_init(void) dprintf(3, "init ACPI tables\n");
// This code is hardcoded for PIIX4 Power Management device. - int bdf = pci_find_device(PCI_VENDOR_ID_INTEL - , PCI_DEVICE_ID_INTEL_82371AB_3); + int bdf = pci_find_init_device(acpi_find_tbl, NULL); if (bdf < 0) // Device not found return;