Re: [PATCH v2 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
Cousson, Benoit b-cous...@ti.com writes: On 9/17/2011 6:13 PM, Grant Likely wrote: On Fri, Sep 16, 2011 at 04:43:19PM +0200, Benoit Cousson wrote: [...] +} + +static int _omap_device_notifier_call(struct notifier_block *nb, + unsigned long event, void *dev) Nit: Why the preceding underscore? Generally that is only done for 'special' variants of public functions. ie. for a variant that expects a lock to already be held. Yeah, the convention in this file is not that strict, and it is used for internal static helper function as well. I'll let Kevin arbitrate that point :-) The convention in this file is the leading '_' is used for internal helper functions. I'd prefer to keep it that way, and if we decide to change the coding convention to match a coding convention elsewhere, we should do it all at the same time. Kevin -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
On 9/17/2011 6:13 PM, Grant Likely wrote: On Fri, Sep 16, 2011 at 04:43:19PM +0200, Benoit Cousson wrote: Add a notifier called during device_add phase. If an of_node is present, retrieve the hwmod entry in order to populate properly the omap_device structure. For the moment the resource from the device-tree are overloaded. DT does not support named resource yet, and thus, most driver will not work without that information. Add two helpers function to parse a property that contains multiple strings. Signed-off-by: Benoit Coussonb-cous...@ti.com Cc: Kevin Hilmankhil...@ti.com --- arch/arm/plat-omap/omap_device.c | 144 ++ 1 files changed, 144 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index cac7b9a..da13630 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -85,6 +85,8 @@ #includelinux/clk.h #includelinux/clkdev.h #includelinux/pm_runtime.h +#includelinux/of.h +#includelinux/notifier.h #includeplat/omap_device.h #includeplat/omap_hwmod.h @@ -94,12 +96,15 @@ #define USE_WAKEUP_LAT0 #define IGNORE_WAKEUP_LAT 1 +#define MAX_HWMOD_NAME_SIZE32 + static int omap_device_register(struct platform_device *pdev); static int omap_early_device_register(struct platform_device *pdev); static struct omap_device *omap_device_alloc(struct platform_device *pdev, struct omap_hwmod **ohs, int oh_cnt, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt); +static void omap_device_delete(struct omap_device *od); static struct omap_device_pm_latency omap_default_latency[] = { @@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od, _add_clkdev(od, oh-opt_clks[i].role, oh-opt_clks[i].clk); } +/* + * XXX: DT helper functions that should probably move elsewhere if + * they become usefull for other needs. + */ Lets just *assume* these are useful for other needs and start with them in drivers/of so that other people know that they actually exist. Otherwise they will never be made generic. :-) Good point... But, meanwhile Stephen Warren proposed a much nicer iterator to deal with that. Since these patches are still not in mainline, I didn't want to depend on them yet. So my secret plan was to remove these functions once the ones from Stephen will be merged. +static int _dt_count_property_string(const char *prop, int len) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len= total; total += l, prop += l) { + l = strlen(prop) + 1; + if (*prop != 0) + i++; + } + return i; +} + +static int _dt_get_property(const char *prop, int len, int index, char *output, + int size) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len= total; total += l, prop += l) { + l = strlcpy(output, prop, size) + 1; + if (*prop != 0) { + if (i++ == index) + return 0; + } + } + return -ENODEV; +} + +static struct dev_pm_domain omap_device_pm_domain; + +/** + * omap_device_build_from_dt - build an omap_device with multiple hwmods + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Function for building an omap_device already registered from device-tree + * + * Returns 0 or PTR_ERR() on error. + */ +static int omap_device_build_from_dt(struct platform_device *pdev) +{ + struct omap_hwmod **hwmods; + struct omap_device *od; + struct omap_hwmod *oh; + char oh_name[MAX_HWMOD_NAME_SIZE]; + const char *prop; + int oh_cnt, i, prop_len; + int ret = 0; + + prop = of_get_property(pdev-dev.of_node, hwmods,prop_len); I know you've posted it before, but what is the status of the hwmods binding documentation. I would expect it to be part of this patch. It was part of the series that introduced the first node with hwmods attribute (http://lists.ozlabs.org/pipermail/devicetree-discuss/2011-August/007621.html). I do agree, it makes sense to add it here. + oh_cnt = _dt_count_property_string(prop, prop_len); + if
Re: [PATCH v2 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
On Fri, Sep 16, 2011 at 04:43:19PM +0200, Benoit Cousson wrote: Add a notifier called during device_add phase. If an of_node is present, retrieve the hwmod entry in order to populate properly the omap_device structure. For the moment the resource from the device-tree are overloaded. DT does not support named resource yet, and thus, most driver will not work without that information. Add two helpers function to parse a property that contains multiple strings. Signed-off-by: Benoit Cousson b-cous...@ti.com Cc: Kevin Hilman khil...@ti.com --- arch/arm/plat-omap/omap_device.c | 144 ++ 1 files changed, 144 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index cac7b9a..da13630 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -85,6 +85,8 @@ #include linux/clk.h #include linux/clkdev.h #include linux/pm_runtime.h +#include linux/of.h +#include linux/notifier.h #include plat/omap_device.h #include plat/omap_hwmod.h @@ -94,12 +96,15 @@ #define USE_WAKEUP_LAT 0 #define IGNORE_WAKEUP_LAT1 +#define MAX_HWMOD_NAME_SIZE 32 + static int omap_device_register(struct platform_device *pdev); static int omap_early_device_register(struct platform_device *pdev); static struct omap_device *omap_device_alloc(struct platform_device *pdev, struct omap_hwmod **ohs, int oh_cnt, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt); +static void omap_device_delete(struct omap_device *od); static struct omap_device_pm_latency omap_default_latency[] = { @@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od, _add_clkdev(od, oh-opt_clks[i].role, oh-opt_clks[i].clk); } +/* + * XXX: DT helper functions that should probably move elsewhere if + * they become usefull for other needs. + */ Lets just *assume* these are useful for other needs and start with them in drivers/of so that other people know that they actually exist. Otherwise they will never be made generic. :-) +static int _dt_count_property_string(const char *prop, int len) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len = total; total += l, prop += l) { + l = strlen(prop) + 1; + if (*prop != 0) + i++; + } + return i; +} + +static int _dt_get_property(const char *prop, int len, int index, char *output, + int size) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len = total; total += l, prop += l) { + l = strlcpy(output, prop, size) + 1; + if (*prop != 0) { + if (i++ == index) + return 0; + } + } + return -ENODEV; +} + +static struct dev_pm_domain omap_device_pm_domain; + +/** + * omap_device_build_from_dt - build an omap_device with multiple hwmods + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Function for building an omap_device already registered from device-tree + * + * Returns 0 or PTR_ERR() on error. + */ +static int omap_device_build_from_dt(struct platform_device *pdev) +{ + struct omap_hwmod **hwmods; + struct omap_device *od; + struct omap_hwmod *oh; + char oh_name[MAX_HWMOD_NAME_SIZE]; + const char *prop; + int oh_cnt, i, prop_len; + int ret = 0; + + prop = of_get_property(pdev-dev.of_node, hwmods, prop_len); I know you've posted it before, but what is the status of the hwmods binding documentation. I would expect it to be part of this patch. + oh_cnt = _dt_count_property_string(prop, prop_len); + if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) { + dev_warn(pdev-dev, No 'hwmods' to build omap_device\n); + return -ENODEV; + } + + hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + if (!hwmods) { + ret = -ENOMEM; + goto odbfd_exit; + } + + for (i = 0; i oh_cnt; i++) { + _dt_get_property(prop, prop_len, i, oh_name, + MAX_HWMOD_NAME_SIZE); + +
[PATCH v2 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
Add a notifier called during device_add phase. If an of_node is present, retrieve the hwmod entry in order to populate properly the omap_device structure. For the moment the resource from the device-tree are overloaded. DT does not support named resource yet, and thus, most driver will not work without that information. Add two helpers function to parse a property that contains multiple strings. Signed-off-by: Benoit Cousson b-cous...@ti.com Cc: Kevin Hilman khil...@ti.com --- arch/arm/plat-omap/omap_device.c | 144 ++ 1 files changed, 144 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index cac7b9a..da13630 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -85,6 +85,8 @@ #include linux/clk.h #include linux/clkdev.h #include linux/pm_runtime.h +#include linux/of.h +#include linux/notifier.h #include plat/omap_device.h #include plat/omap_hwmod.h @@ -94,12 +96,15 @@ #define USE_WAKEUP_LAT 0 #define IGNORE_WAKEUP_LAT 1 +#define MAX_HWMOD_NAME_SIZE32 + static int omap_device_register(struct platform_device *pdev); static int omap_early_device_register(struct platform_device *pdev); static struct omap_device *omap_device_alloc(struct platform_device *pdev, struct omap_hwmod **ohs, int oh_cnt, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt); +static void omap_device_delete(struct omap_device *od); static struct omap_device_pm_latency omap_default_latency[] = { @@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od, _add_clkdev(od, oh-opt_clks[i].role, oh-opt_clks[i].clk); } +/* + * XXX: DT helper functions that should probably move elsewhere if + * they become usefull for other needs. + */ +static int _dt_count_property_string(const char *prop, int len) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len = total; total += l, prop += l) { + l = strlen(prop) + 1; + if (*prop != 0) + i++; + } + return i; +} + +static int _dt_get_property(const char *prop, int len, int index, char *output, + int size) +{ + int i = 0; + size_t l = 0, total = 0; + + if (!prop || !len) + return -EINVAL; + + for (i = 0; len = total; total += l, prop += l) { + l = strlcpy(output, prop, size) + 1; + if (*prop != 0) { + if (i++ == index) + return 0; + } + } + return -ENODEV; +} + +static struct dev_pm_domain omap_device_pm_domain; + +/** + * omap_device_build_from_dt - build an omap_device with multiple hwmods + * @pdev_name: name of the platform_device driver to use + * @pdev_id: this platform_device's connection ID + * @oh: ptr to the single omap_hwmod that backs this omap_device + * @pdata: platform_data ptr to associate with the platform_device + * @pdata_len: amount of memory pointed to by @pdata + * @pm_lats: pointer to a omap_device_pm_latency array for this device + * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats + * @is_early_device: should the device be registered as an early device or not + * + * Function for building an omap_device already registered from device-tree + * + * Returns 0 or PTR_ERR() on error. + */ +static int omap_device_build_from_dt(struct platform_device *pdev) +{ + struct omap_hwmod **hwmods; + struct omap_device *od; + struct omap_hwmod *oh; + char oh_name[MAX_HWMOD_NAME_SIZE]; + const char *prop; + int oh_cnt, i, prop_len; + int ret = 0; + + prop = of_get_property(pdev-dev.of_node, hwmods, prop_len); + oh_cnt = _dt_count_property_string(prop, prop_len); + if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) { + dev_warn(pdev-dev, No 'hwmods' to build omap_device\n); + return -ENODEV; + } + + hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); + if (!hwmods) { + ret = -ENOMEM; + goto odbfd_exit; + } + + for (i = 0; i oh_cnt; i++) { + _dt_get_property(prop, prop_len, i, oh_name, +MAX_HWMOD_NAME_SIZE); + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + dev_err(pdev-dev, Cannot lookup hwmod '%s'\n, + oh_name); + ret = -EINVAL; + goto odbfd_exit1; + } + hwmods[i] = oh; + } + + od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0); + if (!od) { + dev_err(pdev-dev,