コード例 #1
0
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));
}
コード例 #2
0
/**
 * 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);
	}
}
コード例 #3
0
ファイル: acpi_table.c プロジェクト: OpenNoah/u-boot
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;
}
コード例 #4
0
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));
}
コード例 #5
0
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));
}
コード例 #6
0
/* 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);
}
コード例 #7
0
/* 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);
}
コード例 #8
0
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);
}
コード例 #9
0
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);
}
コード例 #10
0
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);
}
コード例 #11
0
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);
}
コード例 #12
0
ファイル: irq.c プロジェクト: Digilent/u-boot-digilent
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;
}
コード例 #13
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;
}
コード例 #14
0
ファイル: acpi_table.c プロジェクト: Xilinx/u-boot-xlnx
/*
 * 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;
}
コード例 #15
0
ファイル: acpi_table.c プロジェクト: Xilinx/u-boot-xlnx
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);
}
コード例 #16
0
ファイル: acpi.c プロジェクト: disdi/u-boot-x86
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);

}