svd-generator 0.2.0

Converts device information from flattened device tree into an SVD description
Documentation
use crate::svd::register::{
    create_bit_range, create_cluster, create_field, create_register, create_register_properties,
};
use crate::Result;

/// Creates a StarFive JH7110 SYS Pinctrl GPI registers.
pub fn create() -> Result<svd::RegisterCluster> {
    const GPI_LEN: usize = 23;
    #[rustfmt::skip]
    const RESET_VALUES: [u64; GPI_LEN] = [
        //       32           33           34           35
        0x0000_0000, 0x0000_0002, 0x0027_2600, 0x0b08_0000,
        //       36           37           38           39
        0x040f_0e0c, 0x0000_0006, 0x3233_0000, 0x0000_0334,
        //       40           41           42           43
        0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,
        //       44           45           46           47
        0x0000_0000, 0x0000_0000, 0x0038_3637, 0x002a_2d00,
        //       48           49           50           51
        0x2928_0000, 0x3c3a_3b15, 0x2e31_0000, 0x0040_3e3f,
        //       52           53           54
        0x0000_0000, 0x0000_0000, 0x0000_0000,
    ];
    #[rustfmt::skip]
    const FIELD_NAMES: [[&str; 4]; GPI_LEN] = [
        // 32
        ["wave511_uart_rxsin", "can_rxd_0", "usb_over_current", "spdif_spdi_fi"],
        // 33
        ["jtag_trstn", "hdmi_cec_sda", "hdmi_ddc_scl", "hdmi_ddc_sda"],
        // 34
        ["hdmi_hpd", "i2c_clk_0", "i2c_data_0", "sdio_detect_0"],
        // 35
        ["sdio_int_0", "sdio_write_prt_0", "uart_sin_0", "hifi4_jtck_0"],
        // 36
        ["hifi4_jtdi", "hifi4_jtms", "hifi4_jtrstn", "jtag_tdi"],
        // 37
        ["jtag_tms", "pdm_dmic_0", "pdm_dmic_1", "audio_i2srx_0"],
        // 38
        ["audio_i2srx_1", "audio_i2srx_2", "spi_clkin_0", "spi_fssin_0"],
        // 39
        ["spi_rxd_0", "jtag_tck", "mclk", "i2srx_bclk_slv_0"],
        // 40
        ["i2srx_lrck_slv_0", "i2stx_bclk_slv_0", "i2stx_lrck_slv_0", "tdm_clk_slv_0"],
        // 41
        ["pcm_rxd_0", "pcm_synon_0", "can_rxd_1", "i2c_clk_1"],
        // 42
        ["i2c_data_1", "sdio_detect_1", "sdio_int_1", "sdio_write_prt_1"],
        // 43
        ["sdio_ccmd_1", "sdio_cdata_0", "sdio_cdata_1", "sdio_cdata_2"],
        // 44
        ["sdio_cdata_3", "sdio_cdata_4", "sdio_cdata_5", "sdio_cdata_6"],
        // 45
        ["sdio_cdata_7", "sdio_data_strobe", "uart_cts_1", "uart_sin_1"],
        // 46
        ["spi_clkin_1", "spi_fssin_1", "spi_rxd_1", "i2c_clk_2"],
        // 47
        ["i2c_data_2", "uart_cts_2", "uart_sin_2", "spi_clkin_2"],
        // 48
        ["spi_fssin_2", "spi_rxd_2", "i2c_clk_3", "i2c_data_3"],
        // 49
        ["uart_sin_3", "spi_clkin_3", "spi_fssin_3", "spi_rxd_3"],
        // 50
        ["i2c_clk_4", "i2c_data_4", "uart_cts_4", "uart_sin_4"],
        // 51
        ["spi_clkin_4", "spi_fssin_4", "spi_rxd_4", "i2c_clk_5"],
        // 52
        ["i2c_data_5", "uart_cts_5", "uart_sin_5", "spi_clkin_5"],
        // 53
        ["spi_fssin_5", "spi_rxd_5", "i2c_clk_6", "i2c_data_6"],
        // 54
        ["spi_clkin_6", "spi_fssin_6", "spi_rxd_6", "_reserved"],
    ];
    const DESC: &str = r#"The register can be used to configure the selected GPIO connector number for input signals. The signal name is indicated in the "Name" column of the following table per StarFive naming conventions. For example, name "u0_WAVE511_i_uart_rxsin_cfg" indicates the corresponding input signal is "u0_WAVE511.i_uart_rxsin". See GPIO Input Signals (on page 107) for a complete list of the input GPIO signals."#;
    const FIELD_DESC: &str = "The register value indicates the selected GPIO number + 2 (GPIO2 - GPIO63, GPIO0 and GPIO1 are not available) for the input signal.";

    Ok(svd::RegisterCluster::Cluster(create_cluster(
        "gpi",
        DESC,
        0x80,
        RESET_VALUES
            .iter()
            .zip(FIELD_NAMES.iter())
            .enumerate()
            .filter_map(|(idx, (&rst, field_names))| {
                // addr serves as the address offset, and the GPIO number
                let addr = (idx * 4) as u32;

                let (a, b, c, d) = (
                    field_names[0],
                    field_names[1],
                    field_names[2],
                    field_names[3],
                );
                let field_len = if idx == GPI_LEN - 1 { 3 } else { 4 };
                let fields = [
                    create_field(
                        a,
                        FIELD_DESC,
                        create_bit_range("[6:0]").ok()?,
                        svd::Access::ReadWrite,
                        None,
                    )
                    .ok()?,
                    create_field(
                        b,
                        FIELD_DESC,
                        create_bit_range("[14:8]").ok()?,
                        svd::Access::ReadWrite,
                        None,
                    )
                    .ok()?,
                    create_field(
                        c,
                        FIELD_DESC,
                        create_bit_range("[22:16]").ok()?,
                        svd::Access::ReadWrite,
                        None,
                    )
                    .ok()?,
                    create_field(
                        d,
                        FIELD_DESC,
                        create_bit_range("[30:24]").ok()?,
                        svd::Access::ReadWrite,
                        None,
                    )
                    .ok()?,
                ];

                let reg_desc = if idx == GPI_LEN - 1 {
                    format!("SYS IOMUX CFG SAIF SYSCFG FMUX GPIO GPI: [{a}, {b}, {c}]")
                } else {
                    format!("SYS IOMUX CFG SAIF SYSCFG FMUX GPIO GPI: [{a}, {b}, {c}, {d}]")
                };

                Some(svd::RegisterCluster::Register(
                    create_register(
                        format!("gpi{idx}").as_str(),
                        reg_desc.as_str(),
                        addr,
                        create_register_properties(32, rst).ok()?,
                        Some(&fields[..field_len]),
                        None,
                    )
                    .ok()?,
                ))
            })
            .collect::<Vec<svd::RegisterCluster>>()
            .as_ref(),
        None,
    )?))
}