checks: add I2C bus checks

Add I2C bus type detection and checks. The node name is used to find I2C
buses as there is no common compatible or property which can be used to
identify I2C controllers/buses. There are some common I2C properties,
but they are not used frequently enough to match on.

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:31 -06:00 committed by David Gibson
parent 88f18909db
commit 53a1bd5469
1 changed files with 70 additions and 0 deletions

View File

@ -962,6 +962,73 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);

static const struct bus_type i2c_bus = {
.name = "i2c-bus",
};

static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
node->bus = &i2c_bus;
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
struct node *child;
for_each_child(node, child) {
if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
return;
}
node->bus = &i2c_bus;
} else
return;

if (!node->children)
return;

if (node_addr_cells(node) != 1)
FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
if (node_size_cells(node) != 0)
FAIL(c, dti, node, "incorrect #size-cells for I2C bus");

}
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);

static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[17];
uint32_t reg = 0;
int len;
cell_t *cells = NULL;

if (!node->parent || (node->parent->bus != &i2c_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, "I2C bus unit address format error, expected \"%s\"",
unit_addr);

for (len = prop->val.len; len > 0; len -= 4) {
reg = fdt32_to_cpu(*(cells++));
if (reg > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);

}
}
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);

static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -1582,6 +1649,9 @@ static struct check *check_table[] = {
&simple_bus_bridge,
&simple_bus_reg,

&i2c_bus_bridge,
&i2c_bus_reg,

&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
&unique_unit_address,