blob: 5f405d5cf50de321c2bf1e98999cdedf1c0d699a [file] [log] [blame]
Caleb Connollyceb92622023-09-26 17:12:13 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/bug.h>
7#include <linux/kernel.h>
8#include <linux/list.h>
9#include <linux/types.h>
10#include <dm/device.h>
11
12#include <soc/qcom/rpmh.h>
13
14#include "rpmh-internal.h"
15
16#define RPMH_TIMEOUT_MS msecs_to_jiffies(10000)
17
18#define DEFINE_RPMH_MSG_ONSTACK(device, s, name) \
19 struct rpmh_request name = { \
20 .msg = { \
21 .state = s, \
22 .cmds = name.cmd, \
23 .num_cmds = 0, \
24 }, \
25 .cmd = { { 0 } }, \
26 .dev = device, \
27 .needs_free = false, \
28 }
29
30#define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
31
32static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct udevice *dev)
33{
34 struct rsc_drv *drv = (struct rsc_drv *)dev_get_priv(dev->parent);
35
36 if(!drv) {
37 printf("BUG: no RPMh driver for %s (parent %s)\n", dev->name, dev->parent->name);
38 BUG();
39 }
40
41 return &drv->client;
42}
43
44/**
45 * __rpmh_write: Cache and send the RPMH request
46 *
47 * @dev: The device making the request
48 * @state: Active/Sleep request type
49 * @rpm_msg: The data that needs to be sent (cmds).
50 *
51 * Cache the RPMH request and send if the state is ACTIVE_ONLY.
52 * SLEEP/WAKE_ONLY requests are not sent to the controller at
53 * this time. Use rpmh_flush() to send them to the controller.
54 */
55static int __rpmh_write(const struct udevice *dev, enum rpmh_state state,
56 struct rpmh_request *rpm_msg)
57{
58 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
59
60 debug("rpmh_write: %s, %d\n", dev->name, state);
61
62 if (state != RPMH_ACTIVE_ONLY_STATE) {
63 printf("WARN: only ACTIVE_ONLY state supported\n");
64 return -EINVAL;
65 }
66
67 return rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);;
68}
69
70static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
71 const struct tcs_cmd *cmd, u32 n)
72{
73 if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
74 return -EINVAL;
75
76 memcpy(req->cmd, cmd, n * sizeof(*cmd));
77
78 req->msg.state = state;
79 req->msg.cmds = req->cmd;
80 req->msg.num_cmds = n;
81
82 debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, cmd->data);
83
84 return 0;
85}
86
87/**
88 * rpmh_write: Write a set of RPMH commands and block until response
89 *
90 * @dev: The device making the request
91 * @state: Active/sleep set
92 * @cmd: The payload data
93 * @n: The number of elements in @cmd
94 *
95 * May sleep. Do not call from atomic contexts.
96 */
97int rpmh_write(const struct udevice *dev, enum rpmh_state state,
98 const struct tcs_cmd *cmd, u32 n)
99{
100 DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
101 int ret;
102
103 ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n);
104 if (ret)
105 return ret;
106
107 ret = __rpmh_write(dev, state, &rpm_msg);
108
109 return ret;
110}