Merge tag 'for-5.6-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / firmware / arm_scmi / clock.c
index 0a194af..4c22276 100644 (file)
@@ -56,7 +56,7 @@ struct scmi_msg_resp_clock_describe_rates {
 struct scmi_clock_set_rate {
        __le32 flags;
 #define CLOCK_SET_ASYNC                BIT(0)
-#define CLOCK_SET_DELAYED      BIT(1)
+#define CLOCK_SET_IGNORE_RESP  BIT(1)
 #define CLOCK_SET_ROUND_UP     BIT(2)
 #define CLOCK_SET_ROUND_AUTO   BIT(3)
        __le32 id;
@@ -65,8 +65,10 @@ struct scmi_clock_set_rate {
 };
 
 struct clock_info {
+       u32 version;
        int num_clocks;
        int max_async_req;
+       atomic_t cur_async_req;
        struct scmi_clock_info *clk;
 };
 
@@ -106,7 +108,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle,
        if (ret)
                return ret;
 
-       *(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+       put_unaligned_le32(clk_id, t->tx.buf);
        attr = t->rx.buf;
 
        ret = scmi_do_xfer(handle, t);
@@ -203,39 +205,47 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
        if (ret)
                return ret;
 
-       *(__le32 *)t->tx.buf = cpu_to_le32(clk_id);
+       put_unaligned_le32(clk_id, t->tx.buf);
 
        ret = scmi_do_xfer(handle, t);
-       if (!ret) {
-               __le32 *pval = t->rx.buf;
-
-               *value = le32_to_cpu(*pval);
-               *value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
-       }
+       if (!ret)
+               *value = get_unaligned_le64(t->rx.buf);
 
        scmi_xfer_put(handle, t);
        return ret;
 }
 
 static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
-                              u32 config, u64 rate)
+                              u64 rate)
 {
        int ret;
+       u32 flags = 0;
        struct scmi_xfer *t;
        struct scmi_clock_set_rate *cfg;
+       struct clock_info *ci = handle->clk_priv;
 
        ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
                                 sizeof(*cfg), 0, &t);
        if (ret)
                return ret;
 
+       if (ci->max_async_req &&
+           atomic_inc_return(&ci->cur_async_req) < ci->max_async_req)
+               flags |= CLOCK_SET_ASYNC;
+
        cfg = t->tx.buf;
-       cfg->flags = cpu_to_le32(config);
+       cfg->flags = cpu_to_le32(flags);
        cfg->id = cpu_to_le32(clk_id);
        cfg->value_low = cpu_to_le32(rate & 0xffffffff);
        cfg->value_high = cpu_to_le32(rate >> 32);
 
-       ret = scmi_do_xfer(handle, t);
+       if (flags & CLOCK_SET_ASYNC)
+               ret = scmi_do_xfer_with_response(handle, t);
+       else
+               ret = scmi_do_xfer(handle, t);
+
+       if (ci->max_async_req)
+               atomic_dec(&ci->cur_async_req);
 
        scmi_xfer_put(handle, t);
        return ret;
@@ -331,6 +341,7 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle)
                        scmi_clock_describe_rates_get(handle, clkid, clk);
        }
 
+       cinfo->version = version;
        handle->clk_ops = &clk_ops;
        handle->clk_priv = cinfo;