Skip to content

Commit

Permalink
doc: boards: extensions: add Sphinx directive for board supported har…
Browse files Browse the repository at this point in the history
…dware

Introduce a new directive for displaying hardware features supported by
a board, using information available in the devicetree.

Signed-off-by: Benjamin Cabé <[email protected]>
  • Loading branch information
kartben authored and nashif committed Feb 13, 2025
1 parent e4bf463 commit dec9f86
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 12 deletions.
145 changes: 145 additions & 0 deletions doc/_extensions/zephyr/domain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
from zephyr.doxybridge import DoxygenGroupDirective
from zephyr.gh_utils import gh_link_get_url

from .binding_types import BINDING_TYPES

__version__ = "0.2.0"


Expand All @@ -67,6 +69,16 @@

logger = logging.getLogger(__name__)

BINDING_TYPE_TO_DOCUTILS_NODE = {}
for key, value in BINDING_TYPES.items():
if isinstance(value, tuple):
# For abbreviations with explanations
abbr, explanation = value
BINDING_TYPE_TO_DOCUTILS_NODE[key] = nodes.abbreviation(abbr, abbr, explanation=explanation)
else:
# For simple text
BINDING_TYPE_TO_DOCUTILS_NODE[key] = nodes.Text(value)


class CodeSampleNode(nodes.Element):
pass
Expand Down Expand Up @@ -685,6 +697,7 @@ def run(self):
board_node = BoardNode(id=board_name)
board_node["full_name"] = board["full_name"]
board_node["vendor"] = vendors.get(board["vendor"], board["vendor"])
board_node["supported_features"] = board["supported_features"]
board_node["archs"] = board["archs"]
board_node["socs"] = board["socs"]
board_node["image"] = board["image"]
Expand Down Expand Up @@ -716,6 +729,137 @@ def run(self):
return [nodes.paragraph(text="Board catalog is only available in HTML.")]


class BoardSupportedHardwareDirective(SphinxDirective):
"""A directive for showing the supported hardware features of a board."""

has_content = False
required_arguments = 0
optional_arguments = 0

def run(self):
env = self.env
docname = env.docname

matcher = NodeMatcher(BoardNode)
board_nodes = list(self.state.document.traverse(matcher))
if not board_nodes:
logger.warning(
"board-supported-hw directive must be used in a board documentation page.",
location=(docname, self.lineno),
)
return []

board_node = board_nodes[0]
supported_features = board_node["supported_features"]
result_nodes = []

paragraph = nodes.paragraph()
paragraph += nodes.Text("The ")
paragraph += nodes.literal(text=board_node["id"])
paragraph += nodes.Text(" board supports the hardware features listed below.")
result_nodes.append(paragraph)

if not env.app.config.zephyr_generate_hw_features:
note = nodes.admonition()
note += nodes.title(text="Note")
note["classes"].append("warning")
note += nodes.paragraph(
text="The list of supported hardware features was not generated. Run a full "
"documentation build for the required metadata to be available."
)
result_nodes.append(note)
return result_nodes

# Add the note before any tables
note = nodes.admonition()
note += nodes.title(text="Note")
note["classes"].append("note")
note += nodes.paragraph(
text="The tables below were automatically generated using information from the "
"Devicetree. They may not be fully representative of all the hardware features "
"supported by the board."
)
result_nodes.append(note)

for target, features in sorted(supported_features.items()):
if not features:
continue

target_heading = nodes.section(ids=[f"{board_node['id']}-{target}-hw-features"])
heading = nodes.title()
heading += nodes.literal(text=target)
heading += nodes.Text(" target")
target_heading += heading
result_nodes.append(target_heading)

table = nodes.table(classes=["colwidths-given"])
tgroup = nodes.tgroup(cols=3)

tgroup += nodes.colspec(colwidth=20, classes=["col-1"])
tgroup += nodes.colspec(colwidth=50)
tgroup += nodes.colspec(colwidth=30)

thead = nodes.thead()
row = nodes.row()
headers = ["Type", "Description", "Compatible"]
for header in headers:
row += nodes.entry("", nodes.paragraph(text=header))
thead += row
tgroup += thead

tbody = nodes.tbody()

def feature_sort_key(feature):
# Put "CPU" first. Later updates might also give priority to features
# like "sensor"s, for example.
if feature == "cpu":
return (0, feature)
return (1, feature)

sorted_features = sorted(features.keys(), key=feature_sort_key)

for feature in sorted_features:
items = list(features[feature].items())
num_items = len(items)

for i, (key, value) in enumerate(items):
row = nodes.row()

# Add type column only for first row of a feature
if i == 0:
type_entry = nodes.entry(morerows=num_items - 1)
type_entry += nodes.paragraph(
"",
"",
BINDING_TYPE_TO_DOCUTILS_NODE.get(
feature, nodes.Text(feature)
).deepcopy(),
)
row += type_entry

row += nodes.entry("", nodes.paragraph(text=value))

# Create compatible xref
xref = addnodes.pending_xref(
"",
refdomain="std",
reftype="dtcompatible",
reftarget=key,
refexplicit=False,
refwarn=True,
)
xref += nodes.literal(text=key)
row += nodes.entry("", nodes.paragraph("", "", xref))

tbody += row

tgroup += tbody
table += tgroup
result_nodes.append(table)

return result_nodes


class ZephyrDomain(Domain):
"""Zephyr domain"""

Expand All @@ -734,6 +878,7 @@ class ZephyrDomain(Domain):
"code-sample-category": CodeSampleCategoryDirective,
"board-catalog": BoardCatalogDirective,
"board": BoardDirective,
"board-supported-hw": BoardSupportedHardwareDirective,
}

object_types: dict[str, ObjType] = {
Expand Down
135 changes: 135 additions & 0 deletions doc/_extensions/zephyr/domain/binding_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""
SPDX-FileCopyrightText: Copyright (c) 2025 The Linux Foundation
SPDX-License-Identifier: Apache-2.0
This module contains the mapping of binding types to their human-readable names and descriptions.
Each entry can be either:
- A string representing the human-readable name
- A tuple of (abbreviation, full name) for cases where an abbreviation exists
"""

BINDING_TYPES = {
# zephyr-keep-sorted-start re(^ ")
"acpi": ("ACPI", "Advanced Configuration and Power Interface"),
"adc": ("ADC", "Analog to Digital Converter"),
"alh": ("ALH", "Audio Link Hub"),
"arc": "ARC architecture",
"arm": "ARM architecture",
"audio": "Audio",
"auxdisplay": "Auxiliary Display",
"base": "Base",
"battery": "Battery",
"bluetooth": "Bluetooth",
"cache": "Cache",
"can": ("CAN", "Controller Area Network"),
"charger": "Charger",
"clock": "Clock control",
"coredump": "Core dump",
"counter": "Counter",
"cpu": "CPU",
"crypto": "Cryptographic accelerator",
"dac": ("DAC", "Digital to Analog Converter"),
"dai": ("DAI", "Digital Audio Interface"),
"debug": "Debug",
"dfpmcch": "DFPMCCH",
"dfpmccu": "DFPMCCU",
"disk": "Disk",
"display": "Display",
"display/panel": "Display panel",
"dma": ("DMA", "Direct Memory Access"),
"dsa": ("DSA", "Distributed Switch Architecture"),
"edac": ("EDAC", "Error Detection and Correction"),
"espi": ("eSPI", "Enhanced Serial Peripheral Interface"),
"ethernet": "Ethernet",
"firmware": "Firmware",
"flash_controller": "Flash controller",
"fpga": ("FPGA", "Field Programmable Gate Array"),
"fs": "File system",
"fuel-gauge": "Fuel gauge",
"gnss": ("GNSS", "Global Navigation Satellite System"),
"gpio": ("GPIO", "General Purpose Input/Output"),
"haptics": "Haptics",
"hda": ("HDA", "High Definition Audio"),
"hdlc_rcp_if": "IEEE 802.15.4 HDLC RCP interface",
"hwinfo": "Hardware information",
"hwspinlock": "Hardware spinlock",
"i2c": ("I2C", "Inter-Integrated Circuit"),
"i2s": ("I2S", "Inter-IC Sound"),
"i3c": ("I3C", "Improved Inter-Integrated Circuit"),
"ieee802154": "IEEE 802.15.4",
"iio": ("IIO", "Industrial I/O"),
"input": "Input",
"interrupt-controller": "Interrupt controller",
"ipc": ("IPC", "Inter-Processor Communication"),
"ipm": ("IPM", "Inter-Processor Mailbox"),
"kscan": "Keyscan",
"led": ("LED", "Light Emitting Diode"),
"led_strip": ("LED", "Light Emitting Diode"),
"lora": "LoRa",
"mbox": "Mailbox",
"mdio": ("MDIO", "Management Data Input/Output"),
"memory-controllers": "Memory controller",
"memory-window": "Memory window",
"mfd": ("MFD", "Multi-Function Device"),
"mhu": ("MHU", "Mailbox Handling Unit"),
"mipi-dbi": ("MIPI DBI", "Mobile Industry Processor Interface Display Bus Interface"),
"mipi-dsi": ("MIPI DSI", "Mobile Industry Processor Interface Display Serial Interface"),
"misc": "Miscellaneous",
"mm": "Memory management",
"mmc": ("MMC", "MultiMediaCard"),
"mmu_mpu": ("MMU / MPU", "Memory Management Unit / Memory Protection Unit"),
"modem": "Modem",
"mspi": "Multi-bit SPI",
"mtd": ("MTD", "Memory Technology Device"),
"net": "Networking",
"options": "Options",
"ospi": "Octal SPI",
"pcie": ("PCIe", "Peripheral Component Interconnect Express"),
"peci": ("PECI", "Platform Environment Control Interface"),
"phy": "PHY",
"pinctrl": "Pin control",
"pm_cpu_ops": "Power management CPU operations",
"power": "Power management",
"power-domain": "Power domain",
"ppc": "PPC architecture",
"ps2": ("PS/2", "Personal System/2"),
"pwm": ("PWM", "Pulse Width Modulation"),
"qspi": "Quad SPI",
"regulator": "Regulator",
"reserved-memory": "Reserved memory",
"reset": "Reset controller",
"retained_mem": "Retained memory",
"retention": "Retention",
"riscv": "RISC-V architecture",
"rng": ("RNG", "Random Number Generator"),
"rtc": ("RTC", "Real Time Clock"),
"sd": "SD",
"sdhc": "SDHC",
"sensor": "Sensors",
"serial": "Serial controller",
"shi": ("SHI", "Secure Hardware Interface"),
"sip_svc": ("SIP", "Service in Platform"),
"smbus": ("SMBus", "System Management Bus"),
"sound": "Sound",
"spi": ("SPI", "Serial Peripheral Interface"),
"sram": "SRAM",
"stepper": "Stepper",
"syscon": "System controller",
"tach": "Tachometer",
"tcpc": ("TCPC", "USB Type-C Port Controller"),
"test": "Test",
"timer": "Timer",
"timestamp": "Timestamp",
"uac2": "USB Audio Class 2",
"usb": "USB",
"usb-c": "USB Type-C",
"video": "Video",
"virtualization": "Virtualization",
"w1": "1-Wire",
"watchdog": "Watchdog",
"wifi": "Wi-Fi",
"wireless": "Wireless network",
"xen": "Xen",
"xspi": ("XSPI", "Expanded Serial Peripheral Interface"),
# zephyr-keep-sorted-stop
}
12 changes: 11 additions & 1 deletion doc/_extensions/zephyr/domain/templates/board-card.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@
data-arch="{{ board.archs | join(" ") }}"
data-vendor="{{ board.vendor }}"
data-socs="{{ board.socs | join(" ") }}"
data-supported-features="{{ board.supported_features | join(" ") }}" tabindex="0">
data-supported-features="
{%- set feature_types = [] -%}
{%- for target_features in board.supported_features.values() -%}
{%- for feature_type in target_features.keys() -%}
{%- if feature_type not in feature_types -%}
{%- set _ = feature_types.append(feature_type) -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{{- feature_types|join(' ') -}}
" tabindex="0">
<div class="vendor">{{ vendors[board.vendor] }}</div>
{% if board.image -%}
<img alt="A picture of the {{ board.full_name }} board"
Expand Down
Loading

0 comments on commit dec9f86

Please sign in to comment.