|
@@ -966,3 +966,190 @@ int omap_device_idle(struct platform_device *pdev)
|
|
|
od->_state = OMAP_DEVICE_STATE_IDLE;
|
|
|
|
|
|
return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_shutdown - shut down an omap_device
|
|
|
+ * @od: struct omap_device * to shut down
|
|
|
+ *
|
|
|
+ * Shut down omap_device @od by calling all .deactivate_func() entries
|
|
|
+ * in the omap_device's pm_lats table and then shutting down all of
|
|
|
+ * the underlying omap_hwmods. Used when a device is being "removed"
|
|
|
+ * or a device driver is being unloaded. Returns -EINVAL if the
|
|
|
+ * omap_device is not currently enabled or idle, or passes along the
|
|
|
+ * return value of _omap_device_deactivate().
|
|
|
+ */
|
|
|
+int omap_device_shutdown(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ int ret, i;
|
|
|
+ struct omap_device *od;
|
|
|
+
|
|
|
+ od = to_omap_device(pdev);
|
|
|
+
|
|
|
+ if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
|
|
|
+ od->_state != OMAP_DEVICE_STATE_IDLE) {
|
|
|
+ dev_warn(&pdev->dev,
|
|
|
+ "omap_device: %s() called from invalid state %d\n",
|
|
|
+ __func__, od->_state);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ omap_hwmod_shutdown(od->hwmods[i]);
|
|
|
+
|
|
|
+ od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_assert_hardreset - set a device's hardreset line
|
|
|
+ * @pdev: struct platform_device * to reset
|
|
|
+ * @name: const char * name of the reset line
|
|
|
+ *
|
|
|
+ * Set the hardreset line identified by @name on the IP blocks
|
|
|
+ * associated with the hwmods backing the platform_device @pdev. All
|
|
|
+ * of the hwmods associated with @pdev must have the same hardreset
|
|
|
+ * line linked to them for this to work. Passes along the return value
|
|
|
+ * of omap_hwmod_assert_hardreset() in the event of any failure, or
|
|
|
+ * returns 0 upon success.
|
|
|
+ */
|
|
|
+int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
|
|
|
+{
|
|
|
+ struct omap_device *od = to_omap_device(pdev);
|
|
|
+ int ret = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++) {
|
|
|
+ ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_deassert_hardreset - release a device's hardreset line
|
|
|
+ * @pdev: struct platform_device * to reset
|
|
|
+ * @name: const char * name of the reset line
|
|
|
+ *
|
|
|
+ * Release the hardreset line identified by @name on the IP blocks
|
|
|
+ * associated with the hwmods backing the platform_device @pdev. All
|
|
|
+ * of the hwmods associated with @pdev must have the same hardreset
|
|
|
+ * line linked to them for this to work. Passes along the return
|
|
|
+ * value of omap_hwmod_deassert_hardreset() in the event of any
|
|
|
+ * failure, or returns 0 upon success.
|
|
|
+ */
|
|
|
+int omap_device_deassert_hardreset(struct platform_device *pdev,
|
|
|
+ const char *name)
|
|
|
+{
|
|
|
+ struct omap_device *od = to_omap_device(pdev);
|
|
|
+ int ret = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++) {
|
|
|
+ ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
|
|
|
+ if (ret)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
|
|
|
+ * @od: struct omap_device *
|
|
|
+ *
|
|
|
+ * When a device's maximum wakeup latency limit changes, call some of
|
|
|
+ * the .activate_func or .deactivate_func function pointers in the
|
|
|
+ * omap_device's pm_lats array to ensure that the device's maximum
|
|
|
+ * wakeup latency is less than or equal to the new latency limit.
|
|
|
+ * Intended to be called by OMAP PM code whenever a device's maximum
|
|
|
+ * wakeup latency limit changes (e.g., via
|
|
|
+ * omap_pm_set_dev_wakeup_lat()). Returns 0 if nothing needs to be
|
|
|
+ * done (e.g., if the omap_device is not currently idle, or if the
|
|
|
+ * wakeup latency is already current with the new limit) or passes
|
|
|
+ * along the return value of _omap_device_deactivate() or
|
|
|
+ * _omap_device_activate().
|
|
|
+ */
|
|
|
+int omap_device_align_pm_lat(struct platform_device *pdev,
|
|
|
+ u32 new_wakeup_lat_limit)
|
|
|
+{
|
|
|
+ int ret = -EINVAL;
|
|
|
+ struct omap_device *od;
|
|
|
+
|
|
|
+ od = to_omap_device(pdev);
|
|
|
+
|
|
|
+ if (new_wakeup_lat_limit == od->dev_wakeup_lat)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ od->_dev_wakeup_lat_limit = new_wakeup_lat_limit;
|
|
|
+
|
|
|
+ if (od->_state != OMAP_DEVICE_STATE_IDLE)
|
|
|
+ return 0;
|
|
|
+ else if (new_wakeup_lat_limit > od->dev_wakeup_lat)
|
|
|
+ ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
|
|
|
+ else if (new_wakeup_lat_limit < od->dev_wakeup_lat)
|
|
|
+ ret = _omap_device_activate(od, USE_WAKEUP_LAT);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_get_pwrdm - return the powerdomain * associated with @od
|
|
|
+ * @od: struct omap_device *
|
|
|
+ *
|
|
|
+ * Return the powerdomain associated with the first underlying
|
|
|
+ * omap_hwmod for this omap_device. Intended for use by core OMAP PM
|
|
|
+ * code. Returns NULL on error or a struct powerdomain * upon
|
|
|
+ * success.
|
|
|
+ */
|
|
|
+struct powerdomain *omap_device_get_pwrdm(struct omap_device *od)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * XXX Assumes that all omap_hwmod powerdomains are identical.
|
|
|
+ * This may not necessarily be true. There should be a sanity
|
|
|
+ * check in here to WARN() if any difference appears.
|
|
|
+ */
|
|
|
+ if (!od->hwmods_cnt)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return omap_hwmod_get_pwrdm(od->hwmods[0]);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base
|
|
|
+ * @od: struct omap_device *
|
|
|
+ *
|
|
|
+ * Return the MPU's virtual address for the base of the hwmod, from
|
|
|
+ * the ioremap() that the hwmod code does. Only valid if there is one
|
|
|
+ * hwmod associated with this device. Returns NULL if there are zero
|
|
|
+ * or more than one hwmods associated with this omap_device;
|
|
|
+ * otherwise, passes along the return value from
|
|
|
+ * omap_hwmod_get_mpu_rt_va().
|
|
|
+ */
|
|
|
+void __iomem *omap_device_get_rt_va(struct omap_device *od)
|
|
|
+{
|
|
|
+ if (od->hwmods_cnt != 1)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_get_by_hwmod_name() - convert a hwmod name to
|
|
|
+ * device pointer.
|
|
|
+ * @oh_name: name of the hwmod device
|
|
|
+ *
|
|
|
+ * Returns back a struct device * pointer associated with a hwmod
|
|
|
+ * device represented by a hwmod_name
|
|
|
+ */
|
|
|
+struct device *omap_device_get_by_hwmod_name(const char *oh_name)
|
|
|
+{
|
|
|
+ struct omap_hwmod *oh;
|
|
|
+
|
|
|
+ if (!oh_name) {
|
|
|
+ WARN(1, "%s: no hwmod name!\n", __func__);
|