[RFC 1/4] of: add of_dev_get_platdata()

From: Milo Kim
Date: Fri Aug 28 2015 - 05:12:34 EST


of_dev_get_platdata()
- provides unified handling of getting device platform data
- supports DT and non-DT(legacy) cases
if CONFIG_OF is not defined, then returns legacy function,
'dev_get_platdata()'.
- removes duplicated code from each driver
- keeps driver specific code simple in each driver

Parser function - of_parse_dt_fn()
Caller(aka driver) gets allocated platform data and optional private
data. Then, it will parse the DT and copy properties into allocated
platform data and use the private data if needed.

Cc: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
Cc: Felipe Balbi <balbi@xxxxxx>
Cc: Grant Likely <grant.likely@xxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Lee Jones <lee.jones@xxxxxxxxxx>
Cc: Rob Herring <robh+dt@xxxxxxxxxx>
Cc: Samuel Ortiz <sameo@xxxxxxxxxxxxxxx>
Cc: Tony Lindgren <tony@xxxxxxxxxxx>
Cc: devicetree@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Signed-off-by: Milo Kim <milo.kim@xxxxxx>
---
drivers/of/device.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/of_device.h | 12 ++++++++++++
2 files changed, 58 insertions(+)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index 8b91ea2..5793ba0 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -286,3 +286,49 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)

return 0;
}
+
+/**
+ * of_dev_get_platdata - get the platform data.
+ * @dev: device to get the platform data.
+ * @size: size of the platform data.
+ * @of_parse_dt_fn: device specific function to parse the device tree.
+ * @priv: driver private data to be passed to of_parse_dt_fn.
+ *
+ * This routine provides unified way of getting device platform data.
+ * If the platform data exists, just return it. It's exactly same as
+ * how to get device platform data by using dev_get_platdata().
+ * If the platform data is null, checks the device node. If the device tree is
+ * is supported, then allocates the device platform data and call back to
+ * driver specific 'of_parse_dt_fn'. The caller driver should handle data
+ * manipulation inside this function.
+ *
+ * of_parse_dt_fn() has three arguments. The first is device structure.
+ * The second is the pointer of allocated device platform data.
+ * The last one is private data pointer which is used in of_parse_dt_fn().
+ *
+ * Return value is a pointer of device platform data.
+ * Caller should check IS_ERR(pdata) and return PTR_ERR(pdata).
+ */
+void *of_dev_get_platdata(struct device *dev, size_t size,
+ of_parse_dt_t of_parse_dt_fn, void *priv)
+{
+ void *pdata = dev_get_platdata(dev);
+ int err;
+
+ if (pdata)
+ return pdata;
+
+ if (!dev_of_node(dev) || !of_parse_dt_fn)
+ return NULL;
+
+ pdata = devm_kzalloc(dev, size, GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ err = of_parse_dt_fn(dev, pdata, priv);
+ if (err)
+ return ERR_PTR(err);
+
+ return pdata;
+}
+EXPORT_SYMBOL_GPL(of_dev_get_platdata);
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index cc7dd687..b24b3d8 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -10,6 +10,9 @@

struct device;

+/* Device specific DT parser function */
+typedef int (*of_parse_dt_t)(struct device *, void *, void *);
+
#ifdef CONFIG_OF
extern const struct of_device_id *of_match_device(
const struct of_device_id *matches, const struct device *dev);
@@ -56,6 +59,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
}

void of_dma_configure(struct device *dev, struct device_node *np);
+
+extern void *of_dev_get_platdata(struct device *dev, size_t size,
+ of_parse_dt_t of_parse_dt_fn, void *priv);
#else /* CONFIG_OF */

static inline int of_driver_match_device(struct device *dev,
@@ -100,6 +106,12 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
}
static inline void of_dma_configure(struct device *dev, struct device_node *np)
{}
+
+static inline void *of_dev_get_platdata(struct device *dev, size_t size,
+ of_parse_dt_t of_parse_dt_fn, void *priv)
+{
+ return dev_get_platdata(dev);
+}
#endif /* CONFIG_OF */

#endif /* _LINUX_OF_DEVICE_H */
--
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/