/** * omap_device_build_ss - build and register 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 * * Convenience function for building and registering an omap_device * subsystem record. Subsystem records consist of multiple * omap_hwmods. This function in turn builds and registers a * platform_device record. Returns an ERR_PTR() on error, or passes * along the return value of omap_device_register(). */ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, struct omap_hwmod **ohs, int oh_cnt, void *pdata, int pdata_len, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt, int is_early_device) { int ret = -ENOMEM; struct platform_device *pdev; struct omap_device *od; pr_debug("omap_device_build_ss: %s\n", pdev_name); if (!ohs || oh_cnt == 0 || !pdev_name) return ERR_PTR(-EINVAL); if (!pdata && pdata_len > 0) return ERR_PTR(-EINVAL); pdev = platform_device_alloc(pdev_name, pdev_id); if (!pdev) { ret = -ENOMEM; goto odbs_exit; } /* Set the dev_name early to allow dev_xxx in omap_device_alloc */ if (pdev->id != -1) dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); else dev_set_name(&pdev->dev, "%s", pdev->name); od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt); if (!od) goto odbs_exit1; ret = platform_device_add_data(pdev, pdata, pdata_len); if (ret) goto odbs_exit2; if (is_early_device) ret = omap_early_device_register(pdev); else ret = omap_device_register(pdev); if (ret) goto odbs_exit2; return pdev; odbs_exit2: omap_device_delete(od); odbs_exit1: platform_device_put(pdev); odbs_exit: pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); return ERR_PTR(ret); }
/** * omap_device_build_ss - build and register 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 * * Convenience function for building and registering an omap_device * subsystem record. Subsystem records consist of multiple * omap_hwmods. This function in turn builds and registers a * platform_device record. Returns an ERR_PTR() on error, or passes * along the return value of omap_device_register(). */ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, struct omap_hwmod **ohs, int oh_cnt, void *pdata, int pdata_len, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt, int is_early_device) { int ret = -ENOMEM; struct omap_device *od; char *pdev_name2; struct resource *res = NULL; int i, res_count; struct omap_hwmod **hwmods; if (!ohs || oh_cnt == 0 || !pdev_name) return ERR_PTR(-EINVAL); if (!pdata && pdata_len > 0) return ERR_PTR(-EINVAL); pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name, oh_cnt); od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); if (!od) return ERR_PTR(-ENOMEM); od->hwmods_cnt = oh_cnt; hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); if (!hwmods) goto odbs_exit1; memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt); od->hwmods = hwmods; pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL); if (!pdev_name2) goto odbs_exit2; strcpy(pdev_name2, pdev_name); od->pdev.name = pdev_name2; od->pdev.id = pdev_id; res_count = omap_device_count_resources(od); if (res_count > 0) { res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); if (!res) goto odbs_exit3; } omap_device_fill_resources(od, res); od->pdev.num_resources = res_count; od->pdev.resource = res; ret = platform_device_add_data(&od->pdev, pdata, pdata_len); if (ret) goto odbs_exit4; od->pm_lats = pm_lats; od->pm_lats_cnt = pm_lats_cnt; if (is_early_device) ret = omap_early_device_register(od); else ret = omap_device_register(od); for (i = 0; i < oh_cnt; i++) { hwmods[i]->od = od; _add_optional_clock_clkdev(od, hwmods[i]); } if (ret) goto odbs_exit4; return od; odbs_exit4: kfree(res); odbs_exit3: kfree(pdev_name2); odbs_exit2: kfree(hwmods); odbs_exit1: kfree(od); pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); return ERR_PTR(ret); }