spmi: qpnp: Change APIs to take a spmi_resource pointer instead of index
Pointers are more flexible than index numbers, since index
numbers depend upon an additional reference to the array in
question. In particular, we'd like to add a new API to lookup a
devnode based on a predefined name in the Device Tree. This API
will return a spmi_resource, and so it's natural to want to use
this pointer directly with the other existing APIs.
Also introduce a new API spmi_for_each_devnode that can be used
to iterate each spmi_resource in the dev_node array. This
abstracts the traversal of the array, which was previously done
within the existing APIs.
Change-Id: I18f9397e5d78770e840a9f95dd8061201931df6e
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index ef2657e..1b42ad9 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -844,8 +844,9 @@
static int qpnp_gpio_probe(struct spmi_device *spmi)
{
struct qpnp_gpio_chip *q_chip;
- struct resource *res;
struct qpnp_gpio_spec *q_spec;
+ struct resource *res;
+ struct spmi_resource *d_node;
int i, rc;
int lowest_gpio = UINT_MAX, highest_gpio = 0;
u32 intspec[3], gpio;
@@ -867,7 +868,7 @@
/* first scan through nodes to find the range required for allocation */
for (i = 0; i < spmi->num_dev_node; i++) {
rc = of_property_read_u32(spmi->dev_node[i].of_node,
- "qcom,gpio-num", &gpio);
+ "qcom,gpio-num", &gpio);
if (rc) {
dev_err(&spmi->dev, "%s: unable to get"
" qcom,gpio-num property\n", __func__);
@@ -919,14 +920,15 @@
/* now scan through again and populate the lookup table */
for (i = 0; i < spmi->num_dev_node; i++) {
- res = spmi_get_resource(spmi, i, IORESOURCE_MEM, 0);
+ d_node = &spmi->dev_node[i];
+ res = spmi_get_resource(spmi, d_node, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&spmi->dev, "%s: node %s is missing has no"
" base address definition\n",
- __func__, spmi->dev_node[i].of_node->full_name);
+ __func__, d_node->of_node->full_name);
}
- rc = of_property_read_u32(spmi->dev_node[i].of_node,
+ rc = of_property_read_u32(d_node->of_node,
"qcom,gpio-num", &gpio);
if (rc) {
dev_err(&spmi->dev, "%s: unable to get"
@@ -948,7 +950,7 @@
q_spec->offset = res->start;
q_spec->gpio_chip_idx = i;
q_spec->pmic_gpio = gpio;
- q_spec->node = spmi->dev_node[i].of_node;
+ q_spec->node = d_node->of_node;
q_spec->q_chip = q_chip;
rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 322af43..8d592fb 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -1187,7 +1187,7 @@
pdata->init_data.constraints.input_uV
= pdata->init_data.constraints.max_uV;
- res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
+ res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&spmi->dev, "%s: node is missing base address\n",
__func__);
diff --git a/drivers/spmi/spmi-resources.c b/drivers/spmi/spmi-resources.c
index b692f82..d7adea9 100644
--- a/drivers/spmi/spmi-resources.c
+++ b/drivers/spmi/spmi-resources.c
@@ -20,21 +20,30 @@
/**
* spmi_get_resource - get a resource for a device
* @dev: spmi device
- * @node_idx: dev_node index
+ * @node: device node resource
* @type: resource type
* @res_num: resource index
*
+ * If 'node' is specified as NULL, then the API treats this as a special
+ * case to assume the first devnode. For configurations that do not use
+ * spmi-dev-container, there is only one node to begin with, so NULL should
+ * be passed in this case.
+ *
* Returns
* NULL on failure.
*/
struct resource *spmi_get_resource(struct spmi_device *dev,
- unsigned int node_idx, unsigned int type,
- unsigned int res_num)
+ struct spmi_resource *node,
+ unsigned int type, unsigned int res_num)
{
int i;
- for (i = 0; i < dev->dev_node[node_idx].num_resources; i++) {
- struct resource *r = &dev->dev_node[node_idx].resource[i];
+ /* if a node is not specified, default to the first node */
+ if (!node)
+ node = &dev->dev_node[0];
+
+ for (i = 0; i < node->num_resources; i++) {
+ struct resource *r = &node->resource[i];
if (type == resource_type(r) && res_num-- == 0)
return r;
@@ -46,19 +55,18 @@
/**
* spmi_get_irq - get an IRQ for a device
* @dev: spmi device
- * @node_idx: dev_node index
+ * @node: device node resource
* @res_num: IRQ number index
*
* Returns
* -ENXIO on failure.
*/
-int spmi_get_irq(struct spmi_device *dev, unsigned int node_idx,
+int spmi_get_irq(struct spmi_device *dev, struct spmi_resource *node,
unsigned int res_num)
{
- struct resource *r = spmi_get_resource(dev, node_idx,
+ struct resource *r = spmi_get_resource(dev, node,
IORESOURCE_IRQ, res_num);
return r ? r->start : -ENXIO;
}
EXPORT_SYMBOL_GPL(spmi_get_irq);
-
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
index 71e9810..3eb1ac9 100644
--- a/include/linux/spmi.h
+++ b/include/linux/spmi.h
@@ -418,10 +418,21 @@
*/
extern int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid);
-extern struct resource *spmi_get_resource(struct spmi_device *dev,
- unsigned int node_idx, unsigned int type,
- unsigned int res_num);
+/**
+ * spmi_for_each_container_dev - iterate over the array of devnode resources.
+ * @res: spmi_resource pointer used as the array cursor
+ * @spmi_dev: spmi_device to iterate
+ *
+ * Only useable in spmi-dev-container configurations.
+ */
+#define spmi_for_each_container_dev(res, spmi_dev) \
+ for (res = ((spmi_dev)->dev_node ? &(spmi_dev)->dev_node[0] : NULL); \
+ (res - (spmi_dev)->dev_node) < (spmi_dev)->num_dev_node; res++)
-extern int spmi_get_irq(struct spmi_device *dev, unsigned int node_idx,
+extern struct resource *spmi_get_resource(struct spmi_device *dev,
+ struct spmi_resource *node,
+ unsigned int type, unsigned int res_num);
+
+extern int spmi_get_irq(struct spmi_device *dev, struct spmi_resource *node,
unsigned int res_num);
#endif