161f5ddcbSStephen Warren /* 261f5ddcbSStephen Warren * Copyright (c) 2016, NVIDIA CORPORATION. 361f5ddcbSStephen Warren * 461f5ddcbSStephen Warren * SPDX-License-Identifier: GPL-2.0 561f5ddcbSStephen Warren */ 661f5ddcbSStephen Warren 761f5ddcbSStephen Warren #ifndef _POWER_DOMAIN_H 861f5ddcbSStephen Warren #define _POWER_DOMAIN_H 961f5ddcbSStephen Warren 1061f5ddcbSStephen Warren /** 1161f5ddcbSStephen Warren * A power domain is a portion of an SoC or chip that is powered by a 1261f5ddcbSStephen Warren * switchable source of power. In many cases, software has control over the 1361f5ddcbSStephen Warren * power domain, and can turn the power source on or off. This is typically 1461f5ddcbSStephen Warren * done to save power by powering off unused devices, or to enable software 1561f5ddcbSStephen Warren * sequencing of initial powerup at boot. This API provides a means for 1661f5ddcbSStephen Warren * drivers to turn power domains on and off. 1761f5ddcbSStephen Warren * 1861f5ddcbSStephen Warren * A driver that implements UCLASS_POWER_DOMAIN is a power domain controller or 1961f5ddcbSStephen Warren * provider. A controller will often implement multiple separate power domains, 2061f5ddcbSStephen Warren * since the hardware it manages often has this capability. 2161f5ddcbSStephen Warren * power-domain-uclass.h describes the interface which power domain controllers 2261f5ddcbSStephen Warren * must implement. 2361f5ddcbSStephen Warren * 2461f5ddcbSStephen Warren * Depending on the power domain controller hardware, changing the state of a 2561f5ddcbSStephen Warren * power domain may require performing related operations on other resources. 2661f5ddcbSStephen Warren * For example, some power domains may require certain clocks to be enabled 2761f5ddcbSStephen Warren * whenever the power domain is powered on, or during the time when the power 2861f5ddcbSStephen Warren * domain is transitioning state. These details are implementation-specific 2961f5ddcbSStephen Warren * and should ideally be encapsulated entirely within the provider driver, or 3061f5ddcbSStephen Warren * configured through mechanisms (e.g. device tree) that do not require client 3161f5ddcbSStephen Warren * drivers to provide extra configuration information. 3261f5ddcbSStephen Warren * 3361f5ddcbSStephen Warren * Power domain consumers/clients are the drivers for HW modules within the 3461f5ddcbSStephen Warren * power domain. This header file describes the API used by those drivers. 3561f5ddcbSStephen Warren * 3661f5ddcbSStephen Warren * In many cases, a single complex IO controller (e.g. a PCIe controller) will 3761f5ddcbSStephen Warren * be the sole logic contained within a power domain. In such cases, it is 3861f5ddcbSStephen Warren * logical for the relevant device driver to directly control that power 3961f5ddcbSStephen Warren * domain. In other cases, multiple controllers, each with their own driver, 4061f5ddcbSStephen Warren * may be contained in a single power domain. Any logic require to co-ordinate 4161f5ddcbSStephen Warren * between drivers for these multiple controllers is beyond the scope of this 4261f5ddcbSStephen Warren * API at present. Equally, this API does not define or implement any policy 4361f5ddcbSStephen Warren * by which power domains are managed. 4461f5ddcbSStephen Warren */ 4561f5ddcbSStephen Warren 4661f5ddcbSStephen Warren struct udevice; 4761f5ddcbSStephen Warren 4861f5ddcbSStephen Warren /** 4961f5ddcbSStephen Warren * struct power_domain - A handle to (allowing control of) a single power domain. 5061f5ddcbSStephen Warren * 5161f5ddcbSStephen Warren * Clients provide storage for power domain handles. The content of the 5261f5ddcbSStephen Warren * structure is managed solely by the power domain API and power domain 5361f5ddcbSStephen Warren * drivers. A power domain struct is initialized by "get"ing the power domain 5461f5ddcbSStephen Warren * struct. The power domain struct is passed to all other power domain APIs to 5561f5ddcbSStephen Warren * identify which power domain to operate upon. 5661f5ddcbSStephen Warren * 5761f5ddcbSStephen Warren * @dev: The device which implements the power domain. 5861f5ddcbSStephen Warren * @id: The power domain ID within the provider. 5961f5ddcbSStephen Warren * 6061f5ddcbSStephen Warren * Currently, the power domain API assumes that a single integer ID is enough 6161f5ddcbSStephen Warren * to identify and configure any power domain for any power domain provider. If 6261f5ddcbSStephen Warren * this assumption becomes invalid in the future, the struct could be expanded 6361f5ddcbSStephen Warren * to either (a) add more fields to allow power domain providers to store 6461f5ddcbSStephen Warren * additional information, or (b) replace the id field with an opaque pointer, 6561f5ddcbSStephen Warren * which the provider would dynamically allocate during its .of_xlate op, and 6661f5ddcbSStephen Warren * process during is .request op. This may require the addition of an extra op 6761f5ddcbSStephen Warren * to clean up the allocation. 6861f5ddcbSStephen Warren */ 6961f5ddcbSStephen Warren struct power_domain { 7061f5ddcbSStephen Warren struct udevice *dev; 7161f5ddcbSStephen Warren /* 7261f5ddcbSStephen Warren * Written by of_xlate. We assume a single id is enough for now. In the 7361f5ddcbSStephen Warren * future, we might add more fields here. 7461f5ddcbSStephen Warren */ 7561f5ddcbSStephen Warren unsigned long id; 7661f5ddcbSStephen Warren }; 7761f5ddcbSStephen Warren 7861f5ddcbSStephen Warren /** 7961f5ddcbSStephen Warren * power_domain_get - Get/request the power domain for a device. 8061f5ddcbSStephen Warren * 8161f5ddcbSStephen Warren * This looks up and requests a power domain. Each device is assumed to have 8261f5ddcbSStephen Warren * a single (or, at least one) power domain associated with it somehow, and 8361f5ddcbSStephen Warren * that domain, or the first/default domain. The mapping of client device to 8461f5ddcbSStephen Warren * provider power domain may be via device-tree properties, board-provided 8561f5ddcbSStephen Warren * mapping tables, or some other mechanism. 8661f5ddcbSStephen Warren * 8761f5ddcbSStephen Warren * @dev: The client device. 8861f5ddcbSStephen Warren * @power_domain A pointer to a power domain struct to initialize. 8961f5ddcbSStephen Warren * @return 0 if OK, or a negative error code. 9061f5ddcbSStephen Warren */ 9161f5ddcbSStephen Warren int power_domain_get(struct udevice *dev, struct power_domain *power_domain); 9261f5ddcbSStephen Warren 9361f5ddcbSStephen Warren /** 9492ac3df1SLokesh Vutla * power_domain_get_by_index - Get the indexed power domain for a device. 9592ac3df1SLokesh Vutla * 9692ac3df1SLokesh Vutla * @dev: The client device. 9792ac3df1SLokesh Vutla * @power_domain: A pointer to a power domain struct to initialize. 9892ac3df1SLokesh Vutla * @index: Power domain index to be powered on. 9992ac3df1SLokesh Vutla * 10092ac3df1SLokesh Vutla * @return 0 if OK, or a negative error code. 10192ac3df1SLokesh Vutla */ 10292ac3df1SLokesh Vutla #if CONFIG_IS_ENABLED(POWER_DOMAIN) 10392ac3df1SLokesh Vutla int power_domain_get_by_index(struct udevice *dev, 10492ac3df1SLokesh Vutla struct power_domain *power_domain, int index); 10592ac3df1SLokesh Vutla #else 10692ac3df1SLokesh Vutla static inline 10792ac3df1SLokesh Vutla int power_domain_get_by_index(struct udevice *dev, 10892ac3df1SLokesh Vutla struct power_domain *power_domain, int index) 10992ac3df1SLokesh Vutla { 11092ac3df1SLokesh Vutla return -ENOSYS; 11192ac3df1SLokesh Vutla } 11292ac3df1SLokesh Vutla #endif 11392ac3df1SLokesh Vutla 11492ac3df1SLokesh Vutla /** 11561f5ddcbSStephen Warren * power_domain_free - Free a previously requested power domain. 11661f5ddcbSStephen Warren * 11761f5ddcbSStephen Warren * @power_domain: A power domain struct that was previously successfully 11861f5ddcbSStephen Warren * requested by power_domain_get(). 11961f5ddcbSStephen Warren * @return 0 if OK, or a negative error code. 12061f5ddcbSStephen Warren */ 12161f5ddcbSStephen Warren int power_domain_free(struct power_domain *power_domain); 12261f5ddcbSStephen Warren 12361f5ddcbSStephen Warren /** 12461f5ddcbSStephen Warren * power_domain_on - Enable power to a power domain. 12561f5ddcbSStephen Warren * 12661f5ddcbSStephen Warren * @power_domain: A power domain struct that was previously successfully 12761f5ddcbSStephen Warren * requested by power_domain_get(). 12861f5ddcbSStephen Warren * @return 0 if OK, or a negative error code. 12961f5ddcbSStephen Warren */ 13061f5ddcbSStephen Warren int power_domain_on(struct power_domain *power_domain); 13161f5ddcbSStephen Warren 13261f5ddcbSStephen Warren /** 13361f5ddcbSStephen Warren * power_domain_off - Disable power ot a power domain. 13461f5ddcbSStephen Warren * 13561f5ddcbSStephen Warren * @power_domain: A power domain struct that was previously successfully 13661f5ddcbSStephen Warren * requested by power_domain_get(). 13761f5ddcbSStephen Warren * @return 0 if OK, or a negative error code. 13861f5ddcbSStephen Warren */ 13961f5ddcbSStephen Warren int power_domain_off(struct power_domain *power_domain); 14061f5ddcbSStephen Warren 141*f594f5d3SPeng Fan /** 142*f594f5d3SPeng Fan * dev_power_domain_on - Enable power domains for a device . 143*f594f5d3SPeng Fan * 144*f594f5d3SPeng Fan * @dev: The client device. 145*f594f5d3SPeng Fan * 146*f594f5d3SPeng Fan * @return 0 if OK, or a negative error code. 147*f594f5d3SPeng Fan */ 148*f594f5d3SPeng Fan #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ 149*f594f5d3SPeng Fan CONFIG_IS_ENABLED(POWER_DOMAIN) 150*f594f5d3SPeng Fan int dev_power_domain_on(struct udevice *dev); 151*f594f5d3SPeng Fan #else 152*f594f5d3SPeng Fan static inline int dev_power_domain_on(struct udevice *dev) 153*f594f5d3SPeng Fan { 154*f594f5d3SPeng Fan return 0; 155*f594f5d3SPeng Fan } 156*f594f5d3SPeng Fan #endif 157*f594f5d3SPeng Fan 15861f5ddcbSStephen Warren #endif 159