1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (c) 2016, NVIDIA CORPORATION. 4 */ 5 6#ifndef _POWER_DOMAIN_H 7#define _POWER_DOMAIN_H 8 9#include <linux/errno.h> 10 11/** 12 * A power domain is a portion of an SoC or chip that is powered by a 13 * switchable source of power. In many cases, software has control over the 14 * power domain, and can turn the power source on or off. This is typically 15 * done to save power by powering off unused devices, or to enable software 16 * sequencing of initial powerup at boot. This API provides a means for 17 * drivers to turn power domains on and off. 18 * 19 * A driver that implements UCLASS_POWER_DOMAIN is a power domain controller or 20 * provider. A controller will often implement multiple separate power domains, 21 * since the hardware it manages often has this capability. 22 * power-domain-uclass.h describes the interface which power domain controllers 23 * must implement. 24 * 25 * Depending on the power domain controller hardware, changing the state of a 26 * power domain may require performing related operations on other resources. 27 * For example, some power domains may require certain clocks to be enabled 28 * whenever the power domain is powered on, or during the time when the power 29 * domain is transitioning state. These details are implementation-specific 30 * and should ideally be encapsulated entirely within the provider driver, or 31 * configured through mechanisms (e.g. device tree) that do not require client 32 * drivers to provide extra configuration information. 33 * 34 * Power domain consumers/clients are the drivers for HW modules within the 35 * power domain. This header file describes the API used by those drivers. 36 * 37 * In many cases, a single complex IO controller (e.g. a PCIe controller) will 38 * be the sole logic contained within a power domain. In such cases, it is 39 * logical for the relevant device driver to directly control that power 40 * domain. In other cases, multiple controllers, each with their own driver, 41 * may be contained in a single power domain. Any logic require to co-ordinate 42 * between drivers for these multiple controllers is beyond the scope of this 43 * API at present. Equally, this API does not define or implement any policy 44 * by which power domains are managed. 45 */ 46 47struct udevice; 48 49/** 50 * struct power_domain - A handle to (allowing control of) a single power domain. 51 * 52 * Clients provide storage for power domain handles. The content of the 53 * structure is managed solely by the power domain API and power domain 54 * drivers. A power domain struct is initialized by "get"ing the power domain 55 * struct. The power domain struct is passed to all other power domain APIs to 56 * identify which power domain to operate upon. 57 * 58 * @dev: The device which implements the power domain. 59 * @id: The power domain ID within the provider. 60 * @priv: Private data corresponding to each power domain. 61 */ 62struct power_domain { 63 struct udevice *dev; 64 unsigned long id; 65 void *priv; 66}; 67 68/** 69 * power_domain_get - Get/request the power domain for a device. 70 * 71 * This looks up and requests a power domain. Each device is assumed to have 72 * a single (or, at least one) power domain associated with it somehow, and 73 * that domain, or the first/default domain. The mapping of client device to 74 * provider power domain may be via device-tree properties, board-provided 75 * mapping tables, or some other mechanism. 76 * 77 * @dev: The client device. 78 * @power_domain A pointer to a power domain struct to initialize. 79 * Return: 0 if OK, or a negative error code. 80 */ 81#if CONFIG_IS_ENABLED(POWER_DOMAIN) 82int power_domain_get(struct udevice *dev, struct power_domain *power_domain); 83#else 84static inline 85int power_domain_get(struct udevice *dev, struct power_domain *power_domain) 86{ 87 return -ENOSYS; 88} 89#endif 90 91/** 92 * power_domain_get_by_index - Get the indexed power domain for a device. 93 * 94 * @dev: The client device. 95 * @power_domain: A pointer to a power domain struct to initialize. 96 * @index: Power domain index to be powered on. 97 * 98 * Return: 0 if OK, or a negative error code. 99 */ 100#if CONFIG_IS_ENABLED(POWER_DOMAIN) 101int power_domain_get_by_index(struct udevice *dev, 102 struct power_domain *power_domain, int index); 103#else 104static inline 105int power_domain_get_by_index(struct udevice *dev, 106 struct power_domain *power_domain, int index) 107{ 108 return -ENOSYS; 109} 110#endif 111 112/** 113 * power_domain_get_by_name - Get the named power domain for a device. 114 * 115 * @dev: The client device. 116 * @power_domain: A pointer to a power domain struct to initialize. 117 * @name: Power domain name to be powered on. 118 * 119 * Return: 0 if OK, or a negative error code. 120 */ 121#if CONFIG_IS_ENABLED(POWER_DOMAIN) 122int power_domain_get_by_name(struct udevice *dev, 123 struct power_domain *power_domain, const char *name); 124#else 125static inline 126int power_domain_get_by_name(struct udevice *dev, 127 struct power_domain *power_domain, const char *name) 128{ 129 return -ENOSYS; 130} 131#endif 132 133/** 134 * power_domain_free - Free a previously requested power domain. 135 * 136 * @power_domain: A power domain struct that was previously successfully 137 * requested by power_domain_get(). 138 * Return: 0 if OK, or a negative error code. 139 */ 140#if CONFIG_IS_ENABLED(POWER_DOMAIN) 141int power_domain_free(struct power_domain *power_domain); 142#else 143static inline int power_domain_free(struct power_domain *power_domain) 144{ 145 return -ENOSYS; 146} 147#endif 148 149/** 150 * power_domain_on - Enable power to a power domain. 151 * 152 * @power_domain: A power domain struct that was previously successfully 153 * requested by power_domain_get(). 154 * Return: 0 if OK, or a negative error code. 155 */ 156#if CONFIG_IS_ENABLED(POWER_DOMAIN) 157int power_domain_on(struct power_domain *power_domain); 158#else 159static inline int power_domain_on(struct power_domain *power_domain) 160{ 161 return -ENOSYS; 162} 163#endif 164 165/** 166 * power_domain_off - Disable power to a power domain. 167 * 168 * @power_domain: A power domain struct that was previously successfully 169 * requested by power_domain_get(). 170 * Return: 0 if OK, or a negative error code. 171 */ 172#if CONFIG_IS_ENABLED(POWER_DOMAIN) 173int power_domain_off(struct power_domain *power_domain); 174#else 175static inline int power_domain_off(struct power_domain *power_domain) 176{ 177 return -ENOSYS; 178} 179#endif 180 181/** 182 * dev_power_domain_on - Enable power domains for a device . 183 * 184 * @dev: The client device. 185 * 186 * Return: 0 if OK, or a negative error code. 187 */ 188#if CONFIG_IS_ENABLED(OF_REAL) && CONFIG_IS_ENABLED(POWER_DOMAIN) 189int dev_power_domain_on(struct udevice *dev); 190#else 191static inline int dev_power_domain_on(struct udevice *dev) 192{ 193 return 0; 194} 195#endif 196 197/** 198 * dev_power_domain_off - Disable power domains for a device . 199 * 200 * @dev: The client device. 201 * 202 * Return: 0 if OK, or a negative error code. 203 */ 204#if CONFIG_IS_ENABLED(OF_REAL) && CONFIG_IS_ENABLED(POWER_DOMAIN) 205int dev_power_domain_off(struct udevice *dev); 206#else 207static inline int dev_power_domain_off(struct udevice *dev) 208{ 209 return 0; 210} 211#endif 212 213#endif 214