SPMI overview

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 an spmis 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.

Resources