of: spmi: Add support for device naming and lookups
Since we support multiple device_nodes per spmi_device when used
with the spmi-dev-container flag, it's often unclear how a driver
should make reference to a particular device. Therefore,
introduce the spmi specific binding spmi-dev-name that specifies
the device name for the device_node.
Also introduce an API that can be used from
the driver to lookup the specific device node associated with a
particular device name.
Note that it may seem at first glance that the binding 'label' is
redundant with device_node->name. However, per the ePAPR,
device_node->name is intended to be as generic as possible,
representing the function of the device and not the precise
programming model. 'label' is used to give a platform
specific name that can be queried from device drivers.
Change-Id: I28eca35d0b625372c26a6d8ad81e7679f200d14b
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/spmi/msm-spmi.txt b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
index 5539940..9d10f07 100644
--- a/Documentation/devicetree/bindings/spmi/msm-spmi.txt
+++ b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
@@ -91,7 +91,10 @@
specified above in the 'reg' property.
- interrupt-names : a list of strings that map in order to the list of
interrupts specified in the 'interrupts' property.
-
+ - label: A single name that names the device. This name can be looked up
+ with spmi_get_node_byname(). This is mostly useful in spmi-dev-container
+ configurations where multiple device_nodes are associated with one spmi
+ device.
Notes :
- It is considered an error to include spmi-slave-dev at this level.
@@ -132,6 +135,7 @@
qcom,qpnp_gpio = <1>;
interrupt-parent = <&qpnp>;
interrupts = <0x3 0x15 0x02 0x1 0x47 0x0>;
+ label = "foo-dev";
};
pm8941_gpio2@0xc100 {
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index ea8f45c..d0ae95a 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -121,6 +121,8 @@
res = d_info->b_info.dev_node[idx].resource;
d_info->b_info.dev_node[idx].of_node = r_info->node;
+ of_property_read_string(r_info->node, "label",
+ &d_info->b_info.dev_node[idx].label);
if ((num_irq || num_reg) && (res != NULL)) {
for (i = 0; i < num_reg; i++, res++) {
diff --git a/drivers/spmi/spmi-resources.c b/drivers/spmi/spmi-resources.c
index 152b69d..390e9ec 100644
--- a/drivers/spmi/spmi-resources.c
+++ b/drivers/spmi/spmi-resources.c
@@ -119,3 +119,30 @@
return r ? r->start : -ENXIO;
}
EXPORT_SYMBOL_GPL(spmi_get_irq_byname);
+
+/*
+ * spmi_get_devnode_byname - get a device node resource
+ * @dev: spmi device handle
+ * @label: device name to lookup
+ *
+ * Given a name, find the associated spmi_resource that matches the name.
+ * Return NULL if the lookup fails.
+ */
+struct spmi_resource *spmi_get_dev_container_byname(struct spmi_device *dev,
+ const char *label)
+{
+ int i;
+
+ if (!label)
+ return NULL;
+
+ for (i = 0; i < dev->num_dev_node; i++) {
+ struct spmi_resource *r = &dev->dev_node[i];
+
+ if (r && r->label && !strncmp(r->label,
+ label, SPMI_MAX_RES_NAME))
+ return r;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(spmi_get_dev_container_byname);
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
index 3ac2a34..299d3de 100644
--- a/include/linux/spmi.h
+++ b/include/linux/spmi.h
@@ -92,11 +92,19 @@
* @num_resources: number of resources for this device node
* @resources: array of resources for this device_node
* @of_node: device_node of the resource in question
+ * @label: name used to reference the device from the driver
+ *
+ * Note that we explicitly add a 'label' pointer here since per
+ * the ePAPR 2.2.2, the device_node->name should be generic and not
+ * reflect precise programming model. Thus label enables a
+ * platform specific name to be assigned with the 'label' binding to
+ * allow for unique query names.
*/
struct spmi_resource {
struct resource *resource;
u32 num_resources;
struct device_node *of_node;
+ const char *label;
};
/**
@@ -443,4 +451,7 @@
extern int spmi_get_irq_byname(struct spmi_device *dev,
struct spmi_resource *node, const char *name);
+
+struct spmi_resource *spmi_get_dev_container_byname(struct spmi_device *dev,
+ const char *label);
#endif