1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Linaro Limited.
4 */
5
6#define LOG_CATEGORY UCLASS_SCMI_AGENT
7
8#include <common.h>
9#include <dm.h>
10#include <errno.h>
11#include <scmi_agent.h>
12#include <scmi_agent-uclass.h>
13#include <scmi_protocols.h>
14#include <dm/device_compat.h>
15#include <dm/device-internal.h>
16#include <linux/compat.h>
17
18/**
19 * struct error_code - Helper structure for SCMI error code conversion
20 * @scmi:	SCMI error code
21 * @errno:	Related standard error number
22 */
23struct error_code {
24	int scmi;
25	int errno;
26};
27
28static const struct error_code scmi_linux_errmap[] = {
29	{ .scmi = SCMI_NOT_SUPPORTED, .errno = -EOPNOTSUPP, },
30	{ .scmi = SCMI_INVALID_PARAMETERS, .errno = -EINVAL, },
31	{ .scmi = SCMI_DENIED, .errno = -EACCES, },
32	{ .scmi = SCMI_NOT_FOUND, .errno = -ENOENT, },
33	{ .scmi = SCMI_OUT_OF_RANGE, .errno = -ERANGE, },
34	{ .scmi = SCMI_BUSY, .errno = -EBUSY, },
35	{ .scmi = SCMI_COMMS_ERROR, .errno = -ECOMM, },
36	{ .scmi = SCMI_GENERIC_ERROR, .errno = -EIO, },
37	{ .scmi = SCMI_HARDWARE_ERROR, .errno = -EREMOTEIO, },
38	{ .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
39};
40
41/**
42 * scmi_protocol_is_supported - check availability of protocol
43 * @dev:	SCMI agent device
44 * @proto_id:	Identifier of protocol
45 *
46 * check if the protocol, @proto_id, is provided by the SCMI agent,
47 * @dev.
48 *
49 * Return:	0 on success, error code otherwise
50 */
51static bool scmi_protocol_is_supported(struct udevice *dev,
52				       enum scmi_std_protocol proto_id)
53{
54	struct scmi_agent_priv *priv;
55	int i;
56
57	if (proto_id == SCMI_PROTOCOL_ID_BASE)
58		return true;
59
60	priv = dev_get_uclass_plat(dev);
61	if (!priv) {
62		dev_err(dev, "No priv data found\n");
63		return false;
64	}
65
66	for (i = 0; i < priv->num_protocols; i++)
67		if (priv->protocols[i] == proto_id)
68			return true;
69
70	return false;
71}
72
73struct udevice *scmi_get_protocol(struct udevice *dev,
74				  enum scmi_std_protocol id)
75{
76	struct scmi_agent_priv *priv;
77	struct udevice *proto;
78
79	priv = dev_get_uclass_plat(dev);
80	if (!priv) {
81		dev_err(dev, "No priv data found\n");
82		return NULL;
83	}
84
85	switch (id) {
86	case SCMI_PROTOCOL_ID_BASE:
87		proto = priv->base_dev;
88		break;
89	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
90		proto = priv->pwdom_dev;
91		break;
92	case SCMI_PROTOCOL_ID_CLOCK:
93		proto = priv->clock_dev;
94		break;
95	case SCMI_PROTOCOL_ID_RESET_DOMAIN:
96		proto = priv->resetdom_dev;
97		break;
98	case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
99		proto = priv->voltagedom_dev;
100		break;
101	default:
102		dev_err(dev, "Protocol not supported\n");
103		proto = NULL;
104		break;
105	}
106	if (proto && device_probe(proto))
107		dev_err(dev, "Probe failed\n");
108
109	return proto;
110}
111
112/**
113 * scmi_add_protocol - add protocol to agent
114 * @dev:	SCMI agent device
115 * @proto_id:	SCMI protocol ID
116 * @proto:	SCMI protocol device
117 *
118 * Associate the protocol instance, @proto, to the agent, @dev,
119 * for later use.
120 *
121 * Return:	0 on success, error code on failure
122 */
123static int scmi_add_protocol(struct udevice *dev,
124			     enum scmi_std_protocol proto_id,
125			     struct udevice *proto)
126{
127	struct scmi_agent_priv *priv;
128
129	priv = dev_get_uclass_plat(dev);
130	if (!priv) {
131		dev_err(dev, "No priv data found\n");
132		return -ENODEV;
133	}
134
135	switch (proto_id) {
136	case SCMI_PROTOCOL_ID_BASE:
137		priv->base_dev = proto;
138		break;
139	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
140		priv->pwdom_dev = proto;
141		break;
142	case SCMI_PROTOCOL_ID_CLOCK:
143		priv->clock_dev = proto;
144		break;
145	case SCMI_PROTOCOL_ID_RESET_DOMAIN:
146		priv->resetdom_dev = proto;
147		break;
148	case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
149		priv->voltagedom_dev = proto;
150		break;
151	default:
152		dev_err(dev, "Protocol not supported\n");
153		return -EPROTO;
154	}
155
156	return 0;
157}
158
159int scmi_to_linux_errno(s32 scmi_code)
160{
161	int n;
162
163	if (!scmi_code)
164		return 0;
165
166	for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++)
167		if (scmi_code == scmi_linux_errmap[n].scmi)
168			return scmi_linux_errmap[n].errno;
169
170	return -EPROTO;
171}
172
173static struct udevice *find_scmi_protocol_device(struct udevice *dev)
174{
175	struct udevice *parent = NULL, *protocol;
176
177	for (protocol = dev; protocol; protocol = parent) {
178		parent = dev_get_parent(protocol);
179		if (!parent ||
180		    device_get_uclass_id(parent) == UCLASS_SCMI_AGENT)
181			break;
182	}
183
184	if (!parent) {
185		dev_err(dev, "Invalid SCMI device, agent not found\n");
186		return NULL;
187	}
188
189	return protocol;
190}
191
192static const struct scmi_agent_ops *transport_dev_ops(struct udevice *dev)
193{
194	return (const struct scmi_agent_ops *)dev->driver->ops;
195}
196
197/**
198 * scmi_of_get_channel() - Get SCMI channel handle
199 *
200 * @dev:	SCMI agent device
201 * @channel:	Output reference to the SCMI channel upon success
202 *
203 * On return, @channel will be set.
204 * Return	0 on success and a negative errno on failure
205 */
206static int scmi_of_get_channel(struct udevice *dev, struct udevice *protocol,
207			       struct scmi_channel **channel)
208{
209	const struct scmi_agent_ops *ops;
210
211	ops = transport_dev_ops(dev);
212	if (ops->of_get_channel)
213		return ops->of_get_channel(dev, protocol, channel);
214	else
215		return -EPROTONOSUPPORT;
216}
217
218int devm_scmi_of_get_channel(struct udevice *dev)
219{
220	struct udevice *protocol;
221	struct scmi_agent_proto_priv *priv;
222	int ret;
223
224	protocol = find_scmi_protocol_device(dev);
225	if (!protocol)
226		return -ENODEV;
227
228	priv = dev_get_parent_priv(protocol);
229	ret = scmi_of_get_channel(protocol->parent, protocol, &priv->channel);
230	if (ret == -EPROTONOSUPPORT) {
231		/* Drivers without a get_channel operator don't need a channel ref */
232		priv->channel = NULL;
233
234		return 0;
235	}
236
237	return ret;
238}
239
240/**
241 * scmi_process_msg() - Send and process an SCMI message
242 *
243 * Send a message to an SCMI server.
244 * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
245 *
246 * @dev:	SCMI agent device
247 * @channel:	Communication channel for the device
248 * @msg:	Message structure reference
249 *
250 * On return, scmi_msg::out_msg_sz stores the response payload size.
251 * Return:	0 on success and a negative errno on failure
252 */
253static int scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
254			    struct scmi_msg *msg)
255{
256	const struct scmi_agent_ops *ops;
257
258	ops = transport_dev_ops(dev);
259	if (ops->process_msg)
260		return ops->process_msg(dev, channel, msg);
261	else
262		return -EPROTONOSUPPORT;
263}
264
265int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg)
266{
267	struct udevice *protocol;
268	struct scmi_agent_proto_priv *priv;
269
270	protocol = find_scmi_protocol_device(dev);
271	if (!protocol)
272		return -ENODEV;
273
274	priv = dev_get_parent_priv(protocol);
275
276	return scmi_process_msg(protocol->parent, priv->channel, msg);
277}
278
279/**
280 * scmi_fill_base_info - get base information about SCMI server
281 * @agent:	SCMI agent device
282 * @dev:	SCMI protocol device
283 *
284 * By using Base protocol commands, collect the base information
285 * about SCMI server.
286 *
287 * Return: 0 on success, error code on failure
288 */
289static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev)
290{
291	struct scmi_agent_priv *priv = dev_get_uclass_plat(agent);
292	int ret;
293
294	ret = scmi_base_protocol_version(dev, &priv->version);
295	if (ret) {
296		dev_err(dev, "protocol_version() failed (%d)\n", ret);
297		return ret;
298	}
299	/* check for required version */
300	if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
301		dev_err(dev, "base protocol version (%d) lower than expected\n",
302			priv->version);
303		return -EPROTO;
304	}
305
306	ret = scmi_base_protocol_attrs(dev, &priv->num_agents,
307				       &priv->num_protocols);
308	if (ret) {
309		dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
310		return ret;
311	}
312	ret = scmi_base_discover_vendor(dev, &priv->vendor);
313	if (ret) {
314		dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
315		return ret;
316	}
317	ret = scmi_base_discover_sub_vendor(dev, &priv->sub_vendor);
318	if (ret) {
319		if (ret != -EOPNOTSUPP) {
320			dev_err(dev, "base_discover_sub_vendor() failed (%d)\n",
321				ret);
322			return ret;
323		}
324		priv->sub_vendor = "NA";
325	}
326	ret = scmi_base_discover_impl_version(dev, &priv->impl_version);
327	if (ret) {
328		dev_err(dev, "base_discover_impl_version() failed (%d)\n",
329			ret);
330		return ret;
331	}
332
333	ret = scmi_base_discover_agent(dev, 0xffffffff,
334				       &priv->agent_id, &priv->agent_name);
335	if (ret) {
336		if (ret != -EOPNOTSUPP) {
337			dev_err(dev,
338				"base_discover_agent() failed for myself (%d)\n",
339				ret);
340			return ret;
341		}
342		priv->agent_id = 0xffffffff;
343		priv->agent_name = "NA";
344	}
345
346	ret = scmi_base_discover_list_protocols(dev, &priv->protocols);
347	if (ret != priv->num_protocols) {
348		dev_err(dev, "base_discover_list_protocols() failed (%d)\n",
349			ret);
350		return -EPROTO;
351	}
352
353	return 0;
354}
355
356/*
357 * SCMI agent devices binds devices of various uclasses depending on
358 * the FDT description. scmi_bind_protocol() is a generic bind sequence
359 * called by the uclass at bind stage, that is uclass post_bind.
360 */
361static int scmi_bind_protocols(struct udevice *dev)
362{
363	int ret = 0;
364	ofnode node;
365	const char *name;
366	struct driver *drv;
367	struct udevice *agent, *proto;
368
369	if (!uclass_get_device(UCLASS_SCMI_AGENT, 1, &agent)) {
370		/* This is a second SCMI agent */
371		dev_err(dev, "Cannot have more than one SCMI agent\n");
372		return -EEXIST;
373	}
374
375	/* initialize the device from device tree */
376	drv = DM_DRIVER_GET(scmi_base_drv);
377	name = "scmi-base.0";
378	ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
379	if (ret) {
380		dev_err(dev, "failed to bind base protocol\n");
381		return ret;
382	}
383	ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
384	if (ret) {
385		dev_err(dev, "failed to add protocol: %s, ret: %d\n",
386			proto->name, ret);
387		return ret;
388	}
389
390	ret = device_probe(proto);
391	if (ret) {
392		dev_err(dev, "failed to probe base protocol\n");
393		return ret;
394	}
395
396	ret = scmi_fill_base_info(dev, proto);
397	if (ret) {
398		dev_err(dev, "failed to get base information\n");
399		return ret;
400	}
401
402	dev_for_each_subnode(node, dev) {
403		u32 protocol_id;
404
405		if (!ofnode_is_enabled(node))
406			continue;
407
408		if (ofnode_read_u32(node, "reg", &protocol_id))
409			continue;
410
411		drv = NULL;
412		name = ofnode_get_name(node);
413		switch (protocol_id) {
414		case SCMI_PROTOCOL_ID_POWER_DOMAIN:
415			if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN) &&
416			    scmi_protocol_is_supported(dev, protocol_id))
417				drv = DM_DRIVER_GET(scmi_power_domain);
418			break;
419		case SCMI_PROTOCOL_ID_CLOCK:
420			if (CONFIG_IS_ENABLED(CLK_SCMI) &&
421			    scmi_protocol_is_supported(dev, protocol_id))
422				drv = DM_DRIVER_GET(scmi_clock);
423			break;
424		case SCMI_PROTOCOL_ID_RESET_DOMAIN:
425			if (IS_ENABLED(CONFIG_RESET_SCMI) &&
426			    scmi_protocol_is_supported(dev, protocol_id))
427				drv = DM_DRIVER_GET(scmi_reset_domain);
428			break;
429		case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
430			if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) &&
431			    scmi_protocol_is_supported(dev, protocol_id)) {
432				node = ofnode_find_subnode(node, "regulators");
433				if (!ofnode_valid(node)) {
434					dev_err(dev, "no regulators node\n");
435					return -ENXIO;
436				}
437				drv = DM_DRIVER_GET(scmi_voltage_domain);
438			}
439			break;
440		default:
441			break;
442		}
443
444		if (!drv) {
445			dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n",
446				protocol_id);
447			continue;
448		}
449
450		ret = device_bind(dev, drv, name, NULL, node, &proto);
451		if (ret) {
452			dev_err(dev, "failed to bind %s protocol\n", drv->name);
453			break;
454		}
455		ret = scmi_add_protocol(dev, protocol_id, proto);
456		if (ret) {
457			dev_err(dev, "failed to add protocol: %s, ret: %d\n",
458				proto->name, ret);
459			break;
460		}
461	}
462
463	return ret;
464}
465
466UCLASS_DRIVER(scmi_agent) = {
467	.id		= UCLASS_SCMI_AGENT,
468	.name		= "scmi_agent",
469	.post_bind	= scmi_bind_protocols,
470	.per_device_plat_auto = sizeof(struct scmi_agent_priv),
471	.per_child_auto	= sizeof(struct scmi_agent_proto_priv),
472};
473