static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt) { memset(rsdp, 0, sizeof(struct acpi_rsdp)); memcpy(rsdp->signature, RSDP_SIG, 8); memcpy(rsdp->oem_id, OEM_ID, 6); rsdp->length = sizeof(struct acpi_rsdp); rsdp->rsdt_address = (u32)rsdt; /* * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2 * * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2. * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR * revision 0) */ if (xsdt == NULL) { rsdp->revision = ACPI_RSDP_REV_ACPI_1_0; } else { rsdp->xsdt_address = (u64)(u32)xsdt; rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; } /* Calculate checksums */ rsdp->checksum = table_compute_checksum((void *)rsdp, 20); rsdp->ext_checksum = table_compute_checksum((void *)rsdp, sizeof(struct acpi_rsdp)); }
/** * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length * and checksum. */ static void acpi_add_table(struct acpi_rsdp *rsdp, void *table) { int i, entries_num; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt = NULL; /* The RSDT is mandatory while the XSDT is not */ rsdt = (struct acpi_rsdt *)rsdp->rsdt_address; if (rsdp->xsdt_address) xsdt = (struct acpi_xsdt *)((u32)rsdp->xsdt_address); /* This should always be MAX_ACPI_TABLES */ entries_num = ARRAY_SIZE(rsdt->entry); for (i = 0; i < entries_num; i++) { if (rsdt->entry[i] == 0) break; } if (i >= entries_num) { debug("ACPI: Error: too many tables\n"); return; } /* Add table to the RSDT */ rsdt->entry[i] = (u32)table; /* Fix RSDT length or the kernel will assume invalid entries */ rsdt->header.length = sizeof(struct acpi_table_header) + (sizeof(u32) * (i + 1)); /* Re-calculate checksum */ rsdt->header.checksum = 0; rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, rsdt->header.length); /* * And now the same thing for the XSDT. We use the same index as for * now we want the XSDT and RSDT to always be in sync in U-Boot */ if (xsdt) { /* Add table to the XSDT */ xsdt->entry[i] = (u64)(u32)table; /* Fix XSDT length */ xsdt->header.length = sizeof(struct acpi_table_header) + (sizeof(u64) * (i + 1)); /* Re-calculate checksum */ xsdt->header.checksum = 0; xsdt->header.checksum = table_compute_checksum((u8 *)xsdt, xsdt->header.length); } }
static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp) { if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) return NULL; debug("Looking on %p for valid checksum\n", rsdp); if (table_compute_checksum((void *)rsdp, 20) != 0) return NULL; debug("acpi rsdp checksum 1 passed\n"); if ((rsdp->revision > 1) && (table_compute_checksum((void *)rsdp, rsdp->length) != 0)) return NULL; debug("acpi rsdp checksum 2 passed\n"); return rsdp; }
static void acpi_write_xsdt(struct acpi_xsdt *xsdt) { struct acpi_table_header *header = &(xsdt->header); /* Fill out header fields */ acpi_fill_header(header, "XSDT"); header->length = sizeof(struct acpi_xsdt); header->revision = 1; /* Entries are filled in later, we come with an empty set */ /* Fix checksum */ header->checksum = table_compute_checksum((void *)xsdt, sizeof(struct acpi_xsdt)); }
static void acpi_write_xsdt(struct acpi_xsdt *xsdt) { acpi_header_t *header = &(xsdt->header); /* Fill out header fields */ fill_header(header, "XSDT", 4); header->length = sizeof(struct acpi_xsdt); /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ header->revision = ACPI_REV_ACPI_2_0; /* Entries are filled in later, we come with an empty set */ /* Fix checksum */ header->checksum = table_compute_checksum((void *)xsdt, sizeof(struct acpi_xsdt)); }
/* MCFG is defined in the PCI Firmware Specification 3.0 */ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) { struct acpi_table_header *header = &(mcfg->header); u32 current = (u32)mcfg + sizeof(struct acpi_mcfg); memset((void *)mcfg, 0, sizeof(struct acpi_mcfg)); /* Fill out header fields */ acpi_fill_header(header, "MCFG"); header->length = sizeof(struct acpi_mcfg); header->revision = 1; current = acpi_fill_mcfg(current); /* (Re)calculate length and checksum */ header->length = current - (u32)mcfg; header->checksum = table_compute_checksum((void *)mcfg, header->length); }
/* MCFG is defined in the PCI Firmware Specification 3.0 */ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) { acpi_header_t *header = &(mcfg->header); unsigned long current = (unsigned long)mcfg + sizeof(struct acpi_mcfg); memset((void *)mcfg, 0, sizeof(struct acpi_mcfg)); /* Fill out header fields */ fill_header(header, "MCFG", 4); header->length = sizeof(struct acpi_mcfg); /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ header->revision = ACPI_REV_ACPI_2_0; current = acpi_fill_mcfg(current); /* (Re)calculate length and checksum */ header->length = current - (unsigned long)mcfg; header->checksum = table_compute_checksum((void *)mcfg, header->length); }
static void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id) { unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t); memset((void *)ssdt, 0, sizeof(acpi_header_t)); memcpy(&ssdt->signature, "SSDT", 4); /* Access size in ACPI 2.0c/3.0/4.0/5.0 */ ssdt->revision = ACPI_REV_ACPI_3_0; memcpy(&ssdt->oem_id, OEM_ID, 6); memcpy(&ssdt->oem_table_id, oem_table_id, 8); ssdt->oem_revision = OEM_REVISION; memcpy(&ssdt->asl_compiler_id, ASLC, 4); ssdt->asl_compiler_revision = ASL_COMPILER_REVISION; ssdt->length = sizeof(acpi_header_t); /* (Re)calculate length and checksum */ ssdt->length = current - (unsigned long)ssdt; ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length); }
static void acpi_create_madt(struct acpi_madt *madt) { struct acpi_table_header *header = &(madt->header); u32 current = (u32)madt + sizeof(struct acpi_madt); memset((void *)madt, 0, sizeof(struct acpi_madt)); /* Fill out header fields */ acpi_fill_header(header, "APIC"); header->length = sizeof(struct acpi_madt); header->revision = 4; madt->lapic_addr = LAPIC_DEFAULT_BASE; madt->flags = ACPI_MADT_PCAT_COMPAT; current = acpi_fill_madt(current); /* (Re)calculate length and checksum */ header->length = current - (u32)madt; header->checksum = table_compute_checksum((void *)madt, header->length); }
static void acpi_create_madt(struct acpi_madt *madt) { acpi_header_t *header = &(madt->header); unsigned long current = (unsigned long)madt + sizeof(struct acpi_madt); memset((void *)madt, 0, sizeof(struct acpi_madt)); /* Fill out header fields */ fill_header(header, "APIC", 4); header->length = sizeof(struct acpi_madt); /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ header->revision = ACPI_REV_ACPI_2_0; madt->lapic_addr = LAPIC_DEFAULT_BASE; madt->flags = PCAT_COMPAT; current = acpi_fill_madt(current); /* (Re)calculate length and checksum */ header->length = current - (unsigned long)madt; header->checksum = table_compute_checksum((void *)madt, header->length); }
void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs, void *dsdt) { struct acpi_table_header *header = &(fadt->header); u16 pmbase = ACPI_BASE_ADDRESS; memset((void *)fadt, 0, sizeof(struct acpi_fadt)); acpi_fill_header(header, "FACP"); header->length = sizeof(struct acpi_fadt); header->revision = 4; fadt->firmware_ctrl = (u32)facs; fadt->dsdt = (u32)dsdt; fadt->preferred_pm_profile = ACPI_PM_MOBILE; fadt->sci_int = 9; fadt->smi_cmd = 0; fadt->acpi_enable = 0; fadt->acpi_disable = 0; fadt->s4bios_req = 0; fadt->pstate_cnt = 0; fadt->pm1a_evt_blk = pmbase; fadt->pm1b_evt_blk = 0x0; fadt->pm1a_cnt_blk = pmbase + 0x4; fadt->pm1b_cnt_blk = 0x0; fadt->pm2_cnt_blk = pmbase + 0x50; fadt->pm_tmr_blk = pmbase + 0x8; fadt->gpe0_blk = pmbase + 0x20; fadt->gpe1_blk = 0; fadt->pm1_evt_len = 4; fadt->pm1_cnt_len = 2; fadt->pm2_cnt_len = 1; fadt->pm_tmr_len = 4; fadt->gpe0_blk_len = 8; fadt->gpe1_blk_len = 0; fadt->gpe1_base = 0; fadt->cst_cnt = 0; fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED; fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED; fadt->flush_size = 0; fadt->flush_stride = 0; fadt->duty_offset = 1; fadt->duty_width = 0; fadt->day_alrm = 0x0d; fadt->mon_alrm = 0x00; fadt->century = 0x00; fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_RESET_REGISTER | ACPI_FADT_PLATFORM_CLOCK; fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO; fadt->reset_reg.bit_width = 8; fadt->reset_reg.bit_offset = 0; fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; fadt->reset_reg.addrl = IO_PORT_RESET; fadt->reset_reg.addrh = 0; fadt->reset_value = SYS_RST | RST_CPU; fadt->x_firmware_ctl_l = (u32)facs; fadt->x_firmware_ctl_h = 0; fadt->x_dsdt_l = (u32)dsdt; fadt->x_dsdt_h = 0; fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8; fadt->x_pm1a_evt_blk.bit_offset = 0; fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk; fadt->x_pm1a_evt_blk.addrh = 0x0; fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm1b_evt_blk.bit_width = 0; fadt->x_pm1b_evt_blk.bit_offset = 0; fadt->x_pm1b_evt_blk.access_size = 0; fadt->x_pm1b_evt_blk.addrl = 0x0; fadt->x_pm1b_evt_blk.addrh = 0x0; fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; fadt->x_pm1a_cnt_blk.bit_offset = 0; fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk; fadt->x_pm1a_cnt_blk.addrh = 0x0; fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm1b_cnt_blk.bit_width = 0; fadt->x_pm1b_cnt_blk.bit_offset = 0; fadt->x_pm1b_cnt_blk.access_size = 0; fadt->x_pm1b_cnt_blk.addrl = 0x0; fadt->x_pm1b_cnt_blk.addrh = 0x0; fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8; fadt->x_pm2_cnt_blk.bit_offset = 0; fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk; fadt->x_pm2_cnt_blk.addrh = 0x0; fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; fadt->x_pm_tmr_blk.bit_offset = 0; fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk; fadt->x_pm_tmr_blk.addrh = 0x0; fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8; fadt->x_gpe0_blk.bit_offset = 0; fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; fadt->x_gpe0_blk.addrl = fadt->gpe0_blk; fadt->x_gpe0_blk.addrh = 0x0; fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO; fadt->x_gpe1_blk.bit_width = 0; fadt->x_gpe1_blk.bit_offset = 0; fadt->x_gpe1_blk.access_size = 0; fadt->x_gpe1_blk.addrl = 0x0; fadt->x_gpe1_blk.addrh = 0x0; header->checksum = table_compute_checksum(fadt, header->length); }
static int create_pirq_routing_table(struct udevice *dev) { struct irq_router *priv = dev_get_priv(dev); const void *blob = gd->fdt_blob; int node; int len, count; const u32 *cell; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; int i; int ret; node = dev->of_offset; /* extract the bdf from fdt_pci_addr */ priv->bdf = dm_pci_get_bdf(dev->parent); ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci"); if (!ret) { priv->config = PIRQ_VIA_PCI; } else { ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "ibase"); if (!ret) priv->config = PIRQ_VIA_IBASE; else return -EINVAL; } ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); if (ret == -1) return ret; priv->link_base = ret; priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { /* Reserve IRQ9 for SCI */ priv->irq_mask &= ~(1 << 9); } if (priv->config == PIRQ_VIA_IBASE) { int ibase_off; ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); if (!ibase_off) return -EINVAL; /* * Here we assume that the IBASE register has already been * properly configured by U-Boot before. * * By 'valid' we mean: * 1) a valid memory space carved within system memory space * assigned to IBASE register block. * 2) memory range decoding is enabled. * Hence we don't do any santify test here. */ dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase); priv->ibase &= ~0xf; } priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit"); priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0); cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL; count = len / sizeof(struct pirq_routing); rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM; /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; rt->version = PIRQ_VERSION; rt->rtr_bus = PCI_BUS(priv->bdf); rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf); rt->rtr_vendor = PCI_VENDOR_ID_INTEL; rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; slot_base = rt->slots; /* Now fill in the irq_info entries in the PIRQ table */ for (i = 0; i < count; i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr; pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); slot = check_dup_entry(slot_base, irq_entries, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot) { debug("found entry for bus %d device %d, ", PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot->irq[pr.pin - 1].link) { debug("skipping\n"); /* * Sanity test on the routed PIRQ pin * * If they don't match, show a warning to tell * there might be something wrong with the PIRQ * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, priv->link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } } else { slot = slot_base + irq_entries++; } debug("writing INT%c\n", 'A' + pr.pin - 1); fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin, pr.pirq); } rt->size = irq_entries * sizeof(struct irq_info) + 32; /* Fix up the table checksum */ rt->checksum = table_compute_checksum(rt, rt->size); pirq_routing_table = rt; return 0; }
/* * QEMU's version of write_acpi_tables is defined in * arch/x86/cpu/qemu/fw_cfg.c */ unsigned long write_acpi_tables(unsigned long start) { unsigned long current; struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; struct acpi_facs *facs; acpi_header_t *dsdt; struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; acpi_header_t *ssdt; current = start; /* Align ACPI tables to 16byte */ current = ALIGN(current, 16); debug("ACPI: Writing ACPI tables at %lx.\n", start); /* We need at least an RSDP and an RSDT Table */ rsdp = (struct acpi_rsdp *)current; current += sizeof(struct acpi_rsdp); current = ALIGN(current, 16); rsdt = (struct acpi_rsdt *)current; current += sizeof(struct acpi_rsdt); current = ALIGN(current, 16); xsdt = (struct acpi_xsdt *)current; current += sizeof(struct acpi_xsdt); current = ALIGN(current, 16); /* clear all table memory */ memset((void *)start, 0, current - start); acpi_write_rsdp(rsdp, rsdt, xsdt); acpi_write_rsdt(rsdt); acpi_write_xsdt(xsdt); debug("ACPI: * FACS\n"); facs = (struct acpi_facs *)current; current += sizeof(struct acpi_facs); current = ALIGN(current, 16); acpi_create_facs(facs); debug("ACPI: * DSDT\n"); dsdt = (acpi_header_t *)current; memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); if (dsdt->length >= sizeof(acpi_header_t)) { current += sizeof(acpi_header_t); memcpy((char *)current, (char *)&AmlCode + sizeof(acpi_header_t), dsdt->length - sizeof(acpi_header_t)); current += dsdt->length - sizeof(acpi_header_t); /* (Re)calculate length and checksum */ dsdt->length = current - (unsigned long)dsdt; dsdt->checksum = 0; dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length); } current = ALIGN(current, 16); debug("ACPI: * FADT\n"); fadt = (struct acpi_fadt *)current; current += sizeof(struct acpi_fadt); current = ALIGN(current, 16); acpi_create_fadt(fadt, facs, dsdt); acpi_add_table(rsdp, fadt); debug("ACPI: * MCFG\n"); mcfg = (struct acpi_mcfg *)current; acpi_create_mcfg(mcfg); if (mcfg->header.length > sizeof(struct acpi_mcfg)) { current += mcfg->header.length; current = ALIGN(current, 16); acpi_add_table(rsdp, mcfg); } debug("ACPI: * MADT\n"); madt = (struct acpi_madt *)current; acpi_create_madt(madt); if (madt->header.length > sizeof(struct acpi_madt)) { current += madt->header.length; acpi_add_table(rsdp, madt); } current = ALIGN(current, 16); debug("ACPI: * SSDT\n"); ssdt = (acpi_header_t *)current; acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); if (ssdt->length > sizeof(acpi_header_t)) { current += ssdt->length; acpi_add_table(rsdp, ssdt); current = ALIGN(current, 16); } debug("current = %lx\n", current); debug("ACPI: done.\n"); return current; }
/* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ ulong write_acpi_tables(ulong start) { u32 current; struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; struct acpi_facs *facs; struct acpi_table_header *dsdt; struct acpi_fadt *fadt; struct acpi_mcfg *mcfg; struct acpi_madt *madt; struct acpi_spcr *spcr; int i; current = start; /* Align ACPI tables to 16 byte */ current = ALIGN(current, 16); debug("ACPI: Writing ACPI tables at %lx\n", start); /* We need at least an RSDP and an RSDT Table */ rsdp = (struct acpi_rsdp *)current; current += sizeof(struct acpi_rsdp); current = ALIGN(current, 16); rsdt = (struct acpi_rsdt *)current; current += sizeof(struct acpi_rsdt); current = ALIGN(current, 16); xsdt = (struct acpi_xsdt *)current; current += sizeof(struct acpi_xsdt); /* * Per ACPI spec, the FACS table address must be aligned to a 64 byte * boundary (Windows checks this, but Linux does not). */ current = ALIGN(current, 64); /* clear all table memory */ memset((void *)start, 0, current - start); acpi_write_rsdp(rsdp, rsdt, xsdt); acpi_write_rsdt(rsdt); acpi_write_xsdt(xsdt); debug("ACPI: * FACS\n"); facs = (struct acpi_facs *)current; current += sizeof(struct acpi_facs); current = ALIGN(current, 16); acpi_create_facs(facs); debug("ACPI: * DSDT\n"); dsdt = (struct acpi_table_header *)current; memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header)); current += sizeof(struct acpi_table_header); memcpy((char *)current, (char *)&AmlCode + sizeof(struct acpi_table_header), dsdt->length - sizeof(struct acpi_table_header)); current += dsdt->length - sizeof(struct acpi_table_header); current = ALIGN(current, 16); /* Pack GNVS into the ACPI table area */ for (i = 0; i < dsdt->length; i++) { u32 *gnvs = (u32 *)((u32)dsdt + i); if (*gnvs == ACPI_GNVS_ADDR) { debug("Fix up global NVS in DSDT to 0x%08x\n", current); *gnvs = current; break; } } /* Update DSDT checksum since we patched the GNVS address */ dsdt->checksum = 0; dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length); /* Fill in platform-specific global NVS variables */ acpi_create_gnvs((struct acpi_global_nvs *)current); current += sizeof(struct acpi_global_nvs); current = ALIGN(current, 16); debug("ACPI: * FADT\n"); fadt = (struct acpi_fadt *)current; current += sizeof(struct acpi_fadt); current = ALIGN(current, 16); acpi_create_fadt(fadt, facs, dsdt); acpi_add_table(rsdp, fadt); debug("ACPI: * MADT\n"); madt = (struct acpi_madt *)current; acpi_create_madt(madt); current += madt->header.length; acpi_add_table(rsdp, madt); current = ALIGN(current, 16); debug("ACPI: * MCFG\n"); mcfg = (struct acpi_mcfg *)current; acpi_create_mcfg(mcfg); current += mcfg->header.length; acpi_add_table(rsdp, mcfg); current = ALIGN(current, 16); debug("ACPI: * SPCR\n"); spcr = (struct acpi_spcr *)current; acpi_create_spcr(spcr); current += spcr->header.length; acpi_add_table(rsdp, spcr); current = ALIGN(current, 16); debug("current = %x\n", current); acpi_rsdp_addr = (unsigned long)rsdp; debug("ACPI: done\n"); return current; }
static void acpi_create_spcr(struct acpi_spcr *spcr) { struct acpi_table_header *header = &(spcr->header); struct serial_device_info serial_info = {0}; ulong serial_address, serial_offset; uint serial_config; uint serial_width; int access_size; int space_id; int ret; /* Fill out header fields */ acpi_fill_header(header, "SPCR"); header->length = sizeof(struct acpi_spcr); header->revision = 2; ret = serial_getinfo(&serial_info); if (ret) serial_info.type = SERIAL_CHIP_UNKNOWN; /* Encode chip type */ switch (serial_info.type) { case SERIAL_CHIP_16550_COMPATIBLE: spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE; break; case SERIAL_CHIP_UNKNOWN: default: spcr->interface_type = ACPI_DBG2_UNKNOWN; break; } /* Encode address space */ switch (serial_info.addr_space) { case SERIAL_ADDRESS_SPACE_MEMORY: space_id = ACPI_ADDRESS_SPACE_MEMORY; break; case SERIAL_ADDRESS_SPACE_IO: default: space_id = ACPI_ADDRESS_SPACE_IO; break; } serial_width = serial_info.reg_width * 8; serial_offset = serial_info.reg_offset << serial_info.reg_shift; serial_address = serial_info.addr + serial_offset; /* Encode register access size */ switch (serial_info.reg_shift) { case 0: access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS; break; case 1: access_size = ACPI_ACCESS_SIZE_WORD_ACCESS; break; case 2: access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS; break; case 3: access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS; break; default: access_size = ACPI_ACCESS_SIZE_UNDEFINED; break; } debug("UART type %u @ %lx\n", spcr->interface_type, serial_address); /* Fill GAS */ spcr->serial_port.space_id = space_id; spcr->serial_port.bit_width = serial_width; spcr->serial_port.bit_offset = 0; spcr->serial_port.access_size = access_size; spcr->serial_port.addrl = lower_32_bits(serial_address); spcr->serial_port.addrh = upper_32_bits(serial_address); /* Encode baud rate */ switch (serial_info.baudrate) { case 9600: spcr->baud_rate = 3; break; case 19200: spcr->baud_rate = 4; break; case 57600: spcr->baud_rate = 6; break; case 115200: spcr->baud_rate = 7; break; default: spcr->baud_rate = 0; break; } ret = serial_getconfig(&serial_config); if (ret) serial_config = SERIAL_DEFAULT_CONFIG; spcr->parity = SERIAL_GET_PARITY(serial_config); spcr->stop_bits = SERIAL_GET_STOP(serial_config); /* No PCI devices for now */ spcr->pci_device_id = 0xffff; spcr->pci_vendor_id = 0xffff; /* Fix checksum */ header->checksum = table_compute_checksum((void *)spcr, header->length); }
void acpi_create_fadt(struct acpi_fadt * fadt, struct acpi_facs * facs, void *dsdt) { acpi_header_t *header = &(fadt->header); u16 pmbase; pci_dev_t bdf = PCI_BDF(0, 0x1f, 0); pci_read_config_word(bdf, 0x40, &pmbase); //wrong value of pmbase by above function. Harcoding it to correct value. pmbase = 0x0600; memset((void *) fadt, 0, sizeof(struct acpi_fadt)); memcpy(header->signature, "FACP", 4); header->length = sizeof(struct acpi_fadt); header->revision = 3; memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); header->asl_compiler_revision = 0; fadt->firmware_ctrl = (unsigned long) facs; fadt->dsdt = (unsigned long) dsdt; fadt->model = 0x00; fadt->preferred_pm_profile = PM_MOBILE; fadt->sci_int = 0x9; fadt->smi_cmd = 0; fadt->acpi_enable = 0; fadt->acpi_disable = 0; fadt->s4bios_req = 0x0; fadt->pstate_cnt = 0; fadt->pm1a_evt_blk = pmbase; fadt->pm1b_evt_blk = 0x0; fadt->pm1a_cnt_blk = pmbase + 0x4; fadt->pm1b_cnt_blk = 0x0; fadt->pm2_cnt_blk = pmbase + 0x50; fadt->pm_tmr_blk = pmbase + 0x8; fadt->gpe0_blk = pmbase + 0x20; fadt->gpe1_blk = 0; fadt->pm1_evt_len = 4; fadt->pm1_cnt_len = 2; /* Upper word is reserved and Linux complains about 32 bit. */ fadt->pm2_cnt_len = 1; fadt->pm_tmr_len = 4; fadt->gpe0_blk_len = 16; fadt->gpe1_blk_len = 0; fadt->gpe1_base = 0; fadt->cst_cnt = 0; fadt->p_lvl2_lat = 1; fadt->p_lvl3_lat = 0x39; fadt->flush_size = 0; fadt->flush_stride = 0; fadt->duty_offset = 1; fadt->duty_width = 3; fadt->day_alrm = 0xd; fadt->mon_alrm = 0x00; fadt->century = 0x32; fadt->iapc_boot_arch = 0x00; fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_DOCKING_SUPPORTED | ACPI_FADT_RESET_REGISTER | ACPI_FADT_PLATFORM_CLOCK; fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO; fadt->reset_reg.bit_width = 8; fadt->reset_reg.bit_offset = 0; fadt->reset_reg.resv = 0; fadt->reset_reg.addrl = 0xcf9; fadt->reset_reg.addrh = 0; fadt->reset_value = 0x06; fadt->x_firmware_ctl_l = 0; /* Set X_FIRMWARE_CTRL only if FACS is */ fadt->x_firmware_ctl_h = 0; /* above 4GB. If X_FIRMWARE_CTRL is set, */ /* then FIRMWARE_CTRL must be zero. */ fadt->x_dsdt_l = (unsigned long)dsdt; fadt->x_dsdt_h = 0; fadt->x_pm1a_evt_blk.space_id = 1; fadt->x_pm1a_evt_blk.bit_width = 32; fadt->x_pm1a_evt_blk.bit_offset = 0; fadt->x_pm1a_evt_blk.resv = 0; fadt->x_pm1a_evt_blk.addrl = pmbase; fadt->x_pm1a_evt_blk.addrh = 0x0; fadt->x_pm1b_evt_blk.space_id = 0; fadt->x_pm1b_evt_blk.bit_width = 0; fadt->x_pm1b_evt_blk.bit_offset = 0; fadt->x_pm1b_evt_blk.resv = 0; fadt->x_pm1b_evt_blk.addrl = 0x0; fadt->x_pm1b_evt_blk.addrh = 0x0; fadt->x_pm1a_cnt_blk.space_id = 1; fadt->x_pm1a_cnt_blk.bit_width = 16; /* Upper word is reserved and Linux complains about 32 bit. */ fadt->x_pm1a_cnt_blk.bit_offset = 0; fadt->x_pm1a_cnt_blk.resv = 0; fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; fadt->x_pm1a_cnt_blk.addrh = 0x0; fadt->x_pm1b_cnt_blk.space_id = 0; fadt->x_pm1b_cnt_blk.bit_width = 0; fadt->x_pm1b_cnt_blk.bit_offset = 0; fadt->x_pm1b_cnt_blk.resv = 0; fadt->x_pm1b_cnt_blk.addrl = 0x0; fadt->x_pm1b_cnt_blk.addrh = 0x0; fadt->x_pm2_cnt_blk.space_id = 1; fadt->x_pm2_cnt_blk.bit_width = 8; fadt->x_pm2_cnt_blk.bit_offset = 0; fadt->x_pm2_cnt_blk.resv = 0; fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; fadt->x_pm2_cnt_blk.addrh = 0x0; fadt->x_pm_tmr_blk.space_id = 1; fadt->x_pm_tmr_blk.bit_width = 32; fadt->x_pm_tmr_blk.bit_offset = 0; fadt->x_pm_tmr_blk.resv = 0; fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; fadt->x_pm_tmr_blk.addrh = 0x0; fadt->x_gpe0_blk.space_id = 1; fadt->x_gpe0_blk.bit_width = 128; fadt->x_gpe0_blk.bit_offset = 0; fadt->x_gpe0_blk.resv = 0; fadt->x_gpe0_blk.addrl = pmbase + 0x20; fadt->x_gpe0_blk.addrh = 0x0; fadt->x_gpe1_blk.space_id = 0; fadt->x_gpe1_blk.bit_width = 0; fadt->x_gpe1_blk.bit_offset = 0; fadt->x_gpe1_blk.resv = 0; fadt->x_gpe1_blk.addrl = 0x0; fadt->x_gpe1_blk.addrh = 0x0; header->checksum = table_compute_checksum((void *) fadt, header->length); }