Board Configuration

The board configuration is the most important part of the board-tailoring, and it works as a data structure containing all the tailoring data which can be supplied by the customers of Microchip (here customer is the one designing a board - not the end user).

The board configuration itself is guarded by a YANG schema file which describes all the fields which can be configured and encoded as CBOR as defined by RFC9254.

The board.yang is different from all the other YANG modules in the system as it is not exposed over CORECONF, and completely invisible to the end-user. The board-yang data belong to the firmware image and are signed along with that image, and therefore being considered as part of the firmware.

CBOR is a compact and machine-friendly encoding, but not very human-friendly, and for this reason, the actual board configurations are written in YAML format, and then converted to CBOR. The build system takes care of doing that.

When reading this material, one should have the board.tree and board.yang files open, and reference them.

The high-level structure of the board.tree looks like this:

module: board
  +--rw drivers                   <container>
  |  ...
  +--rw capabilities              <container>
  |  ...
  +--rw factory_default_config?   <anydata>
  |  ...
  +--rw extmod                    <container>
  |  ...

A basic and empty board configuration YAML template can look like this:

board:drivers:
board:capabilities:
board:factory_default_config:

The following section will go into detail with each of the major sections

1. Drivers

1.1. SGPIO Banks

SGPIOs (Serial GPIOs) are used for communication with devices on the board such as SFP modules and LEDs. Up to 32 SGPIO ports can be enabled, with each port consisting of 1-4 bits. This configuration results in a serial data stream comprising 'ports * bits' number of GPIOs. The definition looks like this:

module: board
  +--rw drivers
     +--rw sgpio_banks
        +--rw sgpio_bank* [sgpio_bank]
           +--rw sgpio_bank    dev_sgpio_bank
           +--rw bit_count     uint32
           +--rw port_mask     uint32
           +--rw clock_div?    uint32
           +--rw pin_ctrl
              +--rw pins*           uint32
              +--rw pin_function    pin_function
  • sgpio_bank is used to select which physical instance in hardware to configure; typically, 1-3 instances are available.

  • bit_count is the number of GPIOs (or bits) that are enabled per SGPIO port, with 1-4 bits available.

  • port_mask defines the SGPIO ports that get enabled. Some signals (e.g., SFP LOS) are mapped directly to the chip device with the same number as the SGPIO port in this mask.

  • clock_div maps directly into the hardware where the SGPIO frequency is set. The resulting frequency is the system clock divided by this value.

  • pin_ctrl is used to assign physical pins on the SoC to this function. Check the datasheet for an overview of which pins can be used.

Example with SGPIO ports 0,1,24,25,26,27 enabled, with 4 bits per port:

  sgpio_banks:
    sgpio_bank:
      - sgpio_bank: DEV_SGPIO_BANK_0
        bit_count: 4
        port_mask: 0x0F000003
        clock_div: 65
        pin_ctrl:
          pins: [5, 6, 7, 8]
          pin_function: alt1

1.2. FlexCom

FlexCOM is a SoC HW component capable of providing a UART, I2C, or SPI interface. The definition of the FlexCOM in the board.tree looks like this:

  +--rw drivers
     +--rw flexcoms
        +--rw flexcom* [hw_instance]
           +--rw hw_instance    uint32
           +--rw uart?          dev_uart
           +--rw i2c?           dev_i2c
           +--rw spi?           dev_spi
           +--rw pin_ctrl
              +--rw pins*           uint32
              +--rw pin_function    pin_function

Here:

  • hw_instance is used to select which physical instance in HW to configure. Typically a SoC supports 2-5 instances, and each instance can only be configured to work with a fixed pool of pins. It is therefore important to configure the correct instance (according to the schematic).

  • uart, i2c, and spi are used to select the personality of the FlexCOM instance. Any given flexcom entry must include one and only one of them. The DEV_xxx value assigned to either uart, i2c, or spi is an internal handle, used further down in the file to reference the FlexCOM instance.

  • pin_ctrl is used to assign physical pins on the SoC to this function. Check the datasheet for an overview of what pins can be used.

Following is an example where FlexCom-0 is configured as UART, and FlexCOM-3 is configured as an I2C controller:

board:drivers:
  flexcoms:
    flexcom:
      - hw_instance: 0
        uart: DEV_UART_0
        pin_ctrl:
          pins: [3, 4]
          pin_function: alt1
      - hw_instance: 3
        i2c: DEV_I2C_0
        pin_ctrl:
          pins: [55, 56]
          pin_function: alt2

See also: MUP1 and I2C Mux.

1.3. Pin Group

Pin group is used to configure and manage the multiplexing of pins to allow multiple devices to share the same physical pins. The pins can be either GPIOs or SGPIOs. The typical usage is to control a mux to I2C devices. The definition looks like this:

module: board
  +--rw drivers
     +--rw pin_groups
        +--rw pin_group* [pin_group]
           +--rw pin_group    dev_pin_group
           +--rw sleep        uint32
           +--ro mux_pins* []
              +--ro (ref)
              |  +--:(sgpio)
              |  |  +--ro sgpio
              |  |     +--ro ref_sgpio_bank    dev_sgpio_bank
              |  |     +--ro port              uint8
              |  |     +--ro bit               uint8
              |  +--:(gpio)
              |     +--ro gpio?     uint32
              +--ro direction       gpio_direction
              +--ro active_state?   active
  • pin_group is the internal handle for others to reference when choosing a pin group.

  • sleep is the time it takes to change the mux, i.e., the driver waits this number of ms before returning and the mux is formed.

  • sgpio defines a reference to an SGPIO bank and which port/bit are used to form the group.

  • gpio has the same purpose as sgpio, just for GPIOs.

Example of a pin group formed by 3 SGPIO pins, wich can contol mux with up to 8 outputs:

  pin_groups:
    pin_group:
      - pin_group: DEV_PIN_GROUP_0
        sleep: 10
        mux_pins:
          - sgpio:
              ref_sgpio_bank: DEV_SGPIO_BANK_0
              port: 0
              bit: 1
            direction: GPIO_DIR_OUT
          - sgpio:
              ref_sgpio_bank: DEV_SGPIO_BANK_0
              port: 0
              bit: 2
            direction: GPIO_DIR_OUT
          - sgpio:
              ref_sgpio_bank: DEV_SGPIO_BANK_0
              port: 0
              bit: 3
            direction: GPIO_DIR_OUT

1.4. I2C Mux

I2C Mux is used to control a number of I2C devices (which share the same I2C bus) by enabling only one of them at a time and keeping the others disabled. Users will reference the MUX based on how it should be configured with 'DEV_MUX_x'. The definition looks like this:

module: board
  +--rw drivers
     +--rw i2c_muxs
        +--rw i2c_mux* [i2c_mux]
           +--rw i2c_mux          dev_i2c_mux
           +--rw ref_parent       dev_i2c
           +--rw ref_pin_group    dev_pin_group
           +--rw gpio_mask        uint32
  • i2c_mux is the internal handle for others to reference when choosing an I2C mux with a specific mux configuration.

  • ref_parent is a reference to an already defined HW I2C instance.

  • ref_pin_group is a reference to an already defined pin controller.

  • gpio_mask defines how this instance will configure the mux.

Example of an I2C MUX which uses the pin group and the I2C instance above and sets the MUX to positions 0-3.

  i2c_muxs:
    i2c_mux:
      - i2c_mux: DEV_MUX_0
        ref_parent: DEV_I2C_0
        ref_pin_group: DEV_PIN_GROUP_0
        gpio_mask: 0
      - i2c_mux: DEV_MUX_1
        ref_parent: DEV_I2C_0
        ref_pin_group: DEV_PIN_GROUP_0
        gpio_mask: 1
      - i2c_mux: DEV_MUX_2
        ref_parent: DEV_I2C_0
        ref_pin_group: DEV_PIN_GROUP_0
        gpio_mask: 2
      - i2c_mux: DEV_MUX_3
        ref_parent: DEV_I2C_0
        ref_pin_group: DEV_PIN_GROUP_0
        gpio_mask: 3

1.5. SFP

The SFP signals that are defined consist of the following: LOS (input), TX_FAULT (input), PRESENT (input), and TX_ENABLE (output). When inserted, 'PRESENT' goes high and the ROM is read via I2C to determine the type and thereby how to configure the switch port to match its capabilities. The definition looks like this:

module: board
  +--rw drivers
     +--rw sfps
        +--rw sfp* [portno]
           +--rw los
           |  +--rw (ref)
           |  |  +--:(sgpio)
           |  |  |  +--rw sgpio
           |  |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
           |  |  |     +--rw port              uint8
           |  |  |     +--rw bit               uint8
           |  |  +--:(gpio)
           |  |     +--rw gpio?     uint32
           |  +--rw direction       gpio_direction
           |  +--rw active_state?   active
           +--rw tx_fault
           |  +--rw (ref)
           |  |  +--:(sgpio)
           |  |  |  +--rw sgpio
           |  |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
           |  |  |     +--rw port              uint8
           |  |  |     +--rw bit               uint8
           |  |  +--:(gpio)
           |  |     +--rw gpio?     uint32
           |  +--rw direction       gpio_direction
           |  +--rw active_state?   active
           +--rw present
           |  +--rw (ref)
           |  |  +--:(sgpio)
           |  |  |  +--rw sgpio
           |  |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
           |  |  |     +--rw port              uint8
           |  |  |     +--rw bit               uint8
           |  |  +--:(gpio)
           |  |     +--rw gpio?     uint32
           |  +--rw direction       gpio_direction
           |  +--rw active_state?   active
           +--rw tx_enable
           |  +--rw (ref)
           |  |  +--:(sgpio)
           |  |  |  +--rw sgpio
           |  |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
           |  |  |     +--rw port              uint8
           |  |  |     +--rw bit               uint8
           |  |  +--:(gpio)
           |  |     +--rw gpio?     uint32
           |  +--rw direction       gpio_direction
           |  +--rw active_state?   active
           +--rw portno         uint32
           +--rw ref_i2c_mux?   dev_i2c_mux
  • portno defines to which switch front port (zero-based) this SFP belongs.

  • los indicates a loss of the received optical signal.

  • present indicates that a module is present.

  • tx_enable signal is used to enable the transmitter output.

  • tx_fault indicates faults in the Tx direction.

  • direction can be either input or output (output for tx_enable, input for others).

  • active_state defines the signal’s active state. This is usually documented in schematics.

  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID.

  • ref_i2c_mux is a reference to an already defined I2C mux, which enables this SFP I2C.

Example of a single SFP implementation:

  sfps:
    sfp:
      - portno: 24
        ref_i2c_mux: DEV_MUX_0
        los:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 0
          direction: GPIO_DIR_IN
          active_state: high
        tx_fault:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 2
          direction: GPIO_DIR_IN
          active_state: high
        present:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 1
          direction: GPIO_DIR_IN
          active_state: low
        tx_enable:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 2
          direction: GPIO_DIR_OUT
          active_state: low

1.6. MDIO

The MDIO (Management Data Input/Output) is a serial bus protocol used for PHY access. There are usually 1-3 buses available on the SoC, and each PHY will reference which bus they belong to.

module: board
  +--rw drivers
     +--rw mdios
        +--rw mdio* [miim_bus]
           +--rw miim_bus     miim_bus
           +--rw pin_ctrl
           |  +--rw pins*           uint32
           |  +--rw pin_function    pin_function
           +--rw frequency?   uint32
  • miim_bus is the bus ID, used for reference.

  • pin_ctrl is used to assign physical pins on the SoC to this function. Check the datasheet for an overview of what pins can be used.

  • frequency is the MIIM bus frequency in Hz. Leave out for default SoC frequency.

Example of an MDIO:

  mdios:
    mdio:
      - miim_bus: MIIM_BUS_0
        frequency: 2500000
        pin_ctrl:
          pins: [9, 10]
          pin_function: alt1

1.7. MUP1

MUP1 is a UART protocol facilitating configuring and inspecting the status of the Switch using the UART.

MUP1 is a SW function, but it needs to know which UART device it shall use. This is done by setting a handle, which ties it to the HW instance of the same handle (typically a FlexCom).

The definition of the MUP1 in the board.tree looks like this:

module: board
  +--rw drivers
     +--rw mup1
        +--rw ref_uart?   dev_uart

Following is an example connecting the MUP1 function to the HW instance using DEV_UART_0.

board:drivers:
  mup1:
    ref_uart: DEV_UART_0

See also: FlexCom

1.8. GPIO-Restart

The GPIO for Board restart is defined here. A board restart can e.g. be performed from management. The definition looks like this:

module: board
  +--rw drivers
     +--rw gpio_restart
        +--rw (ref)
        |  +--:(sgpio)
        |  |  +--rw sgpio
        |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
        |  |     +--rw port              uint8
        |  |     +--rw bit               uint8
        |  +--:(gpio)
        |     +--rw gpio?     uint32
        +--rw direction       gpio_direction
        +--rw active_state?   active
  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID.

  • direction is output.

  • active_state defines the signal’s active state. This is usually documented in schematics.

Example:

  gpio_restart:
    gpio: 60
    direction: GPIO_DIR_OUT
    active_state: low

1.9. GPIO-Reset

This reset is an input signal (activated by pressing a button) that indicates a reset-to-default should be performed. The SoC will immediately reset and read this signal during startup (state of the reset button). If active, the configuration is restored to default. The definition looks like this:

module: board
  +--rw drivers
     +--rw gpio_reset
        +--rw (ref)
        |  +--:(sgpio)
        |  |  +--rw sgpio
        |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
        |  |     +--rw port              uint8
        |  |     +--rw bit               uint8
        |  +--:(gpio)
        |     +--rw gpio?     uint32
        +--rw direction       gpio_direction
        +--rw active_state?   active
  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID.

  • direction is input.

  • active_state defines the signal’s active state. This is usually documented in schematics.

Example:

  gpio_reset:
    gpio: 2
    direction: GPIO_DIR_IN

1.10. Status Led

Initially, the status LED is turned off, and after the initial configuration is applied, it turns green (or blinks) to indicate normal operation.

module: board
  +--rw drivers
     +--rw status_led
        +--rw (ref)
        |  +--:(sgpio)
        |  |  +--rw sgpio
        |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
        |  |     +--rw port              uint8
        |  |     +--rw bit               uint8
        |  +--:(gpio)
        |     +--rw gpio?     uint32
        +--rw direction       gpio_direction
        +--rw active_state?   active
  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID.

  • direction is output.

  • active_state defines the signal’s active state. This is usually documented in schematics.

Example:

  status_led:
    gpio: 61
    direction: GPIO_DIR_OUT
    active_state: low

1.11. PHY Reset

The PHY’s reset state is controlled through the pin defined here.

module: board
  +--rw drivers
    +--rw phy_reset
       +--rw (ref)
       |  +--:(sgpio)
       |  |  +--rw sgpio
       |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
       |  |     +--rw port              uint8
       |  |     +--rw bit               uint8
       |  +--:(gpio)
       |     +--rw gpio?     uint32
       +--rw direction       gpio_direction
       +--rw active_state?   active
  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID.

  • direction is output.

  • active_state defines the signal’s active state. This is usually documented in schematics.

Example:

  phy_reset:
    gpio: 62
    direction: GPIO_DIR_OUT
    active_state: low

1.12. WatchDog

The watchdog is a hardware timer and helps to ensure the system can recover from unforeseen failures. It reboots the system if its timer has not been updated by the CPU within a period that is set here. If left out, then the watchdog is disabled.

module: board
  +--rw drivers
     +--rw watchdog
        +--rw timeout?   enumeration

Example, when timeout is set to 2 seconds:

  watchdog:
    timeout: timeout_2000ms

1.13. Port Leds

This section defines how the front port LEDs should be accessed, typically SFP-based LEDs. Each switch port typically has two LEDs: green for 'high' speed and a second one (red/yellow/orange, etc.) for 'low' speed. Note that the PHYs usually control the LEDs directly through their own GPIOs and do not require any board configuration setup.

module: board
  +--rw drivers
     +--rw port_leds
        +--rw port_led* [portno]
           +--rw portno        uint32
           +--rw led_green
           |  +--rw (ref)
           |  |  +--:(sgpio)
           |  |  |  +--rw sgpio
           |  |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
           |  |  |     +--rw port              uint8
           |  |  |     +--rw bit               uint8
           |  |  +--:(gpio)
           |  |     +--rw gpio?     uint32
           |  +--rw direction       gpio_direction
           |  +--rw active_state?   active
           +--rw led_second
              +--rw (ref)
              |  +--:(sgpio)
              |  |  +--rw sgpio
              |  |     +--rw ref_sgpio_bank    dev_sgpio_bank
              |  |     +--rw port              uint8
              |  |     +--rw bit               uint8
              |  +--:(gpio)
              |     +--rw gpio?     uint32
              +--rw direction       gpio_direction
              +--rw active_state?   active
  • portno defines to which switch front port (zero-based) these LEDs belong.

  • led_green defines how the green LED is accessed through SGPIOs or GPIOs.

  • led_second defines how the second LED is accessed through SGPIOs or GPIOs.

  • sgpio/gpio section defines how the signals are mapped to either SGPIO port/bit or GPIO ID. Example:

  port_leds:
    port_led:
      - portno: 24
        led_green:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 0
          direction: GPIO_DIR_OUT
          active_state: low
        led_second:
          sgpio:
            ref_sgpio_bank: DEV_SGPIO_BANK_0
            port: 24
            bit: 1
          direction: GPIO_DIR_OUT
          active_state: low

1.14. Bridge

The Ethernet bridge interconnects multiple ports to form a LAN. This section defines the switch chip and the properties of each of the attached ports and phys.

module: board
  +--rw drivers
     +--rw bridge
        +--rw mux_mode?      port_mux_mode
        +--rw target_chip    target_chip_type
        +--rw eth_ports
           +--rw eth_port* [port_dev]
              +--rw port_dev        uint32
              +--rw phy_mode        phy_mode
              +--rw phy_chip?       int32
              +--rw in_band_aneg?   boolean
              +--rw bandwidth?      uint32
              +--rw phy
                 +--rw ref_miim_bus    miim_bus
                 +--rw miim_addr       uint32
                 +--rw dummy?          boolean
                 +--rw base_port?      uint32
                 +--rw fixed_link
                 |  +--rw speed?   uint32
                 |  +--rw role?    phy_role
                 +--rw led* [id]
                    +--rw id      phy_led_id
                    +--rw mode    phy_led_mode
  • mux_mode defines which devices and serdeses are used. Used on some SoCs.

  • phy_mode defines the PHY to MAC interface.

  • target_chip The physical chip sometimes supports different skews. target_chip defines which one.

  • port_dev defines the chip port device to be used.

  • phy_chip defines the physical PHY chip this port is associated with, for hardware monitoring.

  • bandwidth defines the internal switch core bandwidth this port requires.

  • in_band_aneg means that the PHY status is fetched via the device PCS as opposed to via MDIO access. Supported for some interfaces.

  • ref_miim_bus defines the PHY MIIM bus ID.

  • miim_addr defines the PHY address on the bus.

  • dummy means that this is a software PHY and PHY access is disabled. Typically used where PHY access is not possible.

  • base_port is used for quad PHYs for determining which port ID should be used for access of shared resources.

  • fixed_link means that the speed is forced as opposed to 'aneg', and is left out when aneg is enabled.

  • speed defines the speed of the fixed_link.

  • role defines the role (master/slave) of the PHY, and is left out when aneg is enabled.

  • led defines the LED settings for the PHY. Supported for some PHYs.

The following example is a bridge with one PHY-based port and one SFP-based port:

    target_chip: lan9696tsn
    eth_ports:
      eth_port:
        - port_dev: 0
          phy_mode: qsgmii
          phy_chip: 1
          bandwidth: 1000
          phy:
            ref_miim_bus: MIIM_BUS_0
            miim_addr: 4
            base_port: 0
            led:
              - id: led0
                mode: link1000_activity
              - id: led1
                mode: link10_100_activity
        - port_dev: 24
          phy_mode: 10gbase-r
          bandwidth: 10000

1.15. PTP

Pin configuration of PTP functions. This section defines the GPIO to PTP mapping.

module: board
  +--rw drivers
     +--rw ptp
        +--ro pins* []
           +--ro pin_ctrl
              +--ro pins*           uint32
              +--ro pin_function    pin_function
  • pin_ctrl is used to assign physical pins on the SoC to this function. Check the datasheet for an overview of what pins can be used.

  • pins defines the GPIO(s) ID.

  • pin_function defines the mode to configure the pin(s).

The following example maps 3 GPIOs to the 1PPS PTP function ALT4:

  ptp:
    pins:
      - pin_ctrl:
          pins: [57, 58, 59]
          pin_function: alt4

2. Allocating of resources (capabilities)

The capabilities section is used to provide selected configurations for the application. All capability configurations are parsed at boot-time, and if this configuration requires memory to be allocated, then this allocation is done before the MUP1 announce packet is emitted.

If too many resources are assigned, it will result in a fatal boot error, and the board-tailor needs to lower the counts.

Here is what the capability section looks like in the board.tree:

module: board
  +--rw capabilities
     +--rw manufacturer          string
     +--rw model                 string
     +--rw l3_count?             uint32
     +--rw ltc_count?            uint32
     +--rw ltc_pin_count?        uint8
     +--rw phy_timestamping?     boolean
     +--rw stream_count?         uint32
     +--rw coap_session_count?   uint32
     +--rw arp_count?            uint32
     +--rw ipv4_route_count?     uint32

Where:

  • manufacturer: is a string returned by the IETF-HW YANG manufacturer leaf.

  • model: is the model returned in the IETF-System YANG.

  • l3_count?: Is the number of L3 interfaces. This shall be set to 1 on SW variants without routing support, and can be up to 32 on SW variants with routing support.

  • ltc_count?: Is the number of PTP instances (each instance is tied to a PTP domain). Set this to 3, as this is the number of domains supported in HW.

  • ltc_pin_count?: Number of PTP Pins which can be used for 1PPS in/out.

  • phy_timestamping?: Select if PHY time-stamping shall be used (requires PHYs with time-stamping support).

  • stream_count?: Number of PSFP Streams.

  • coap_session_count?: Number of CoAP sessions to support.

  • arp_count?: Number of ARP entries to support.

  • ipv4_route_count?: Number of IPv4 static routes. This shall be set to zero on SW variants without routing, and above 1 on systems with SW routing.

Here is an example of the capabilities:

board:capabilities:
  manufacturer: "Microchip Technology Inc."
  model: "LAN9698RED - EV89P81A (UNG8422)"
  l3_count: 1
  ltc_count: 3
  ltc_pin_count: 8
  phy_timestamping: false
  stream_count: 64
  coap_session_count: 4
  arp_count: 64
  ipv4_route_count: 0

3. Factory defaults

The factory defaults can contain the full CORECONF data-store, and is applied at boot time if no user-configuration is stored in flash.

An example of a factory defaults which includes port 1 and port 2 in VLAN 1 is shown below:

board:factory_default_config:
  ieee802-dot1q-bridge:bridges:
    bridge:
      - name: b0
        component:
          - name: c0
            filtering-database:
              vlan-registration-entry:
                - database-id: 0
                  vids: '1'
                  entry-type: static
                  port-map:
                    - port-ref: 1
                      static-vlan-registration-entries:
                        vlan-transmitted: untagged
                    - port-ref: 2
                      static-vlan-registration-entries:
                        vlan-transmitted: untagged