Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/samsung/exynos-acpm-dvfs.c
38189 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright 2020 Samsung Electronics Co., Ltd.
4
* Copyright 2020 Google LLC.
5
* Copyright 2025 Linaro Ltd.
6
*/
7
8
#include <linux/bitfield.h>
9
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
10
#include <linux/ktime.h>
11
#include <linux/types.h>
12
#include <linux/units.h>
13
14
#include "exynos-acpm.h"
15
#include "exynos-acpm-dvfs.h"
16
17
#define ACPM_DVFS_ID GENMASK(11, 0)
18
#define ACPM_DVFS_REQ_TYPE GENMASK(15, 0)
19
20
#define ACPM_DVFS_FREQ_REQ 0
21
#define ACPM_DVFS_FREQ_GET 1
22
23
static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
24
unsigned int acpm_chan_id, bool response)
25
{
26
xfer->acpm_chan_id = acpm_chan_id;
27
xfer->txd = cmd;
28
xfer->txlen = cmdlen;
29
30
if (response) {
31
xfer->rxd = cmd;
32
xfer->rxlen = cmdlen;
33
}
34
}
35
36
static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
37
unsigned long rate)
38
{
39
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
40
cmd[1] = rate / HZ_PER_KHZ;
41
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_REQ);
42
cmd[3] = ktime_to_ms(ktime_get());
43
}
44
45
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
46
unsigned int acpm_chan_id, unsigned int clk_id,
47
unsigned long rate)
48
{
49
struct acpm_xfer xfer = {0};
50
u32 cmd[4];
51
52
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
53
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
54
55
return acpm_do_xfer(handle, &xfer);
56
}
57
58
static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
59
{
60
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
61
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_GET);
62
cmd[3] = ktime_to_ms(ktime_get());
63
}
64
65
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
66
unsigned int acpm_chan_id, unsigned int clk_id)
67
{
68
struct acpm_xfer xfer;
69
unsigned int cmd[4] = {0};
70
int ret;
71
72
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
73
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
74
75
ret = acpm_do_xfer(handle, &xfer);
76
if (ret)
77
return 0;
78
79
return xfer.rxd[1] * HZ_PER_KHZ;
80
}
81
82