Concepts
System Power Management Interface, or SPMI, is a bus on which up to four controller devices can communicate with up to sixteen target devices to accomplish different power management tasks. Each controller and target device has an address space of up to 16 bits made up of 8-bit registers, the functions of which are defined by the hardware vendor.
While not part of the SPMI specification, some target devices that have multiple functions can be further divided into sub-target devices, which have a limited view into the target's address space. Having a logical separation of device functions allows the software drivers for them to be separate as well.
Writing an SPMI client driver
Using SPMI from a client driver depends on whether the device you intend to use is a target or a sub-target. In either case, the FIDL protocol to use is fuchsia.hardware.spmi.Device.
Target device
First update the board driver so that the SPMI controller driver adds a node for your target. On devicetree platforms, this would involve adding a new node such as:
#include "sdk/lib/driver/devicetree/visitors/drivers/spmi-controllers/spmi/spmi.h"
spmi@0xffff0000 {
/* The new node is below */
$TARGET_DEVICE_TYPE@$TARGET_ID {
reg = <$TARGET_ID SPMI_USID>;
reg-names = "$TARGET_NAME";
};
};
Your driver should connect to fuchsia.hardware.spmi.TargetService, and have an entry for it in its component manifest. The SPMI controller driver will add a node for your target with the following bind properties:
Property | Optional | Purpose |
---|---|---|
fuchsia.hardware.spmi.TargetService |
N | The SPMI target service. |
fuchsia.spmi.TARGET_ID |
N | The SPMI target ID. |
fuchsia.spmi.TARGET_NAME |
Y | A string name for the target. On devicetree platforms, this is generated from the target node's reg-names property. |
Sub-target device
First update the board driver so that the SPMI controller driver adds a node for your sub-target. On devicetree platforms, this would involve adding a new node such as:
#include "sdk/lib/driver/devicetree/visitors/drivers/spmi-controllers/spmi/spmi.h"
spmi@0xffff0000 {
$TARGET_DEVICE_TYPE@$TARGET_ID {
reg = <$TARGET_ID SPMI_USID>;
reg-names = "$TARGET_NAME";
/* Your driver's node is below */
$SUB_TARGET_DEVICE_TYPE@$SUB_TARGET_ADDRESS {
compatible = "$COMPATIBLE"
reg = <$SUB_TARGET_ADDRESS $SUB_TARGET_SIZE>;
reg-names = "$SUB_TARGET_NAME";
};
};
};
If your driver node must be the child of some other bus, you can also get access
to a sub-target with an spmis
reference property. For example:
#include "sdk/lib/driver/devicetree/visitors/drivers/spmi-controllers/spmi/spmi.h"
$BUS@0xffff1000 {
/* Your driver's node is below */
$BUS_CHILD {
compatible = "$COMPATIBLE"
spmis = <&$SUB_TARGET_LABEL>;
};
};
spmi@0xffff0000 {
$TARGET_DEVICE_TYPE@$TARGET_ID {
reg = <$TARGET_ID SPMI_USID>;
reg-names = "$TARGET_NAME";
/* This is the sub-target your driver can access */
$SUB_TARGET_LABEL: $SUB_TARGET_DEVICE_TYPE@$SUB_TARGET_ADDRESS {
reg = <$SUB_TARGET_ADDRESS $SUB_TARGET_SIZE>;
reg-names = "$SUB_TARGET_NAME";
};
};
};
Your driver should connect to fuchsia.hardware.spmi.SubTargetService, and have an entry for it in its component manifest. The SPMI controller driver will add a node for your sub-target or reference property with the following bind properties:
Property | Optional | Purpose |
---|---|---|
fuchsia.hardware.spmi.SubTargetService |
N | The SPMI sub-target service. |
fuchsia.spmi.TARGET_ID |
N | The ID of the target that contains this sub-target. |
fuchsia.spmi.TARGET_NAME |
Y | A string name for the target that contains this sub-target. On devicetree platforms, this is generated from the target node's reg-names property. |
fuchsia.spmi.SUB_TARGET_ADDRESS |
N | The starting address for this sub-target within the target. |
fuchsia.spmi.SUB_TARGET_NAME |
Y | A string name for the sub-target. On devicetree platforms, this is generated from the sub-target node's reg-names property. |
Register accesses through fuchsia.hardware.spmi.Device will be mapped to the sub-target's starting address, and limited to the range assigned to the sub-target.
Sub-target devicetree bindings
The following are prohibited by the SPMI devicetree visitor:
- Target nodes being referenced in
spmis
properties - A sub-target node having a
compatible
property and also being referenced in anspmis
property - A sub-target node being referenced by
spmis
properties in multiple other nodes
Writing an SPMI controller driver
SPMI controller drivers are responsible for setting up child nodes based on fuchsia.hardware.spmi.ControllerInfo metadata received from the board driver.
Target devices
For each TargetInfo
in ControllerInfo
that does not have sub_targets
, the
controller driver should add a child node that serves
fuchsia.hardware.spmi.TargetService and has the following
properties:
Property | Value |
---|---|
fuchsia.spmi.CONTROLLER_ID |
id in ControllerInfo (if specified) |
fuchsia.spmi.TARGET_ID |
id in TargetInfo |
fuchsia.spmi.TARGET_NAME |
name in TargetInfo (if specified) |
Sub-target devices
For each SubTargetInfo
in each TargetInfo
in ControllerInfo
, the
controller driver should add a child node that serves
fuchsia.hardware.spmi.SubTargetService and has the following
properties:
Property | Value |
---|---|
fuchsia.spmi.CONTROLLER_ID |
id in ControllerInfo (if specified) |
fuchsia.spmi.TARGET_ID |
id in TargetInfo |
fuchsia.spmi.TARGET_NAME |
name in TargetInfo (if specified) |
fuchsia.spmi.SUB_TARGET_ADDRESS |
address in SubTargetInfo |
fuchsia.spmi.SUB_TARGET_NAME |
name in SubTargetInfo (if specified) |
The controller driver should restrict register accesses to sub-targets to the
range [0, size
) and offset them by address
.