X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fof%2Fbase.c;h=ad8ac1a8af28689acc7198b22fe95a888d62e6a6;hb=676056132425ac425d7215cdaa8bd25582e07966;hp=80c9deca5f35aa3313245d099215d5f387c687b1;hpb=0a3abcf75bf391fec4e32356ab5ddb8f5d2e6b41;p=linux-2.6 diff --git a/drivers/of/base.c b/drivers/of/base.c index 80c9deca5f..ad8ac1a8af 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -65,6 +65,9 @@ struct property *of_find_property(const struct device_node *np, { struct property *pp; + if (!np) + return NULL; + read_lock(&devtree_lock); for (pp = np->properties; pp != 0; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { @@ -116,6 +119,32 @@ int of_device_is_compatible(const struct device_node *device, } EXPORT_SYMBOL(of_device_is_compatible); +/** + * of_device_is_available - check if a device is available for use + * + * @device: Node to check for availability + * + * Returns 1 if the status property is absent or set to "okay" or "ok", + * 0 otherwise + */ +int of_device_is_available(const struct device_node *device) +{ + const char *status; + int statlen; + + status = of_get_property(device, "status", &statlen); + if (status == NULL) + return 1; + + if (statlen > 0) { + if (!strcmp(status, "okay") || !strcmp(status, "ok")) + return 1; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_available); + /** * of_get_parent - Get a node's parent if any * @node: Node to get parent @@ -356,3 +385,91 @@ struct device_node *of_find_matching_node(struct device_node *from, return np; } EXPORT_SYMBOL(of_find_matching_node); + +/** + * of_modalias_table: Table of explicit compatible ==> modalias mappings + * + * This table allows particulare compatible property values to be mapped + * to modalias strings. This is useful for busses which do not directly + * understand the OF device tree but are populated based on data contained + * within the device tree. SPI and I2C are the two current users of this + * table. + * + * In most cases, devices do not need to be listed in this table because + * the modalias value can be derived directly from the compatible table. + * However, if for any reason a value cannot be derived, then this table + * provides a method to override the implicit derivation. + * + * At the moment, a single table is used for all bus types because it is + * assumed that the data size is small and that the compatible values + * should already be distinct enough to differentiate between SPI, I2C + * and other devices. + */ +struct of_modalias_table { + char *of_device; + char *modalias; +}; +static struct of_modalias_table of_modalias_table[] = { + /* Empty for now; add entries as needed */ +}; + +/** + * of_modalias_node - Lookup appropriate modalias for a device node + * @node: pointer to a device tree node + * @modalias: Pointer to buffer that modalias value will be copied into + * @len: Length of modalias value + * + * Based on the value of the compatible property, this routine will determine + * an appropriate modalias value for a particular device tree node. Three + * separate methods are used to derive a modalias value. + * + * First method is to lookup the compatible value in of_modalias_table. + * Second is to look for a "linux," entry in the compatible list + * and used that for modalias. Third is to strip off the manufacturer + * prefix from the first compatible entry and use the remainder as modalias + * + * This routine returns 0 on success + */ +int of_modalias_node(struct device_node *node, char *modalias, int len) +{ + int i, cplen; + const char *compatible; + const char *p; + + /* 1. search for exception list entry */ + for (i = 0; i < ARRAY_SIZE(of_modalias_table); i++) { + compatible = of_modalias_table[i].of_device; + if (!of_device_is_compatible(node, compatible)) + continue; + strlcpy(modalias, of_modalias_table[i].modalias, len); + return 0; + } + + compatible = of_get_property(node, "compatible", &cplen); + if (!compatible) + return -ENODEV; + + /* 2. search for linux, entry */ + p = compatible; + while (cplen > 0) { + if (!strncmp(p, "linux,", 6)) { + p += 6; + strlcpy(modalias, p, len); + return 0; + } + + i = strlen(p) + 1; + p += i; + cplen -= i; + } + + /* 3. take first compatible entry and strip manufacturer */ + p = strchr(compatible, ','); + if (!p) + return -ENODEV; + p++; + strlcpy(modalias, p, len); + return 0; +} +EXPORT_SYMBOL_GPL(of_modalias_node); +