| 1 | |
| 2 | |
| 3 | * drivers/base/power/common.c - Common device power management code.
|
| 4 | *
|
| 5 | * Copyright (C) 2011 Rafael J. Wysocki <[email protected]>, Renesas Electronics Corp.
|
| 6 |
|
| 7 | #include <linux/kernel.h>
|
| 8 | #include <linux/device.h>
|
| 9 | #include <linux/export.h>
|
| 10 | #include <linux/slab.h>
|
| 11 | #include <linux/pm_clock.h>
|
| 12 | #include <linux/acpi.h>
|
| 13 | #include <linux/pm_domain.h>
|
| 14 | #include <linux/pm_opp.h>
|
| 15 |
|
| 16 | #include "power.h"
|
| 17 |
|
| 18 | |
| 19 | * dev_pm_get_subsys_data - Create or refcount power.subsys_data for device.
|
| 20 | * @dev: Device to handle.
|
| 21 | *
|
| 22 | * If power.subsys_data is NULL, point it to a new object, otherwise increment
|
| 23 | * its reference counter. Return 0 if new object has been created or refcount
|
| 24 | * increased, otherwise negative error code.
|
| 25 |
|
| 26 | int dev_pm_get_subsys_data(struct device *dev)
|
| 27 | {
|
| 28 | struct pm_subsys_data *psd;
|
| 29 |
|
| 30 | psd = kzalloc_obj(*psd);
|
| 31 | if (!psd)
|
| 32 | return -ENOMEM;
|
| 33 |
|
| 34 | spin_lock_irq(&dev->power.lock);
|
| 35 |
|
| 36 | if (dev->power.subsys_data) {
|
| 37 | dev->power.subsys_data->refcount++;
|
| 38 | } else {
|
| 39 | spin_lock_init(&psd->lock);
|
| 40 | psd->refcount = 1;
|
| 41 | dev->power.subsys_data = psd;
|
| 42 | pm_clk_init(dev);
|
| 43 | psd = NULL;
|
| 44 | }
|
| 45 |
|
| 46 | spin_unlock_irq(&dev->power.lock);
|
| 47 |
|
| 48 |
|
| 49 | kfree(psd);
|
| 50 |
|
| 51 | return 0;
|
| 52 | }
|
| 53 | EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data);
|
| 54 |
|
| 55 | |
| 56 | * dev_pm_put_subsys_data - Drop reference to power.subsys_data.
|
| 57 | * @dev: Device to handle.
|
| 58 | *
|
| 59 | * If the reference counter of power.subsys_data is zero after dropping the
|
| 60 | * reference, power.subsys_data is removed.
|
| 61 |
|
| 62 | void dev_pm_put_subsys_data(struct device *dev)
|
| 63 | {
|
| 64 | struct pm_subsys_data *psd;
|
| 65 |
|
| 66 | spin_lock_irq(&dev->power.lock);
|
| 67 |
|
| 68 | psd = dev_to_psd(dev);
|
| 69 | if (!psd)
|
| 70 | goto out;
|
| 71 |
|
| 72 | if (--psd->refcount == 0)
|
| 73 | dev->power.subsys_data = NULL;
|
| 74 | else
|
| 75 | psd = NULL;
|
| 76 |
|
| 77 | out:
|
| 78 | spin_unlock_irq(&dev->power.lock);
|
| 79 | kfree(psd);
|
| 80 | }
|
| 81 | EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
|
| 82 |
|
| 83 | |
| 84 | * dev_pm_domain_attach - Attach a device to its PM domain.
|
| 85 | * @dev: Device to attach.
|
| 86 | * @flags: indicate whether we should power on/off the device on attach/detach
|
| 87 | *
|
| 88 | * The @dev may only be attached to a single PM domain. By iterating through
|
| 89 | * the available alternatives we try to find a valid PM domain for the device.
|
| 90 | * As attachment succeeds, the ->detach() callback in the struct dev_pm_domain
|
| 91 | * should be assigned by the corresponding attach function.
|
| 92 | *
|
| 93 | * This function should typically be invoked from subsystem level code during
|
| 94 | * the probe phase. Especially for those that holds devices which requires
|
| 95 | * power management through PM domains.
|
| 96 | *
|
| 97 | * Callers must ensure proper synchronization of this function with power
|
| 98 | * management callbacks.
|
| 99 | *
|
| 100 | * Returns 0 on successfully attached PM domain, or when it is found that the
|
| 101 | * device doesn't need a PM domain, else a negative error code.
|
| 102 |
|
| 103 | int dev_pm_domain_attach(struct device *dev, u32 flags)
|
| 104 | {
|
| 105 | int ret;
|
| 106 |
|
| 107 | if (dev->pm_domain)
|
| 108 | return 0;
|
| 109 |
|
| 110 | ret = acpi_dev_pm_attach(dev, !!(flags & PD_FLAG_ATTACH_POWER_ON));
|
| 111 | if (!ret)
|
| 112 | ret = genpd_dev_pm_attach(dev);
|
| 113 |
|
| 114 | if (dev->pm_domain)
|
| 115 | dev->power.detach_power_off = !!(flags & PD_FLAG_DETACH_POWER_OFF);
|
| 116 |
|
| 117 | return ret < 0 ? ret : 0;
|
| 118 | }
|
| 119 | EXPORT_SYMBOL_GPL(dev_pm_domain_attach);
|
| 120 |
|
| 121 | |
| 122 | * dev_pm_domain_attach_by_id - Associate a device with one of its PM domains.
|
| 123 | * @dev: The device used to lookup the PM domain.
|
| 124 | * @index: The index of the PM domain.
|
| 125 | *
|
| 126 | * As @dev may only be attached to a single PM domain, the backend PM domain
|
| 127 | * provider creates a virtual device to attach instead. If attachment succeeds,
|
| 128 | * the ->detach() callback in the struct dev_pm_domain are assigned by the
|
| 129 | * corresponding backend attach function, as to deal with detaching of the
|
| 130 | * created virtual device.
|
| 131 | *
|
| 132 | * This function should typically be invoked by a driver during the probe phase,
|
| 133 | * in case its device requires power management through multiple PM domains. The
|
| 134 | * driver may benefit from using the received device, to configure device-links
|
| 135 | * towards its original device. Depending on the use-case and if needed, the
|
| 136 | * links may be dynamically changed by the driver, which allows it to control
|
| 137 | * the power to the PM domains independently from each other.
|
| 138 | *
|
| 139 | * Callers must ensure proper synchronization of this function with power
|
| 140 | * management callbacks.
|
| 141 | *
|
| 142 | * Returns the virtual created device when successfully attached to its PM
|
| 143 | * domain, NULL in case @dev don't need a PM domain, else an ERR_PTR().
|
| 144 | * Note that, to detach the returned virtual device, the driver shall call
|
| 145 | * dev_pm_domain_detach() on it, typically during the remove phase.
|
| 146 |
|
| 147 | struct device *dev_pm_domain_attach_by_id(struct device *dev,
|
| 148 | unsigned int index)
|
| 149 | {
|
| 150 | if (dev->pm_domain)
|
| 151 | return ERR_PTR(-EEXIST);
|
| 152 |
|
| 153 | return genpd_dev_pm_attach_by_id(dev, index);
|
| 154 | }
|
| 155 | EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_id);
|
| 156 |
|
| 157 | |
| 158 | * dev_pm_domain_attach_by_name - Associate a device with one of its PM domains.
|
| 159 | * @dev: The device used to lookup the PM domain.
|
| 160 | * @name: The name of the PM domain.
|
| 161 | *
|
| 162 | * For a detailed function description, see dev_pm_domain_attach_by_id().
|
| 163 |
|
| 164 | struct device *dev_pm_domain_attach_by_name(struct device *dev,
|
| 165 | const char *name)
|
| 166 | {
|
| 167 | if (dev->pm_domain)
|
| 168 | return ERR_PTR(-EEXIST);
|
| 169 |
|
| 170 | return genpd_dev_pm_attach_by_name(dev, name);
|
| 171 | }
|
| 172 | EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
|
| 173 |
|
| 174 | |
| 175 | * dev_pm_domain_attach_list - Associate a device with its PM domains.
|
| 176 | * @dev: The device used to lookup the PM domains for.
|
| 177 | * @data: The data used for attaching to the PM domains.
|
| 178 | * @list: An out-parameter with an allocated list of attached PM domains.
|
| 179 | *
|
| 180 | * This function helps to attach a device to its multiple PM domains. The
|
| 181 | * caller, which is typically a driver's probe function, may provide a list of
|
| 182 | * names for the PM domains that we should try to attach the device to, but it
|
| 183 | * may also provide an empty list, in case the attach should be done for all of
|
| 184 | * the available PM domains.
|
| 185 | *
|
| 186 | * Callers must ensure proper synchronization of this function with power
|
| 187 | * management callbacks.
|
| 188 | *
|
| 189 | * Returns the number of attached PM domains or a negative error code in case of
|
| 190 | * a failure. Note that, to detach the list of PM domains, the driver shall call
|
| 191 | * dev_pm_domain_detach_list(), typically during the remove phase.
|
| 192 |
|
| 193 | int dev_pm_domain_attach_list(struct device *dev,
|
| 194 | const struct dev_pm_domain_attach_data *data,
|
| 195 | struct dev_pm_domain_list **list)
|
| 196 | {
|
| 197 | struct device_node *np = dev->of_node;
|
| 198 | struct dev_pm_domain_list *pds;
|
| 199 | struct device *pd_dev = NULL;
|
| 200 | int ret, i, num_pds = 0;
|
| 201 | bool by_id = true;
|
| 202 | size_t size;
|
| 203 | u32 pd_flags = data ? data->pd_flags : 0;
|
| 204 | u32 link_flags = pd_flags & PD_FLAG_NO_DEV_LINK ? 0 :
|
| 205 | DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME;
|
| 206 |
|
| 207 | if (dev->pm_domain)
|
| 208 | return -EEXIST;
|
| 209 |
|
| 210 |
|
| 211 | if (!np)
|
| 212 | return 0;
|
| 213 |
|
| 214 | if (data && data->pd_names) {
|
| 215 | num_pds = data->num_pd_names;
|
| 216 | by_id = false;
|
| 217 | } else {
|
| 218 | num_pds = of_count_phandle_with_args(np, "power-domains",
|
| 219 | "#power-domain-cells");
|
| 220 | }
|
| 221 |
|
| 222 | if (num_pds <= 0)
|
| 223 | return 0;
|
| 224 |
|
| 225 | pds = kzalloc_obj(*pds);
|
| 226 | if (!pds)
|
| 227 | return -ENOMEM;
|
| 228 |
|
| 229 | size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links) +
|
| 230 | sizeof(*pds->opp_tokens);
|
| 231 | pds->pd_devs = kcalloc(num_pds, size, GFP_KERNEL);
|
| 232 | if (!pds->pd_devs) {
|
| 233 | ret = -ENOMEM;
|
| 234 | goto free_pds;
|
| 235 | }
|
| 236 | pds->pd_links = (void *)(pds->pd_devs + num_pds);
|
| 237 | pds->opp_tokens = (void *)(pds->pd_links + num_pds);
|
| 238 |
|
| 239 | if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
|
| 240 | link_flags |= DL_FLAG_RPM_ACTIVE;
|
| 241 |
|
| 242 | for (i = 0; i < num_pds; i++) {
|
| 243 | if (by_id)
|
| 244 | pd_dev = dev_pm_domain_attach_by_id(dev, i);
|
| 245 | else
|
| 246 | pd_dev = dev_pm_domain_attach_by_name(dev,
|
| 247 | data->pd_names[i]);
|
| 248 | if (IS_ERR_OR_NULL(pd_dev)) {
|
| 249 | ret = pd_dev ? PTR_ERR(pd_dev) : -ENODEV;
|
| 250 | goto err_attach;
|
| 251 | }
|
| 252 |
|
| 253 | if (pd_flags & PD_FLAG_REQUIRED_OPP) {
|
| 254 | struct dev_pm_opp_config config = {
|
| 255 | .required_dev = pd_dev,
|
| 256 | .required_dev_index = i,
|
| 257 | };
|
| 258 |
|
| 259 | ret = dev_pm_opp_set_config(dev, &config);
|
| 260 | if (ret < 0)
|
| 261 | goto err_link;
|
| 262 |
|
| 263 | pds->opp_tokens[i] = ret;
|
| 264 | }
|
| 265 |
|
| 266 | if (link_flags) {
|
| 267 | struct device_link *link;
|
| 268 |
|
| 269 | link = device_link_add(dev, pd_dev, link_flags);
|
| 270 | if (!link) {
|
| 271 | ret = -ENODEV;
|
| 272 | goto err_link;
|
| 273 | }
|
| 274 |
|
| 275 | pds->pd_links[i] = link;
|
| 276 | }
|
| 277 |
|
| 278 | pds->pd_devs[i] = pd_dev;
|
| 279 | }
|
| 280 |
|
| 281 | pds->num_pds = num_pds;
|
| 282 | *list = pds;
|
| 283 | return num_pds;
|
| 284 |
|
| 285 | err_link:
|
| 286 | dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
| 287 | dev_pm_domain_detach(pd_dev, true);
|
| 288 | err_attach:
|
| 289 | while (--i >= 0) {
|
| 290 | dev_pm_opp_clear_config(pds->opp_tokens[i]);
|
| 291 | if (pds->pd_links[i])
|
| 292 | device_link_del(pds->pd_links[i]);
|
| 293 | dev_pm_domain_detach(pds->pd_devs[i], true);
|
| 294 | }
|
| 295 | kfree(pds->pd_devs);
|
| 296 | free_pds:
|
| 297 | kfree(pds);
|
| 298 | return ret;
|
| 299 | }
|
| 300 | EXPORT_SYMBOL_GPL(dev_pm_domain_attach_list);
|
| 301 |
|
| 302 | |
| 303 | * devm_pm_domain_detach_list - devres-enabled version of dev_pm_domain_detach_list.
|
| 304 | * @_list: The list of PM domains to detach.
|
| 305 | *
|
| 306 | * This function reverse the actions from devm_pm_domain_attach_list().
|
| 307 | * it will be invoked during the remove phase from drivers implicitly if driver
|
| 308 | * uses devm_pm_domain_attach_list() to attach the PM domains.
|
| 309 |
|
| 310 | static void devm_pm_domain_detach_list(void *_list)
|
| 311 | {
|
| 312 | struct dev_pm_domain_list *list = _list;
|
| 313 |
|
| 314 | dev_pm_domain_detach_list(list);
|
| 315 | }
|
| 316 |
|
| 317 | |
| 318 | * devm_pm_domain_attach_list - devres-enabled version of dev_pm_domain_attach_list
|
| 319 | * @dev: The device used to lookup the PM domains for.
|
| 320 | * @data: The data used for attaching to the PM domains.
|
| 321 | * @list: An out-parameter with an allocated list of attached PM domains.
|
| 322 | *
|
| 323 | * NOTE: this will also handle calling devm_pm_domain_detach_list() for
|
| 324 | * you during remove phase.
|
| 325 | *
|
| 326 | * Returns the number of attached PM domains or a negative error code in case of
|
| 327 | * a failure.
|
| 328 |
|
| 329 | int devm_pm_domain_attach_list(struct device *dev,
|
| 330 | const struct dev_pm_domain_attach_data *data,
|
| 331 | struct dev_pm_domain_list **list)
|
| 332 | {
|
| 333 | int ret, num_pds;
|
| 334 |
|
| 335 | num_pds = dev_pm_domain_attach_list(dev, data, list);
|
| 336 | if (num_pds <= 0)
|
| 337 | return num_pds;
|
| 338 |
|
| 339 | ret = devm_add_action_or_reset(dev, devm_pm_domain_detach_list, *list);
|
| 340 | if (ret)
|
| 341 | return ret;
|
| 342 |
|
| 343 | return num_pds;
|
| 344 | }
|
| 345 | EXPORT_SYMBOL_GPL(devm_pm_domain_attach_list);
|
| 346 |
|
| 347 | |
| 348 | * dev_pm_domain_detach - Detach a device from its PM domain.
|
| 349 | * @dev: Device to detach.
|
| 350 | * @power_off: Used to indicate whether we should power off the device.
|
| 351 | *
|
| 352 | * This functions will reverse the actions from dev_pm_domain_attach(),
|
| 353 | * dev_pm_domain_attach_by_id() and dev_pm_domain_attach_by_name(), thus it
|
| 354 | * detaches @dev from its PM domain. Typically it should be invoked during the
|
| 355 | * remove phase, either from subsystem level code or from drivers.
|
| 356 | *
|
| 357 | * Callers must ensure proper synchronization of this function with power
|
| 358 | * management callbacks.
|
| 359 |
|
| 360 | void dev_pm_domain_detach(struct device *dev, bool power_off)
|
| 361 | {
|
| 362 | if (dev->pm_domain && dev->pm_domain->detach)
|
| 363 | dev->pm_domain->detach(dev, power_off);
|
| 364 | }
|
| 365 | EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
|
| 366 |
|
| 367 | |
| 368 | * dev_pm_domain_detach_list - Detach a list of PM domains.
|
| 369 | * @list: The list of PM domains to detach.
|
| 370 | *
|
| 371 | * This function reverse the actions from dev_pm_domain_attach_list().
|
| 372 | * Typically it should be invoked during the remove phase from drivers.
|
| 373 | *
|
| 374 | * Callers must ensure proper synchronization of this function with power
|
| 375 | * management callbacks.
|
| 376 |
|
| 377 | void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
|
| 378 | {
|
| 379 | int i;
|
| 380 |
|
| 381 | if (!list)
|
| 382 | return;
|
| 383 |
|
| 384 | for (i = 0; i < list->num_pds; i++) {
|
| 385 | dev_pm_opp_clear_config(list->opp_tokens[i]);
|
| 386 | if (list->pd_links[i])
|
| 387 | device_link_del(list->pd_links[i]);
|
| 388 | dev_pm_domain_detach(list->pd_devs[i], true);
|
| 389 | }
|
| 390 |
|
| 391 | kfree(list->pd_devs);
|
| 392 | kfree(list);
|
| 393 | }
|
| 394 | EXPORT_SYMBOL_GPL(dev_pm_domain_detach_list);
|
| 395 |
|
| 396 | |
| 397 | * dev_pm_domain_start - Start the device through its PM domain.
|
| 398 | * @dev: Device to start.
|
| 399 | *
|
| 400 | * This function should typically be called during probe by a subsystem/driver,
|
| 401 | * when it needs to start its device from the PM domain's perspective. Note
|
| 402 | * that, it's assumed that the PM domain is already powered on when this
|
| 403 | * function is called.
|
| 404 | *
|
| 405 | * Returns 0 on success and negative error values on failures.
|
| 406 |
|
| 407 | int dev_pm_domain_start(struct device *dev)
|
| 408 | {
|
| 409 | if (dev->pm_domain && dev->pm_domain->start)
|
| 410 | return dev->pm_domain->start(dev);
|
| 411 |
|
| 412 | return 0;
|
| 413 | }
|
| 414 | EXPORT_SYMBOL_GPL(dev_pm_domain_start);
|
| 415 |
|
| 416 | |
| 417 | * dev_pm_domain_set - Set PM domain of a device.
|
| 418 | * @dev: Device whose PM domain is to be set.
|
| 419 | * @pd: PM domain to be set, or NULL.
|
| 420 | *
|
| 421 | * Sets the PM domain the device belongs to. The PM domain of a device needs
|
| 422 | * to be set before its probe finishes (it's bound to a driver).
|
| 423 | *
|
| 424 | * This function must be called with the device lock held.
|
| 425 |
|
| 426 | void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd)
|
| 427 | {
|
| 428 | if (dev->pm_domain == pd)
|
| 429 | return;
|
| 430 |
|
| 431 | WARN(pd && device_is_bound(dev),
|
| 432 | "PM domains can only be changed for unbound devices\n");
|
| 433 | dev->pm_domain = pd;
|
| 434 | device_pm_check_callbacks(dev);
|
| 435 | }
|
| 436 | EXPORT_SYMBOL_GPL(dev_pm_domain_set);
|
| 437 |
|
| 438 | |
| 439 | * dev_pm_domain_set_performance_state - Request a new performance state.
|
| 440 | * @dev: The device to make the request for.
|
| 441 | * @state: Target performance state for the device.
|
| 442 | *
|
| 443 | * This function should be called when a new performance state needs to be
|
| 444 | * requested for a device that is attached to a PM domain. Note that, the
|
| 445 | * support for performance scaling for PM domains is optional.
|
| 446 | *
|
| 447 | * Returns 0 on success and when performance scaling isn't supported, negative
|
| 448 | * error code on failure.
|
| 449 |
|
| 450 | int dev_pm_domain_set_performance_state(struct device *dev, unsigned int state)
|
| 451 | {
|
| 452 | if (dev->pm_domain && dev->pm_domain->set_performance_state)
|
| 453 | return dev->pm_domain->set_performance_state(dev, state);
|
| 454 |
|
| 455 | return 0;
|
| 456 | }
|
| 457 | EXPORT_SYMBOL_GPL(dev_pm_domain_set_performance_state);
|