mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Struct acpm_xfer holds two buffers with u32 commands - rxd and txd - and counts their size by rxlen and txlen. "len" suffix is here ambiguous, so could mean length of the buffer or length of commands, and these are not the same since each command is u32. Rename these to rxcnt and txcnt, and change their usage to count the number of commands in each buffer. This will have a benefit of allowing to use __counted_by_ptr later. Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org> Link: https://patch.msgid.link/20260219-firmare-acpm-counted-v2-2-e1f7389237d3@oss.qualcomm.com Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
82 lines
2.0 KiB
C
82 lines
2.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright 2020 Samsung Electronics Co., Ltd.
|
|
* Copyright 2020 Google LLC.
|
|
* Copyright 2025 Linaro Ltd.
|
|
*/
|
|
|
|
#include <linux/array_size.h>
|
|
#include <linux/bitfield.h>
|
|
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
|
|
#include <linux/ktime.h>
|
|
#include <linux/types.h>
|
|
#include <linux/units.h>
|
|
|
|
#include "exynos-acpm.h"
|
|
#include "exynos-acpm-dvfs.h"
|
|
|
|
#define ACPM_DVFS_ID GENMASK(11, 0)
|
|
#define ACPM_DVFS_REQ_TYPE GENMASK(15, 0)
|
|
|
|
#define ACPM_DVFS_FREQ_REQ 0
|
|
#define ACPM_DVFS_FREQ_GET 1
|
|
|
|
static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
|
|
unsigned int acpm_chan_id, bool response)
|
|
{
|
|
xfer->acpm_chan_id = acpm_chan_id;
|
|
xfer->txd = cmd;
|
|
xfer->txcnt = cmdlen;
|
|
|
|
if (response) {
|
|
xfer->rxd = cmd;
|
|
xfer->rxcnt = cmdlen;
|
|
}
|
|
}
|
|
|
|
static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
|
|
unsigned long rate)
|
|
{
|
|
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
|
|
cmd[1] = rate / HZ_PER_KHZ;
|
|
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_REQ);
|
|
cmd[3] = ktime_to_ms(ktime_get());
|
|
}
|
|
|
|
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
|
|
unsigned int acpm_chan_id, unsigned int clk_id,
|
|
unsigned long rate)
|
|
{
|
|
struct acpm_xfer xfer = {0};
|
|
u32 cmd[4];
|
|
|
|
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
|
|
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, false);
|
|
|
|
return acpm_do_xfer(handle, &xfer);
|
|
}
|
|
|
|
static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
|
|
{
|
|
cmd[0] = FIELD_PREP(ACPM_DVFS_ID, clk_id);
|
|
cmd[2] = FIELD_PREP(ACPM_DVFS_REQ_TYPE, ACPM_DVFS_FREQ_GET);
|
|
cmd[3] = ktime_to_ms(ktime_get());
|
|
}
|
|
|
|
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
|
|
unsigned int acpm_chan_id, unsigned int clk_id)
|
|
{
|
|
struct acpm_xfer xfer;
|
|
unsigned int cmd[4] = {0};
|
|
int ret;
|
|
|
|
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
|
|
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, true);
|
|
|
|
ret = acpm_do_xfer(handle, &xfer);
|
|
if (ret)
|
|
return 0;
|
|
|
|
return xfer.rxd[1] * HZ_PER_KHZ;
|
|
}
|