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>
main
Rob Herring 2018-07-26 21:19:32 -06:00 committed by David Gibson
parent 53a1bd5469
commit 90a190eb04
1 changed files with 73 additions and 0 deletions

View File

@ -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, &reg_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, &reg_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,