示例#1
0
文件: cppc_acpi.c 项目: 020gzh/linux
static int register_pcc_channel(int pcc_subspace_idx)
{
	struct acpi_pcct_hw_reduced *cppc_ss;
	unsigned int len;
	u64 usecs_lat;

	if (pcc_subspace_idx >= 0) {
		pcc_channel = pcc_mbox_request_channel(&cppc_mbox_cl,
				pcc_subspace_idx);

		if (IS_ERR(pcc_channel)) {
			pr_err("Failed to find PCC communication channel\n");
			return -ENODEV;
		}

		/*
		 * The PCC mailbox controller driver should
		 * have parsed the PCCT (global table of all
		 * PCC channels) and stored pointers to the
		 * subspace communication region in con_priv.
		 */
		cppc_ss = pcc_channel->con_priv;

		if (!cppc_ss) {
			pr_err("No PCC subspace found for CPPC\n");
			return -ENODEV;
		}

		/*
		 * This is the shared communication region
		 * for the OS and Platform to communicate over.
		 */
		comm_base_addr = cppc_ss->base_address;
		len = cppc_ss->length;

		/*
		 * cppc_ss->latency is just a Nominal value. In reality
		 * the remote processor could be much slower to reply.
		 * So add an arbitrary amount of wait on top of Nominal.
		 */
		usecs_lat = NUM_RETRIES * cppc_ss->latency;
		deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
		pcc_mrtt = cppc_ss->min_turnaround_time;
		pcc_mpar = cppc_ss->max_access_rate;

		pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len);
		if (!pcc_comm_addr) {
			pr_err("Failed to ioremap PCC comm region mem\n");
			return -ENOMEM;
		}

		/* Set flag so that we dont come here for each CPU. */
		pcc_channel_acquired = true;
	}

	return 0;
}
示例#2
0
static int register_pcc_channel(int pcc_ss_idx)
{
	struct acpi_pcct_hw_reduced *cppc_ss;
	u64 usecs_lat;

	if (pcc_ss_idx >= 0) {
		pcc_data[pcc_ss_idx]->pcc_channel =
			pcc_mbox_request_channel(&cppc_mbox_cl,	pcc_ss_idx);

		if (IS_ERR(pcc_data[pcc_ss_idx]->pcc_channel)) {
			pr_err("Failed to find PCC channel for subspace %d\n",
			       pcc_ss_idx);
			return -ENODEV;
		}

		/*
		 * The PCC mailbox controller driver should
		 * have parsed the PCCT (global table of all
		 * PCC channels) and stored pointers to the
		 * subspace communication region in con_priv.
		 */
		cppc_ss = (pcc_data[pcc_ss_idx]->pcc_channel)->con_priv;

		if (!cppc_ss) {
			pr_err("No PCC subspace found for %d CPPC\n",
			       pcc_ss_idx);
			return -ENODEV;
		}

		/*
		 * cppc_ss->latency is just a Nominal value. In reality
		 * the remote processor could be much slower to reply.
		 * So add an arbitrary amount of wait on top of Nominal.
		 */
		usecs_lat = NUM_RETRIES * cppc_ss->latency;
		pcc_data[pcc_ss_idx]->deadline_us = usecs_lat;
		pcc_data[pcc_ss_idx]->pcc_mrtt = cppc_ss->min_turnaround_time;
		pcc_data[pcc_ss_idx]->pcc_mpar = cppc_ss->max_access_rate;
		pcc_data[pcc_ss_idx]->pcc_nominal = cppc_ss->latency;

		pcc_data[pcc_ss_idx]->pcc_comm_addr =
			acpi_os_ioremap(cppc_ss->base_address, cppc_ss->length);
		if (!pcc_data[pcc_ss_idx]->pcc_comm_addr) {
			pr_err("Failed to ioremap PCC comm region mem for %d\n",
			       pcc_ss_idx);
			return -ENOMEM;
		}

		/* Set flag so that we dont come here for each CPU. */
		pcc_data[pcc_ss_idx]->pcc_channel_acquired = true;
	}

	return 0;
}
示例#3
0
static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
{
	unsigned long pfn;

	pfn = pg_off >> PAGE_SHIFT;
	if (should_use_kmap(pfn)) {
		if (pg_sz > PAGE_SIZE)
			return NULL;
		return (void __iomem __force *)kmap(pfn_to_page(pfn));
	} else
		return acpi_os_ioremap(pg_off, pg_sz);
}
示例#4
0
int psb_intel_opregion_setup(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct psb_intel_opregion *opregion = &dev_priv->opregion;
	u32 opregion_phy, mboxes;
	void __iomem *base;
	int err = 0;

	pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy);
	if (opregion_phy == 0) {
		DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
		return -ENOTSUPP;
	}

	INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);

	DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
	base = acpi_os_ioremap(opregion_phy, 8*1024);
	if (!base)
		return -ENOMEM;

	if (memcmp(base, OPREGION_SIGNATURE, 16)) {
		DRM_DEBUG_DRIVER("opregion signature mismatch\n");
		err = -EINVAL;
		goto err_out;
	}

	opregion->header = base;
	opregion->vbt = base + OPREGION_VBT_OFFSET;

	opregion->lid_state = base + ACPI_CLID;

	mboxes = opregion->header->mboxes;
	if (mboxes & MBOX_ACPI) {
		DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
		opregion->acpi = base + OPREGION_ACPI_OFFSET;
	}

	if (mboxes & MBOX_ASLE) {
		DRM_DEBUG_DRIVER("ASLE supported\n");
		opregion->asle = base + OPREGION_ASLE_OFFSET;
	}

	return 0;

err_out:
	iounmap(base);
	return err;
}
示例#5
0
static int register_pcc_channel(int pcc_subspace_idx)
{
	struct acpi_pcct_hw_reduced *cppc_ss;
	unsigned int len;

	if (pcc_subspace_idx >= 0) {
		pcc_channel = pcc_mbox_request_channel(&cppc_mbox_cl,
				pcc_subspace_idx);

		if (IS_ERR(pcc_channel)) {
			pr_err("Failed to find PCC communication channel\n");
			return -ENODEV;
		}

		/*
		 * The PCC mailbox controller driver should
		 * have parsed the PCCT (global table of all
		 * PCC channels) and stored pointers to the
		 * subspace communication region in con_priv.
		 */
		cppc_ss = pcc_channel->con_priv;

		if (!cppc_ss) {
			pr_err("No PCC subspace found for CPPC\n");
			return -ENODEV;
		}

		/*
		 * This is the shared communication region
		 * for the OS and Platform to communicate over.
		 */
		comm_base_addr = cppc_ss->base_address;
		len = cppc_ss->length;
		pcc_cmd_delay = cppc_ss->min_turnaround_time;

		pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len);
		if (!pcc_comm_addr) {
			pr_err("Failed to ioremap PCC comm region mem\n");
			return -ENOMEM;
		}

		/* Set flag so that we dont come here for each CPU. */
		pcc_channel_acquired = true;
	}

	return 0;
}
示例#6
0
acpi_status
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
{
	void __iomem *virt_addr;
	unsigned int size = width / 8;
	bool unmap = false;
	u64 dummy;

	rcu_read_lock();
	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
	if (!virt_addr) {
		rcu_read_unlock();
		virt_addr = acpi_os_ioremap(phys_addr, size);
		if (!virt_addr)
			return AE_BAD_ADDRESS;
		unmap = true;
	}

	if (!value)
		value = &dummy;

	switch (width) {
	case 8:
		*(u8 *) value = readb(virt_addr);
		break;
	case 16:
		*(u16 *) value = readw(virt_addr);
		break;
	case 32:
		*(u32 *) value = readl(virt_addr);
		break;
	case 64:
		*(u64 *) value = read64(virt_addr);
		break;
	default:
		BUG();
	}

	if (unmap)
		iounmap(virt_addr);
	else
		rcu_read_unlock();

	return AE_OK;
}
示例#7
0
acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
{
	void __iomem *virt_addr;
	unsigned int size = width / 8;
	bool unmap = false;

	rcu_read_lock();
	virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
	if (!virt_addr) {
		rcu_read_unlock();
		virt_addr = acpi_os_ioremap(phys_addr, size);
		if (!virt_addr)
			return AE_BAD_ADDRESS;
		unmap = true;
	}

	switch (width) {
	case 8:
		writeb(value, virt_addr);
		break;
	case 16:
		writew(value, virt_addr);
		break;
	case 32:
		writel(value, virt_addr);
		break;
	case 64:
		write64(value, virt_addr);
		break;
	default:
		BUG();
	}

	if (unmap)
		iounmap(virt_addr);
	else
		rcu_read_unlock();

	return AE_OK;
}
示例#8
0
文件: pcc.c 项目: guanhe0/kernel
/**
 * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
 *
 * Return: 0 for Success, else errno.
 */
static int __init acpi_pcc_probe(void)
{
	acpi_size pcct_tbl_header_size;
	struct acpi_table_header *pcct_tbl;
	struct acpi_subtable_header *pcct_entry;
	int count, i;
	acpi_status status = AE_OK;

	/* Search for PCCT */
	status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0,
			&pcct_tbl,
			&pcct_tbl_header_size);

	if (ACPI_FAILURE(status) || !pcct_tbl) {
		pr_warn("PCCT header not found.\n");
		return -ENODEV;
	}

	count = acpi_table_parse_entries(ACPI_SIG_PCCT,
			sizeof(struct acpi_table_pcct),
			ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
			parse_pcc_subspace, MAX_PCC_SUBSPACES);

	if (count <= 0) {
		pr_err("Error parsing PCC subspaces from PCCT\n");
		return -EINVAL;
	}

	pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
			count, GFP_KERNEL);

	if (!pcc_mbox_channels) {
		pr_err("Could not allocate space for PCC mbox channels\n");
		return -ENOMEM;
	}

	pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
	if (!pcc_doorbell_vaddr) {
		kfree(pcc_mbox_channels);
		return -ENOMEM;
	}

	/* Point to the first PCC subspace entry */
	pcct_entry = (struct acpi_subtable_header *) (
		(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));

	for (i = 0; i < count; i++) {
		struct acpi_generic_address *db_reg;
		struct acpi_pcct_hw_reduced *pcct_ss;
		pcc_mbox_channels[i].con_priv = pcct_entry;
		pcct_entry = (struct acpi_subtable_header *)
			((unsigned long) pcct_entry + pcct_entry->length);

		/* If doorbell is in system memory cache the virt address */
		pcct_ss = (struct acpi_pcct_hw_reduced *)pcct_entry;
		db_reg = &pcct_ss->doorbell_register;
		if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
			pcc_doorbell_vaddr[i] = acpi_os_ioremap(db_reg->address,
							db_reg->bit_width/8);
	}

	pcc_mbox_ctrl.num_chans = count;

	pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);

	return 0;
}