|
@@ -368,3 +368,168 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
|
|
pac_exit:
|
|
pac_exit:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
|
|
|
|
+ * @pwrdm: struct powerdomain * to add the clockdomain to
|
|
|
|
+ * @clkdm: struct clockdomain * to associate with a powerdomain
|
|
|
|
+ *
|
|
|
|
+ * Dissociate the clockdomain @clkdm from the powerdomain
|
|
|
|
+ * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT
|
|
|
|
+ * if @clkdm was not associated with the powerdomain, or 0 upon
|
|
|
|
+ * success.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
|
|
|
|
+{
|
|
|
|
+ int ret = -EINVAL;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (!pwrdm || !clkdm)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ pr_debug("powerdomain: %s: dissociating clockdomain %s\n",
|
|
|
|
+ pwrdm->name, clkdm->name);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
|
|
|
|
+ if (pwrdm->pwrdm_clkdms[i] == clkdm)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ if (i == PWRDM_MAX_CLKDMS) {
|
|
|
|
+ pr_debug("powerdomain: %s: clkdm %s not associated?!\n",
|
|
|
|
+ pwrdm->name, clkdm->name);
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
+ goto pdc_exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pwrdm->pwrdm_clkdms[i] = NULL;
|
|
|
|
+
|
|
|
|
+ ret = 0;
|
|
|
|
+
|
|
|
|
+pdc_exit:
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
|
|
|
|
+ * @pwrdm: struct powerdomain * to iterate over
|
|
|
|
+ * @fn: callback function *
|
|
|
|
+ *
|
|
|
|
+ * Call the supplied function @fn for each clockdomain in the powerdomain
|
|
|
|
+ * @pwrdm. The callback function can return anything but 0 to bail
|
|
|
|
+ * out early from the iterator. Returns -EINVAL if presented with
|
|
|
|
+ * invalid pointers; or passes along the last return value of the
|
|
|
|
+ * callback function, which should be 0 for success or anything else
|
|
|
|
+ * to indicate failure.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
|
|
|
|
+ int (*fn)(struct powerdomain *pwrdm,
|
|
|
|
+ struct clockdomain *clkdm))
|
|
|
|
+{
|
|
|
|
+ int ret = 0;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (!fn)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
|
|
|
|
+ ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in
|
|
|
|
+ * @pwrdm: struct powerdomain *
|
|
|
|
+ *
|
|
|
|
+ * Return a pointer to the struct voltageomain that the specified powerdomain
|
|
|
|
+ * @pwrdm exists in.
|
|
|
|
+ */
|
|
|
|
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ return pwrdm->voltdm.ptr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
|
|
|
|
+ * @pwrdm: struct powerdomain *
|
|
|
|
+ *
|
|
|
|
+ * Return the number of controllable memory banks in powerdomain @pwrdm,
|
|
|
|
+ * starting with 1. Returns -EINVAL if the powerdomain pointer is null.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ if (!pwrdm)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return pwrdm->banks;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_set_next_pwrst - set next powerdomain power state
|
|
|
|
+ * @pwrdm: struct powerdomain * to set
|
|
|
|
+ * @pwrst: one of the PWRDM_POWER_* macros
|
|
|
|
+ *
|
|
|
|
+ * Set the powerdomain @pwrdm's next power state to @pwrst. The powerdomain
|
|
|
|
+ * may not enter this state immediately if the preconditions for this state
|
|
|
|
+ * have not been satisfied. Returns -EINVAL if the powerdomain pointer is
|
|
|
|
+ * null or if the power state is invalid for the powerdomin, or returns 0
|
|
|
|
+ * upon success.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
|
|
+{
|
|
|
|
+ int ret = -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (!pwrdm)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (!(pwrdm->pwrsts & (1 << pwrst)))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ pr_debug("powerdomain: %s: setting next powerstate to %0x\n",
|
|
|
|
+ pwrdm->name, pwrst);
|
|
|
|
+
|
|
|
|
+ if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
|
|
|
|
+ /* Trace the pwrdm desired target state */
|
|
|
|
+ trace_power_domain_target(pwrdm->name, pwrst,
|
|
|
|
+ smp_processor_id());
|
|
|
|
+ /* Program the pwrdm desired target state */
|
|
|
|
+ ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_read_next_pwrst - get next powerdomain power state
|
|
|
|
+ * @pwrdm: struct powerdomain * to get power state
|
|
|
|
+ *
|
|
|
|
+ * Return the powerdomain @pwrdm's next power state. Returns -EINVAL
|
|
|
|
+ * if the powerdomain pointer is null or returns the next power state
|
|
|
|
+ * upon success.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ int ret = -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (!pwrdm)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
|
|
|
|
+ ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * pwrdm_read_pwrst - get current powerdomain power state
|
|
|
|
+ * @pwrdm: struct powerdomain * to get power state
|
|
|
|
+ *
|
|
|
|
+ * Return the powerdomain @pwrdm's current power state. Returns -EINVAL
|
|
|
|
+ * if the powerdomain pointer is null or returns the current power state
|
|
|
|
+ * upon success. Note that if the power domain only supports the ON state
|
|
|
|
+ * then just return ON as the current state.
|
|
|
|
+ */
|
|
|
|
+int pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
|
|
+{
|
|
|
|
+ int ret = -EINVAL;
|
|
|
|
+
|