|
@@ -1153,3 +1153,148 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name)
|
|
|
|
|
|
if (!oh_name) {
|
|
|
WARN(1, "%s: no hwmod name!\n", __func__);
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ oh = omap_hwmod_lookup(oh_name);
|
|
|
+ if (IS_ERR_OR_NULL(oh)) {
|
|
|
+ WARN(1, "%s: no hwmod for %s\n", __func__,
|
|
|
+ oh_name);
|
|
|
+ return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
|
|
|
+ }
|
|
|
+ if (IS_ERR_OR_NULL(oh->od)) {
|
|
|
+ WARN(1, "%s: no omap_device for %s\n", __func__,
|
|
|
+ oh_name);
|
|
|
+ return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IS_ERR_OR_NULL(oh->od->pdev))
|
|
|
+ return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
|
|
|
+
|
|
|
+ return &oh->od->pdev->dev;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
|
|
|
+
|
|
|
+/*
|
|
|
+ * Public functions intended for use in omap_device_pm_latency
|
|
|
+ * .activate_func and .deactivate_func function pointers
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
|
|
|
+ * @od: struct omap_device *od
|
|
|
+ *
|
|
|
+ * Enable all underlying hwmods. Returns 0.
|
|
|
+ */
|
|
|
+int omap_device_enable_hwmods(struct omap_device *od)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ omap_hwmod_enable(od->hwmods[i]);
|
|
|
+
|
|
|
+ /* XXX pass along return value here? */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
|
|
|
+ * @od: struct omap_device *od
|
|
|
+ *
|
|
|
+ * Idle all underlying hwmods. Returns 0.
|
|
|
+ */
|
|
|
+int omap_device_idle_hwmods(struct omap_device *od)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ omap_hwmod_idle(od->hwmods[i]);
|
|
|
+
|
|
|
+ /* XXX pass along return value here? */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_disable_clocks - disable all main and interface clocks
|
|
|
+ * @od: struct omap_device *od
|
|
|
+ *
|
|
|
+ * Disable the main functional clock and interface clock for all of the
|
|
|
+ * omap_hwmods associated with the omap_device. Returns 0.
|
|
|
+ */
|
|
|
+int omap_device_disable_clocks(struct omap_device *od)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ omap_hwmod_disable_clocks(od->hwmods[i]);
|
|
|
+
|
|
|
+ /* XXX pass along return value here? */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_enable_clocks - enable all main and interface clocks
|
|
|
+ * @od: struct omap_device *od
|
|
|
+ *
|
|
|
+ * Enable the main functional clock and interface clock for all of the
|
|
|
+ * omap_hwmods associated with the omap_device. Returns 0.
|
|
|
+ */
|
|
|
+int omap_device_enable_clocks(struct omap_device *od)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < od->hwmods_cnt; i++)
|
|
|
+ omap_hwmod_enable_clocks(od->hwmods[i]);
|
|
|
+
|
|
|
+ /* XXX pass along return value here? */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block platform_nb = {
|
|
|
+ .notifier_call = _omap_device_notifier_call,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init omap_device_init(void)
|
|
|
+{
|
|
|
+ bus_register_notifier(&platform_bus_type, &platform_nb);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+core_initcall(omap_device_init);
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap_device_late_idle - idle devices without drivers
|
|
|
+ * @dev: struct device * associated with omap_device
|
|
|
+ * @data: unused
|
|
|
+ *
|
|
|
+ * Check the driver bound status of this device, and idle it
|
|
|
+ * if there is no driver attached.
|
|
|
+ */
|
|
|
+static int __init omap_device_late_idle(struct device *dev, void *data)
|
|
|
+{
|
|
|
+ struct platform_device *pdev = to_platform_device(dev);
|
|
|
+ struct omap_device *od = to_omap_device(pdev);
|
|
|
+
|
|
|
+ if (!od)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If omap_device state is enabled, but has no driver bound,
|
|
|
+ * idle it.
|
|
|
+ */
|
|
|
+ if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
|
|
|
+ if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
|
|
|
+ dev_warn(dev, "%s: enabled but no driver. Idling\n",
|
|
|
+ __func__);
|
|
|
+ omap_device_idle(pdev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init omap_device_late_init(void)
|
|
|
+{
|
|
|
+ bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+late_initcall(omap_device_late_init);
|