Merge branch 'sh/smp'
[pandora-kernel.git] / arch / arm / plat-omap / omap_device.c
index 2ed7201..0f51974 100644 (file)
@@ -79,6 +79,7 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
 
@@ -90,6 +91,8 @@
 #define IGNORE_WAKEUP_LAT              1
 
 
+#define OMAP_DEVICE_MAGIC 0xf00dcafe
+
 /* Private functions */
 
 /**
@@ -138,10 +141,22 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
                         "%llu nsec\n", od->pdev.name, od->pm_lat_level,
                         act_lat);
 
-               WARN(act_lat > odpl->activate_lat, "omap_device: %s.%d: "
-                    "activate step %d took longer than expected (%llu > %d)\n",
-                    od->pdev.name, od->pdev.id, od->pm_lat_level,
-                    act_lat, odpl->activate_lat);
+               if (act_lat > odpl->activate_lat) {
+                       odpl->activate_lat_worst = act_lat;
+                       if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
+                               odpl->activate_lat = act_lat;
+                               pr_warning("omap_device: %s.%d: new worst case "
+                                          "activate latency %d: %llu\n",
+                                          od->pdev.name, od->pdev.id,
+                                          od->pm_lat_level, act_lat);
+                       } else
+                               pr_warning("omap_device: %s.%d: activate "
+                                          "latency %d higher than exptected. "
+                                          "(%llu > %d)\n",
+                                          od->pdev.name, od->pdev.id,
+                                          od->pm_lat_level, act_lat,
+                                          odpl->activate_lat);
+               }
 
                od->dev_wakeup_lat -= odpl->activate_lat;
        }
@@ -194,10 +209,23 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
                         "%llu nsec\n", od->pdev.name, od->pm_lat_level,
                         deact_lat);
 
-               WARN(deact_lat > odpl->deactivate_lat, "omap_device: %s.%d: "
-                    "deactivate step %d took longer than expected "
-                    "(%llu > %d)\n", od->pdev.name, od->pdev.id,
-                    od->pm_lat_level, deact_lat, odpl->deactivate_lat);
+               if (deact_lat > odpl->deactivate_lat) {
+                       odpl->deactivate_lat_worst = deact_lat;
+                       if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
+                               odpl->deactivate_lat = deact_lat;
+                               pr_warning("omap_device: %s.%d: new worst case "
+                                          "deactivate latency %d: %llu\n",
+                                          od->pdev.name, od->pdev.id,
+                                          od->pm_lat_level, deact_lat);
+                       } else
+                               pr_warning("omap_device: %s.%d: deactivate "
+                                          "latency %d higher than exptected. "
+                                          "(%llu > %d)\n",
+                                          od->pdev.name, od->pdev.id,
+                                          od->pm_lat_level, deact_lat,
+                                          odpl->deactivate_lat);
+               }
+
 
                od->dev_wakeup_lat += odpl->activate_lat;
 
@@ -280,6 +308,7 @@ int omap_device_fill_resources(struct omap_device *od, struct resource *res)
  * @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 a single
  * omap_device record, which in turn builds and registers a
@@ -291,7 +320,7 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
                                      struct omap_hwmod *oh, void *pdata,
                                      int pdata_len,
                                      struct omap_device_pm_latency *pm_lats,
-                                     int pm_lats_cnt)
+                                     int pm_lats_cnt, int is_early_device)
 {
        struct omap_hwmod *ohs[] = { oh };
 
@@ -299,7 +328,8 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
                return ERR_PTR(-EINVAL);
 
        return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
-                                   pdata_len, pm_lats, pm_lats_cnt);
+                                   pdata_len, pm_lats, pm_lats_cnt,
+                                   is_early_device);
 }
 
 /**
@@ -311,6 +341,7 @@ struct omap_device *omap_device_build(const char *pdev_name, int pdev_id,
  * @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
@@ -322,7 +353,7 @@ 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 pm_lats_cnt, int is_early_device)
 {
        int ret = -ENOMEM;
        struct omap_device *od;
@@ -378,7 +409,13 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
        od->pm_lats = pm_lats;
        od->pm_lats_cnt = pm_lats_cnt;
 
-       ret = omap_device_register(od);
+       od->magic = OMAP_DEVICE_MAGIC;
+
+       if (is_early_device)
+               ret = omap_early_device_register(od);
+       else
+               ret = omap_device_register(od);
+
        if (ret)
                goto odbs_exit4;
 
@@ -398,6 +435,24 @@ odbs_exit1:
        return ERR_PTR(ret);
 }
 
+/**
+ * omap_early_device_register - register an omap_device as an early platform
+ * device.
+ * @od: struct omap_device * to register
+ *
+ * Register the omap_device structure.  This currently just calls
+ * platform_early_add_device() on the underlying platform_device.
+ * Returns 0 by default.
+ */
+int omap_early_device_register(struct omap_device *od)
+{
+       struct platform_device *devices[1];
+
+       devices[0] = &(od->pdev);
+       early_platform_add_devices(devices, 1);
+       return 0;
+}
+
 /**
  * omap_device_register - register an omap_device with one omap_hwmod
  * @od: struct omap_device * to register
@@ -437,8 +492,8 @@ int omap_device_enable(struct platform_device *pdev)
        od = _find_by_pdev(pdev);
 
        if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
-               WARN(1, "omap_device: %s.%d: omap_device_enable() called from "
-                    "invalid state\n", od->pdev.name, od->pdev.id);
+               WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
+                    od->pdev.name, od->pdev.id, __func__, od->_state);
                return -EINVAL;
        }
 
@@ -476,8 +531,8 @@ int omap_device_idle(struct platform_device *pdev)
        od = _find_by_pdev(pdev);
 
        if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
-               WARN(1, "omap_device: %s.%d: omap_device_idle() called from "
-                    "invalid state\n", od->pdev.name, od->pdev.id);
+               WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
+                    od->pdev.name, od->pdev.id, __func__, od->_state);
                return -EINVAL;
        }
 
@@ -509,8 +564,8 @@ int omap_device_shutdown(struct platform_device *pdev)
 
        if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
            od->_state != OMAP_DEVICE_STATE_IDLE) {
-               WARN(1, "omap_device: %s.%d: omap_device_shutdown() called "
-                    "from invalid state\n", od->pdev.name, od->pdev.id);
+               WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
+                    od->pdev.name, od->pdev.id, __func__, od->_state);
                return -EINVAL;
        }
 
@@ -563,6 +618,18 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
        return ret;
 }
 
+/**
+ * omap_device_is_valid - Check if pointer is a valid omap_device
+ * @od: struct omap_device *
+ *
+ * Return whether struct omap_device pointer @od points to a valid
+ * omap_device.
+ */
+bool omap_device_is_valid(struct omap_device *od)
+{
+       return (od && od->magic == OMAP_DEVICE_MAGIC);
+}
+
 /**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *