On Thu, Jul 26, 2018 at 09:19:31PM -0600, Rob Herring wrote: > 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@xxxxxxxxxx> Applied series, thanks. > --- > checks.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 70 insertions(+) > > diff --git a/checks.c b/checks.c > index a2cc1036c915..f0b9f87e8132 100644 > --- a/checks.c > +++ b/checks.c > @@ -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, ®_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, ®_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, -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Attachment:
signature.asc
Description: PGP signature