/** * 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; }
/** * 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); }
/** * 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); } }
/** * 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); } } }
/** * 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); }
/** * 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; }