uboot/drivers/clk/clk_scmi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019-2020 Linaro Limited
   4 */
   5#include <common.h>
   6#include <clk-uclass.h>
   7#include <dm.h>
   8#include <scmi_agent.h>
   9#include <scmi_protocols.h>
  10#include <asm/types.h>
  11
  12static int scmi_clk_gate(struct clk *clk, int enable)
  13{
  14        struct scmi_clk_state_in in = {
  15                .clock_id = clk->id,
  16                .attributes = enable,
  17        };
  18        struct scmi_clk_state_out out;
  19        struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
  20                                          SCMI_CLOCK_CONFIG_SET,
  21                                          in, out);
  22        int ret;
  23
  24        ret = devm_scmi_process_msg(clk->dev->parent, &msg);
  25        if (ret)
  26                return ret;
  27
  28        return scmi_to_linux_errno(out.status);
  29}
  30
  31static int scmi_clk_enable(struct clk *clk)
  32{
  33        return scmi_clk_gate(clk, 1);
  34}
  35
  36static int scmi_clk_disable(struct clk *clk)
  37{
  38        return scmi_clk_gate(clk, 0);
  39}
  40
  41static ulong scmi_clk_get_rate(struct clk *clk)
  42{
  43        struct scmi_clk_rate_get_in in = {
  44                .clock_id = clk->id,
  45        };
  46        struct scmi_clk_rate_get_out out;
  47        struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
  48                                          SCMI_CLOCK_RATE_GET,
  49                                          in, out);
  50        int ret;
  51
  52        ret = devm_scmi_process_msg(clk->dev->parent, &msg);
  53        if (ret < 0)
  54                return ret;
  55
  56        ret = scmi_to_linux_errno(out.status);
  57        if (ret < 0)
  58                return ret;
  59
  60        return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb);
  61}
  62
  63static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
  64{
  65        struct scmi_clk_rate_set_in in = {
  66                .clock_id = clk->id,
  67                .flags = SCMI_CLK_RATE_ROUND_CLOSEST,
  68                .rate_lsb = (u32)rate,
  69                .rate_msb = (u32)((u64)rate >> 32),
  70        };
  71        struct scmi_clk_rate_set_out out;
  72        struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
  73                                          SCMI_CLOCK_RATE_SET,
  74                                          in, out);
  75        int ret;
  76
  77        ret = devm_scmi_process_msg(clk->dev->parent, &msg);
  78        if (ret < 0)
  79                return ret;
  80
  81        ret = scmi_to_linux_errno(out.status);
  82        if (ret < 0)
  83                return ret;
  84
  85        return scmi_clk_get_rate(clk);
  86}
  87
  88static const struct clk_ops scmi_clk_ops = {
  89        .enable = scmi_clk_enable,
  90        .disable = scmi_clk_disable,
  91        .get_rate = scmi_clk_get_rate,
  92        .set_rate = scmi_clk_set_rate,
  93};
  94
  95U_BOOT_DRIVER(scmi_clock) = {
  96        .name = "scmi_clk",
  97        .id = UCLASS_CLK,
  98        .ops = &scmi_clk_ops,
  99};
 100