diff options
author | Rob Herring <robh@kernel.org> | 2018-07-26 21:19:32 -0600 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2018-07-27 13:42:50 +1000 |
commit | 90a190eb04d926655b643328ae995336568b705b (patch) | |
tree | 0905e17b92ab1d90770403c4e24c4dfefd7ca6d5 /checks.c | |
parent | 53a1bd5469055af7049a0ddaf00524a56d21bca2 (diff) | |
download | dtc-90a190eb04d926655b643328ae995336568b705b.zip dtc-90a190eb04d926655b643328ae995336568b705b.tar.gz dtc-90a190eb04d926655b643328ae995336568b705b.tar.bz2 |
checks: add SPI bus checks
Add SPI bus type detection and checks. The node name is the
preferred way to find SPI buses as there is no common compatible or
property which can be used. There are a few common properties used in
child nodes, so they can be used as a fallback detection method. This
lets us warn if the SPI controller is not properly named 'spi@...'.
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'checks.c')
-rw-r--r-- | checks.c | 73 |
1 files changed, 73 insertions, 0 deletions
@@ -1029,6 +1029,76 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node } WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); +static const struct bus_type spi_bus = { + .name = "spi-bus", +}; + +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + + if (strprefixeq(node->name, node->basenamelen, "spi")) { + node->bus = &spi_bus; + } else { + /* Try to detect SPI buses which don't have proper node name */ + struct node *child; + + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) + return; + + for_each_child(node, child) { + struct property *prop; + for_each_property(child, prop) { + if (strprefixeq(prop->name, 4, "spi-")) { + node->bus = &spi_bus; + break; + } + } + if (node->bus == &spi_bus) + break; + } + + if (node->bus == &spi_bus && get_property(node, "reg")) + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); + } + if (node->bus != &spi_bus || !node->children) + return; + + if (node_addr_cells(node) != 1) + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); + +} +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); + +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[9]; + uint32_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &spi_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", + unit_addr); +} +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); + static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node) { @@ -1652,6 +1722,9 @@ static struct check *check_table[] = { &i2c_bus_bridge, &i2c_bus_reg, + &spi_bus_bridge, + &spi_bus_reg, + &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, |