Beispiel #1
0
/**
 * acpi_dev_pm_attach - Prepare device for ACPI power management.
 * @dev: Device to prepare.
 * @power_on: Whether or not to power on the device.
 *
 * If @dev has a valid ACPI handle that has a valid struct acpi_device object
 * attached to it, install a wakeup notification handler for the device and
 * add it to the general ACPI PM domain.  If @power_on is set, the device will
 * be put into the ACPI D0 state before the function returns.
 *
 * This assumes that the @dev's bus type uses generic power management callbacks
 * (or doesn't use any power management callbacks at all).
 *
 * Callers must ensure proper synchronization of this function with power
 * management callbacks.
 */
int acpi_dev_pm_attach(struct device *dev, bool power_on)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (!adev)
		return -ENODEV;

	if (dev->pm_domain)
		return -EEXIST;

	/*
	 * Only attach the power domain to the first device if the
	 * companion is shared by multiple. This is to prevent doing power
	 * management twice.
	 */
	if (!acpi_device_is_first_physical_node(adev, dev))
		return -EBUSY;

	acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
	dev_pm_domain_set(dev, &acpi_general_pm_domain);
	if (power_on) {
		acpi_dev_pm_full_power(adev);
		__acpi_device_run_wake(adev, false);
	}
	return 0;
}
Beispiel #2
0
/**
 * omap_device_register - register an omap_device with one omap_hwmod
 * @od: struct omap_device * to register
 *
 * Register the omap_device structure.  This currently just calls
 * platform_device_register() on the underlying platform_device.
 * Returns the return value of platform_device_register().
 */
int omap_device_register(struct platform_device *pdev)
{
	pr_debug("omap_device: %s: registering\n", pdev->name);

	dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
	return platform_device_add(pdev);
}
Beispiel #3
0
/**
 * mei_txe_set_pm_domain - fill and set pm domain structure for device
 *
 * @dev: mei_device
 */
static inline void mei_txe_set_pm_domain(struct mei_device *dev)
{
    struct pci_dev *pdev  = to_pci_dev(dev->dev);

    if (pdev->dev.bus && pdev->dev.bus->pm) {
        dev->pg_domain.ops = *pdev->dev.bus->pm;

        dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend;
        dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume;
        dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle;

        dev_pm_domain_set(&pdev->dev, &dev->pg_domain);
    }
}
Beispiel #4
0
/**
 * acpi_dev_pm_detach - Remove ACPI power management from the device.
 * @dev: Device to take care of.
 * @power_off: Whether or not to try to remove power from the device.
 *
 * Remove the device from the general ACPI PM domain and remove its wakeup
 * notifier.  If @power_off is set, additionally remove power from the device if
 * possible.
 *
 * Callers must ensure proper synchronization of this function with power
 * management callbacks.
 */
void acpi_dev_pm_detach(struct device *dev, bool power_off)
{
	struct acpi_device *adev = acpi_dev_pm_get_node(dev);

	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
		dev_pm_domain_set(dev, NULL);
		acpi_remove_pm_notifier(adev, acpi_wakeup_device);
		if (power_off) {
			/*
			 * If the device's PM QoS resume latency limit or flags
			 * have been exposed to user space, they have to be
			 * hidden at this point, so that they don't affect the
			 * choice of the low-power state to put the device into.
			 */
			dev_pm_qos_hide_latency_limit(dev);
			dev_pm_qos_hide_flags(dev);
			__acpi_device_run_wake(adev, false);
			acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
		}
	}
}
Beispiel #5
0
/**
 * mei_txe_unset_pm_domain - clean pm domain structure for device
 *
 * @dev: mei_device
 */
static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
{
    /* stop using pm callbacks if any */
    dev_pm_domain_set(dev->dev, NULL);
}
Beispiel #6
0
/**
 * omap_device_build_from_dt - build an omap_device with multiple hwmods
 * @pdev_name: name of the platform_device driver to use
 * @pdev_id: this platform_device's connection ID
 * @oh: ptr to the single omap_hwmod that backs this omap_device
 * @pdata: platform_data ptr to associate with the platform_device
 * @pdata_len: amount of memory pointed to by @pdata
 *
 * Function for building an omap_device already registered from device-tree
 *
 * Returns 0 or PTR_ERR() on error.
 */
static int omap_device_build_from_dt(struct platform_device *pdev)
{
	struct omap_hwmod **hwmods;
	struct omap_device *od;
	struct omap_hwmod *oh;
	struct device_node *node = pdev->dev.of_node;
	const char *oh_name;
	int oh_cnt, i, ret = 0;
	bool device_active = false;

	oh_cnt = of_property_count_strings(node, "ti,hwmods");
	if (oh_cnt <= 0) {
		dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
		return -ENODEV;
	}

	hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
	if (!hwmods) {
		ret = -ENOMEM;
		goto odbfd_exit;
	}

	for (i = 0; i < oh_cnt; i++) {
		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
		oh = omap_hwmod_lookup(oh_name);
		if (!oh) {
			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
				oh_name);
			ret = -EINVAL;
			goto odbfd_exit1;
		}
		hwmods[i] = oh;
		if (oh->flags & HWMOD_INIT_NO_IDLE)
			device_active = true;
	}

	od = omap_device_alloc(pdev, hwmods, oh_cnt);
	if (IS_ERR(od)) {
		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
			oh_name);
		ret = PTR_ERR(od);
		goto odbfd_exit1;
	}

	/* Fix up missing resource names */
	for (i = 0; i < pdev->num_resources; i++) {
		struct resource *r = &pdev->resource[i];

		if (r->name == NULL)
			r->name = dev_name(&pdev->dev);
	}

	dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);

	if (device_active) {
		omap_device_enable(pdev);
		pm_runtime_set_active(&pdev->dev);
	}

odbfd_exit1:
	kfree(hwmods);
odbfd_exit:
	/* if data/we are at fault.. load up a fail handler */
	if (ret)
		dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);

	return ret;
}