| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * drivers/base/power/common.c - Common device power management code. |
| 4 | * |
| 5 | * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, 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(sizeof(*psd), GFP_KERNEL); |
| 31 | if (!psd) |
| 32 | return -ENOMEM; |
| 33 | |
| 34 | spin_lock_irq(lock: &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(lock: &dev->power.lock); |
| 47 | |
| 48 | /* kfree() verifies that its argument is nonzero. */ |
| 49 | kfree(objp: 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(lock: &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(lock: &dev->power.lock); |
| 79 | kfree(objp: 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, power_on: !!(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(error: -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(error: -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 | /* For now this is limited to OF based platforms. */ |
| 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, list_name: "power-domains" , |
| 219 | cells_name: "#power-domain-cells" ); |
| 220 | } |
| 221 | |
| 222 | if (num_pds <= 0) |
| 223 | return 0; |
| 224 | |
| 225 | pds = kzalloc(sizeof(*pds), GFP_KERNEL); |
| 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(ptr: pd_dev)) { |
| 249 | ret = pd_dev ? PTR_ERR(ptr: 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: &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(consumer: dev, supplier: pd_dev, flags: 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(token: pds->opp_tokens[i]); |
| 287 | dev_pm_domain_detach(dev: pd_dev, power_off: true); |
| 288 | err_attach: |
| 289 | while (--i >= 0) { |
| 290 | dev_pm_opp_clear_config(token: pds->opp_tokens[i]); |
| 291 | if (pds->pd_links[i]) |
| 292 | device_link_del(link: pds->pd_links[i]); |
| 293 | dev_pm_domain_detach(dev: pds->pd_devs[i], power_off: true); |
| 294 | } |
| 295 | kfree(objp: pds->pd_devs); |
| 296 | free_pds: |
| 297 | kfree(objp: 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(token: list->opp_tokens[i]); |
| 386 | if (list->pd_links[i]) |
| 387 | device_link_del(link: list->pd_links[i]); |
| 388 | dev_pm_domain_detach(list->pd_devs[i], true); |
| 389 | } |
| 390 | |
| 391 | kfree(objp: list->pd_devs); |
| 392 | kfree(objp: 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); |
| 458 | |