blob: 71fc2e8ef6a08321497e910f2fbc4918342b1718 [file] [view] [edit]
# 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][spmi.fidl].
### 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:
```none {:.devsite-disable-click-to-copy}
#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][spmi.fidl],
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:
```none {:.devsite-disable-click-to-copy}
#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:
```none {:.devsite-disable-click-to-copy}
#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][spmi.fidl], 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][spmi.fidl] 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][spmi-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.fidl] 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][spmi.fidl] 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][spmi.fidl] 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
- [SPMI bind rules][spmi.bind]
- [SPMI devicetree visitor][spmi-visitor]
- [SPMI FIDL protocol][spmi.fidl]
- [SPMI metadata][metadata.fidl]
<!-- Reference links -->
[board-driver]: /docs/glossary/README.md#board-driver
[composite-node-spec]: /docs/glossary/README.md#composite-node-specification
[metadata.fidl]: /sdk/fidl/fuchsia.hardware.spmi/metadata.fidl
[spmi.bind]: /src/devices/bind/fuchsia.spmi/fuchsia.spmi.bind
[spmi.fidl]: /sdk/fidl/fuchsia.hardware.spmi/spmi.fidl
[spmi.yaml]: /sdk/lib/driver/devicetree/visitors/drivers/spmi-controllers/spmi/spmi.yaml
[spmi-visitor]: /sdk/lib/driver/devicetree/visitors/drivers/spmi-controllers/spmi