diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-B1CE51BC-B452-5FC9-9C00-35447AF40671.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,357 @@ + + + + + + Implement +the controllable power resourcesThis document describes how to write and use power resources. +
Purpose

Implement your power resource according +to the type of resource you wish to support.

Introduction

Power +resources controlled by the PRM can be turned on, off and varied with software.

See +the Power +resources section for detailed information about resources. There are +five main types of resource that can be implemented:

    +
  • static resources - derived +from the DStaticPowerResource base class,

  • +
  • static resource that +support dependancy - derived from the DStaticpowerResourceD base +class,

  • +
  • dynamic resources - +derived from the DDynamicPowerResource base class. Create +dynamic resources in the kernel data section or in the heap,

  • +
  • dynamic resource that +support dependancy - derived from the DDynamicPowerResourceD.

  • +
  • custom sense resources +- when shared the power level of this resource may be increased or decreased +freely by some privileged clients but not by others, which are bound by the +requirement of the privileged clients.

  • +

Note: dynamic resources and resource dependancies are only +supported in the extended version of the PRM. See setup and configuration requirements.

+
Implementing power resources

The following tasks +are covered in this tutorial:

    +
  • Create your resource by

    Override +the pure virtual functions,

  • +
  • Create resource dependencies,

  • +
  • Create custom resources.

  • +

Override the pure +virtual functions

The pure virtual functions of DStaticPowerResource or DDynamicPowerResource must +be implemented.

Constructor

Information about the resource +based on the resources category must be set in the iFlags bit +mask. Static variables that define a resources classification can be found +within 32\include\drivers\resource.h.

Each resource +is classified based on:

    +
  • usage,

  • +
  • operating levels,

  • +
  • latency,

  • +
  • resource sense.

  • +

Below is the example implementation of derived class constructor

// multilevel, shared, long latency, read and write, positive resource. +DMLSHLGLSPResource::DMLSHLGLSPResource() : DStaticPowerResource(KDBSHLGLSPResource, E_ON), + iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(ETrue) + { + iFlags = EMultilevel | KShared | KLongLatencySet | KLongLatencyGet; + . . . + }

GetInfo()

The PIL uses GetInfo() to +get resource information. The default implementation of this function provides +generic information about the resource by updating the passed descriptor that +contains an information structure TPowerResourceInfoV01. +Derived implementations must fill in all the PSL specific fields and call +the base class implementation. Below is an example implementation.

TInt DH4SndFclkResource::GetInfo(TDes8* info) const + { + __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DH4SndFclkResource::GetInfo\n")); + + /** Call base class implementation to fill generic details */ + DStaticPowerResource::GetInfo((TDes8*) info); + TPowerResourceInfoV01 *buf1 = (TPowerResourceInfoV01*) info; + buf1->iMinLevel = iMinLevel; + buf1->iMaxLevel = iMaxLevel; + __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DH4SndFclkResource::GetInfo\n")); + return KErrNone; + }

The member variables of the TPowerResourceInfoV01 structure +are reserved for PSL information. These can be used to return resource specific +information to clients.

DoRequest()

DoRequest() is +used by the PIL to control resources. For example, to change and read the +state of resources. DoRequest() takes a TPowerRequest object +that contains all the request information. Note: This function needs +to be implemented for all resources.

Below is an example DoRequest() function +implementation for a binary, instantaneous resource.

TInt DH4MmcCtrllerPwrResource::DoRequest(TPowerRequest& aRequest) + { + TInt retVal = KErrNone; + TUint16 config; + /** Enable/disable the MMC controller by programming the MMC controller 'CON' register- 'POW' bit */ + if (aRequest.ReqType()==TPowerRequest::EGet) + { + PRM_PSL_RESOURCE_GET_STATE_START_TRACE + config = OMAPMMC_GET_REG(KHoMMC_Con_Reg); + if(config & KHtMMC_PowerUp) + { + aRequest.Level() = 1; + iCurLevel = 1; + } + else + { + aRequest.Level() = 0; + iCurLevel = 0; + } + PRM_PSL_RESOURCE_GET_STATE_END_TRACE + } + else if(aRequest.ReqType()==TPowerRequest::ESetDefaultLevel) + { + PRM_PSL_RESOURCE_CHANGE_STATE_START_TRACE + OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KHtMMC_PowerUp, KClear32); + iCurLevel = iDefaultLevel; + aRequest.Level() = iDefaultLevel; + PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE + } + else + { + PRM_PSL_RESOURCE_CHANGE_STATE_START_TRACE + if(aRequest.Level() == 1) + { + OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KClear32, KHtMMC_PowerUp); + } + else + { + OMAPMMC_MOD_REG(KHoMMC_Con_Reg, KHtMMC_PowerUp, KClear32); + } + iCurLevel = aRequest.Level(); + PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE + } + return retVal; + }

The DoRequest function implementation should take care +of blocking the Resource Controller thread as operations on a long latency +resource take a significant amount of time to complete (in hardware). Usually +the request completion is notified either through an ISR (interrupt driven) +or through register setting (polling wait) by hardware.

Below is an +example DoRequest() implementation for a long latency resource.

TInt DH4MmcPowerResource::DoRequest(TPowerRequest& aRequest) + { + TUint8 iMenelausConf; + TInt retVal = KErrNone; + + /** Access to Menelaus registers is over I2C bus. This is a long latency synchronous operation. + Create a Menelaus Request structure and send it to Menelaus chip, Wait until a response is received */ + + if (aRequest.ReqType()==TPowerRequest::EGet) + { + // Frame the request + ... + } + // Default level is off. + else if (aRequest.ReqType() == TPowerRequest::ESetDefaultLevel) + { + // Frame request to move the resource to default state + ... + } + // EChange + else + { + // Frame request to set the requested resource state + ... + } + + // Request the operation on the hardware + retVal = Menelaus::AccessRegister(iMenelausReq); + + // Wait for the request to complete + __KTRACE_OPT(KPBUS1, Kern::Printf("Waiting for menelaus req to signal sem\n")); + NKern::FSSetOwner(&iSemaphore,NULL); + iSemaphore.iCount = 0; + + // This will be signalled in Menelaus access functions callback below + NKern::FSWait(&(iSemaphore)); + + // Menelaus chip has responded + if(iMenelausAccessErr == KErrNone) + { + switch(iMenelausState) + { + case EMenelausRead: + // Return 0/1 depending on the value set + iMenelausConf = (*(iRdBuffer.Ptr())) & KHoMenelausVmmcModeMask; + if(iMenelausConf == 3) + { + iCurLevel=aRequest.Level()=1; + } + else + { + iCurLevel=aRequest.Level()=0; + } + PRM_PSL_RESOURCE_GET_STATE_END_TRACE + break; + + case EMenelausSingleWrite: + iCurLevel = aRequest.Level(); + PRM_PSL_RESOURCE_CHANGE_STATE_END_TRACE + break; + } + } + return iMenelausAccessErr; + } + +/** Below is the Menelaus access functions callback where the semaphore is signalled. */ +void DH4MmcPowerResource::MenelausAccessDone(TAny* aPtr, TInt aResult) + { + DH4MmcPowerResource* ptr = reinterpret_cast<DH4MmcPowerResource*>(aPtr); + ptr->iMenelausAccessErr = aResult; + if(aResult != KErrNone) + { + __KTRACE_OPT(KRESMANAGER, + Kern::Printf("Menelaus::MenelausAccessRegister ERR(%d)\n", aResult)); + } + // Signal the waiting thread + NKern::FSSignal(&(ptr->iSemaphore)); + return; + }

Create +resource dependencies

A resource has a dependency if the state +of the resource depends on the state of one or more resources. For example, +a clock whose frequency is derived from another clock or voltage is a dependent +resource. The PSL usually handles resource dependencies transparently. However, +if the resources have public users (clients of the PRM), then these resources +should be registered with the PRM as Resource +dependencies that are linked.

Each dependency must be assigned +a priority value. The priority is used by the PIL when propagating the change +and propagating the request for notifications. Each link stemming from a resource +must have a unique priority value.

Note: Resource dependencies +are only supported in the extended version of the PRM. Only long latency resources +are allowed to have dependents and no closed loop dependencies are allowed.

Register +resource dependencies for dynamic and static resources

Static +resources that support dependencies are created and registered with the PRM +during resource controller creation time and are derived from DStaticPowerResourceD:

DXXXStaticPowerResourceD : public DStaticPowerResourceD + { +public: + DXXXStaticPowerResourceD(); + TInt DoRequest(TPowerRequest &req); + TInt GetInfo(TDes8* aInfo) const; + TChangePropagationStatus TranslateDependentState(TInt aDepId, TInt aDepState, TInt& aResState); +private: + TInt iMinLevel; + TInt iMaxLevel; + TInt iCurrentLevel; + ... + };

Dependencies between static resources should be established +by the PSL before registering these resources with the PIL. Use the DStaticPowerResourceD::AddNode() function +provided in the base class to establish a dependency link between static resources. +See Creating +dependencies between static resources.

Dynamic resources that +support dependency are derived from DDynamicPowerResourceD. +These can be registered and deregistered from the PRM at any time after the +PRM is fully initialised. Dependencies between resources are established by +the client using PowerResourceManager::RegisterResourceDependency().

DXXXDynamicPowerResourceD : public DDynamicPowerResourceD + { +public: + DXXXDynamicPowerResourceD(); + TInt DoRequest(TPowerRequest &req); + TInt GetInfo(TDes8* aInfo) const; + TChangePropagationStatus TranslateDependentState(TInt aDepId, TInt aDepState, TInt& aResState); +private: + TInt iMinLevel; + TInt iMaxLevel; + TInt iCurrentLevel; + ... + };

Dependencies can be established between a dynamic resource +and a static (dependency enabled) resource using the same API. A client can +deregister dependencies between a pair of dynamic resource (or between a dynamic +and static resource) using PowerResourceManager::DeRegisterResourceDependency(). +When a dynamic resource that supports dependency deregisters from the PRM, +dependencies are removed automatically by the PIL.

Change the state +of dependent resources

When a state change is requested by a client +on any resource in a dependency tree before proceeding with the change the +PIL must check if the change is allowed by its dependents and the ones it +depends on. The PIL does this by calling the TranslateDependentState() function +on each resource. This is a pure virtual function in the base class and must +be implemented in the derived class.

This function is called by the +PIL prior to a resource change on any of its dependents. The function returns +one of these values:

    +
  • EChange - +If the resource accepts the state change of the dependent resource and, as +a result of the dependent resources state change this resource needs to change +its own state. The new state of this resource is updated in aResState,

  • +
  • ENoChange - +if the resource accepts the dependent resources state change and this resource +does not need to change its state,

  • +
  • ENotAllowed - +if the resource does not accept the dependent resources state change.

  • +
TChangePropagationStatus DXXDependResource::TranslateDependentState(TInt /*aDepId*/, TInt aDepState, + TInt& aResState) + { + /* Switch ON if the dependent resource is ON */ + if((aDepState == 1) && (iCurrentLevel == 0) + { + aResState = iMaxLevel; + return EChange; + } + + /* Don’t allow dependent to OFF, if this is still ON */ + else if (aDepState == 0) && (iCurrentLevel == 1) + { + return ENotAllowed; + } + + return ENoChange; + }

Create +custom resources

Clients on a shared resource may have different +requirements on the state of a shared resource. The resource sense is used +by the PIL to determine whose requirement prevails:

    +
  • positive sense resources +- when shared can have their value increased without prejudice to their clients,

  • +
  • negative sense resources +- when shared can have their value decreased without prejudice to their clients,

  • +
  • custom sense resources +- when shared may be increased or decreased freely by some privileged clients +but not by others, which are bound by the requirement of the privileged clients.

  • +

A custom function must be supplied for every Power resources resource. This function is called by the PIL every +time a change request is issued to determine if the change requested by the +client is allowed as a decision to allow the resource change is determined +solely by the PSL. The resource object contains a pointer that must be set +at construction for custom sense resources by calling this function:

inline void SetCustomFunction(TCustomFunction aCustomFunction)

This +function sets the custom function for the resource. If a custom function is +not supplied for a custom sense resource the PIL panics during a resource +state change. An example of a custom sense resource is a shared domain clock +when a domain client uses it as a bit clock.

TCustomFunction is +a function pointer:

typedef TBool (*TCustomFunction) (TInt& /*aClientId*/, + TUint /*aResourceId*/, + TInt& /*aLevel*/, + TAny* /*aLevelList*/);

The +values held in TCustomFunction are:

    +
  • the Id of the client +requesting the change,

  • +
  • the Id of the resource +on which the change is requested (this allows a single function to handle +multiple resources),

  • +
  • the level the client +is requesting,

  • +
  • a pointer to the list +of the resource’s client +levels.

  • +

Custom functions can be set at any time before a resource state change +is requested on a resource. Ideally a custom function is set at resource creation +time in the resource's constructor.

DBSHLGLSCResource::DBSHLGLSCResource() : DStaticPowerResource(KDBSHLGLSCResource, E_ON), iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(EFalse) + { + iFlags = KMultiLevel | KShared | KLongLatencySet | KSenseCustom; + SetCustomFunction(CustomFunction); + ... + }

The decision to allow the requested resource state change +is specified in the custom function return value. This is ETrue if +the change is allowed and EFalse if the change is not allowed.

The +function can change the state of the resource to a level other than the one +requested and can choose a client other than the passed client to hold the Caching +the prevailing level of the resource.

Supporting dependencies

If +the custom sense resource supports dependencies then use the function pointer TDependencyCustomFunction. +This takes an additional parameter that specifies the resource Client level objects.

+
+Porting the +Power Resource Manager +Implement +the PSL for the target +Port the +client drivers to use the PRM +Debugging +the PRM +Testing the +PRM PSL +
\ No newline at end of file