|
@@ -431,3 +431,181 @@ int omap_device_get_context_loss_count(struct platform_device *pdev)
|
|
|
u32 ret = 0;
|
|
|
|
|
|
od = to_omap_device(pdev);
|
|
|
+
|
|
|
+ if (od->hwmods_cnt)
|
|
|
+ ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_count_resources - count number of struct resource entries needed
|
|
|
+ * @od: struct omap_device *
|
|
|
+ * @flags: Type of resources to include when counting (IRQ/DMA/MEM)
|
|
|
+ *
|
|
|
+ * Count the number of struct resource entries needed for this
|
|
|
+ * omap_device @od. Used by omap_device_build_ss() to determine how
|
|
|
+ * much memory to allocate before calling
|
|
|
+ * omap_device_fill_resources(). Returns the count.
|
|
|
+ */
|
|
|
+static int omap_device_count_resources(struct omap_device *od,
|
|
|
+ unsigned long flags)
|
|
|
+{
|
|
|
+ int c = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ c += omap_hwmod_count_resources(od->hwmods[i], flags);
|
|
|
+
|
|
|
+ pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
|
|
|
+ od->pdev->name, c, od->hwmods_cnt);
|
|
|
+
|
|
|
+ return c;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_fill_resources - fill in array of struct resource
|
|
|
+ * @od: struct omap_device *
|
|
|
+ * @res: pointer to an array of struct resource to be filled in
|
|
|
+ *
|
|
|
+ * Populate one or more empty struct resource pointed to by @res with
|
|
|
+ * the resource data for this omap_device @od. Used by
|
|
|
+ * omap_device_build_ss() after calling omap_device_count_resources().
|
|
|
+ * Ideally this function would not be needed at all. If omap_device
|
|
|
+ * replaces platform_device, then we can specify our own
|
|
|
+ * get_resource()/ get_irq()/etc functions that use the underlying
|
|
|
+ * omap_hwmod information. Or if platform_device is extended to use
|
|
|
+ * subarchitecture-specific function pointers, the various
|
|
|
+ * platform_device functions can simply call omap_device internal
|
|
|
+ * functions to get device resources. Hacking around the existing
|
|
|
+ * platform_device code wastes memory. Returns 0.
|
|
|
+ */
|
|
|
+static int omap_device_fill_resources(struct omap_device *od,
|
|
|
+ struct resource *res)
|
|
|
+{
|
|
|
+ int i, r;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++) {
|
|
|
+ r = omap_hwmod_fill_resources(od->hwmods[i], res);
|
|
|
+ res += r;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * _od_fill_dma_resources - fill in array of struct resource with dma resources
|
|
|
+ * @od: struct omap_device *
|
|
|
+ * @res: pointer to an array of struct resource to be filled in
|
|
|
+ *
|
|
|
+ * Populate one or more empty struct resource pointed to by @res with
|
|
|
+ * the dma resource data for this omap_device @od. Used by
|
|
|
+ * omap_device_alloc() after calling omap_device_count_resources().
|
|
|
+ *
|
|
|
+ * Ideally this function would not be needed at all. If we have
|
|
|
+ * mechanism to get dma resources from DT.
|
|
|
+ *
|
|
|
+ * Returns 0.
|
|
|
+ */
|
|
|
+static int _od_fill_dma_resources(struct omap_device *od,
|
|
|
+ struct resource *res)
|
|
|
+{
|
|
|
+ int i, r;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++) {
|
|
|
+ r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
|
|
|
+ res += r;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_alloc - allocate an omap_device
|
|
|
+ * @pdev: platform_device that will be included in this omap_device
|
|
|
+ * @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
|
|
|
+ *
|
|
|
+ * Convenience function for allocating an omap_device structure and filling
|
|
|
+ * hwmods, resources and pm_latency attributes.
|
|
|
+ *
|
|
|
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
|
|
|
+ */
|
|
|
+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)
|
|
|
+{
|
|
|
+ int ret = -ENOMEM;
|
|
|
+ struct omap_device *od;
|
|
|
+ struct resource *res = NULL;
|
|
|
+ int i, res_count;
|
|
|
+ struct omap_hwmod **hwmods;
|
|
|
+
|
|
|
+ od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
|
|
|
+ if (!od) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto oda_exit1;
|
|
|
+ }
|
|
|
+ od->hwmods_cnt = oh_cnt;
|
|
|
+
|
|
|
+ hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
|
|
|
+ if (!hwmods)
|
|
|
+ goto oda_exit2;
|
|
|
+
|
|
|
+ od->hwmods = hwmods;
|
|
|
+ od->pdev = pdev;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Non-DT Boot:
|
|
|
+ * Here, pdev->num_resources = 0, and we should get all the
|
|
|
+ * resources from hwmod.
|
|
|
+ *
|
|
|
+ * DT Boot:
|
|
|
+ * OF framework will construct the resource structure (currently
|
|
|
+ * does for MEM & IRQ resource) and we should respect/use these
|
|
|
+ * resources, killing hwmod dependency.
|
|
|
+ * If pdev->num_resources > 0, we assume that MEM & IRQ resources
|
|
|
+ * have been allocated by OF layer already (through DTB).
|
|
|
+ * As preparation for the future we examine the OF provided resources
|
|
|
+ * to see if we have DMA resources provided already. In this case
|
|
|
+ * there is no need to update the resources for the device, we use the
|
|
|
+ * OF provided ones.
|
|
|
+ *
|
|
|
+ * TODO: Once DMA resource is available from OF layer, we should
|
|
|
+ * kill filling any resources from hwmod.
|
|
|
+ */
|
|
|
+ if (!pdev->num_resources) {
|
|
|
+ /* Count all resources for the device */
|
|
|
+ res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
|
|
|
+ IORESOURCE_DMA |
|
|
|
+ IORESOURCE_MEM);
|
|
|
+ } else {
|
|
|
+ /* Take a look if we already have DMA resource via DT */
|
|
|
+ for (i = 0; i < pdev->num_resources; i++) {
|
|
|
+ struct resource *r = &pdev->resource[i];
|
|
|
+
|
|
|
+ /* We have it, no need to touch the resources */
|
|
|
+ if (r->flags == IORESOURCE_DMA)
|
|
|
+ goto have_everything;
|
|
|
+ }
|
|
|
+ /* Count only DMA resources for the device */
|
|
|
+ res_count = omap_device_count_resources(od, IORESOURCE_DMA);
|
|
|
+ /* The device has no DMA resource, no need for update */
|
|
|
+ if (!res_count)
|
|
|
+ goto have_everything;
|
|
|
+
|
|
|
+ res_count += pdev->num_resources;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Allocate resources memory to account for new resources */
|
|
|
+ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
|
|
|
+ if (!res)
|
|
|
+ goto oda_exit3;
|
|
|
+
|
|
|
+ if (!pdev->num_resources) {
|
|
|
+ dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
|
|
|
+ __func__, res_count);
|