diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2008-07-26 04:25:13 +0200 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2008-07-26 04:25:13 +0200 |
commit | 3f07af494dfa6de43137dae430431c9fbf929c0c (patch) | |
tree | ee204d7cb204fbe287f2626fdeb8926adc7d4889 /drivers/of/base.c | |
parent | Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/po... (diff) | |
download | linux-3f07af494dfa6de43137dae430431c9fbf929c0c.tar.xz linux-3f07af494dfa6de43137dae430431c9fbf929c0c.zip |
of: adapt of_find_i2c_driver() to be usable by SPI also
SPI has a similar problem as I2C in that it needs to determine an
appropriate modalias value for each device node. This patch adapts
the of_i2c of_find_i2c_driver() function to be usable by of_spi also.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 23ffb7c0caf2..ad8ac1a8af28 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -385,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,<modalias>" 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,<modalias> 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); + |