1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments' K3 System Controller Driver
4  *
5  * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
6  *	Lokesh Vutla <lokeshvutla@ti.com>
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <remoteproc.h>
12 #include <errno.h>
13 #include <mailbox.h>
14 #include <linux/soc/ti/k3-sec-proxy.h>
15 
16 #define K3_MSG_R5_TO_M3_M3FW			0x8105
17 #define K3_MSG_M3_TO_R5_CERT_RESULT		0x8805
18 #define K3_MSG_M3_TO_R5_BOOT_NOTIFICATION	0x000A
19 
20 #define K3_FLAGS_MSG_CERT_AUTH_PASS		0x555555
21 #define K3_FLAGS_MSG_CERT_AUTH_FAIL		0xffffff
22 
23 /**
24  * struct k3_sysctrler_msg_hdr - Generic Header for Messages and responses.
25  * @cmd_id:	Message ID. One of K3_MSG_*
26  * @host_id:	Host ID of the message
27  * @seq_ne:	Message identifier indicating a transfer sequence.
28  * @flags:	Flags for the message.
29  */
30 struct k3_sysctrler_msg_hdr {
31 	u16 cmd_id;
32 	u8 host_id;
33 	u8 seq_nr;
34 	u32 flags;
35 } __packed;
36 
37 /**
38  * struct k3_sysctrler_load_msg - Message format for Firmware loading
39  * @hdr:		Generic message hdr
40  * @buffer_address:	Address at which firmware is located.
41  * @buffer_size:	Size of the firmware.
42  */
43 struct k3_sysctrler_load_msg {
44 	struct k3_sysctrler_msg_hdr hdr;
45 	u32 buffer_address;
46 	u32 buffer_size;
47 } __packed;
48 
49 /**
50  * struct k3_sysctrler_boot_notification_msg - Message format for boot
51  *					       notification
52  * @checksum:		Checksum for the entire message
53  * @reserved:		Reserved for future use.
54  * @hdr:		Generic message hdr
55  */
56 struct k3_sysctrler_boot_notification_msg {
57 	u16 checksum;
58 	u16 reserved;
59 	struct k3_sysctrler_msg_hdr hdr;
60 } __packed;
61 
62 /**
63  * struct k3_sysctrler_desc - Description of SoC integration.
64  * @host_id:	Host identifier representing the compute entity
65  * @max_rx_timeout_ms:	Timeout for communication with SoC (in Milliseconds)
66  * @max_msg_size: Maximum size of data per message that can be handled.
67  */
68 struct k3_sysctrler_desc {
69 	u8 host_id;
70 	int max_rx_timeout_us;
71 	int max_msg_size;
72 };
73 
74 /**
75  * struct k3_sysctrler_privdata - Structure representing System Controller data.
76  * @chan_tx:	Transmit mailbox channel
77  * @chan_rx:	Receive mailbox channel
78  * @desc:	SoC description for this instance
79  * @seq_nr:	Counter for number of messages sent.
80  */
81 struct k3_sysctrler_privdata {
82 	struct mbox_chan chan_tx;
83 	struct mbox_chan chan_rx;
84 	struct k3_sysctrler_desc *desc;
85 	u32 seq_nr;
86 };
87 
88 static inline
k3_sysctrler_load_msg_setup(struct k3_sysctrler_load_msg * fw,struct k3_sysctrler_privdata * priv,ulong addr,ulong size)89 void k3_sysctrler_load_msg_setup(struct k3_sysctrler_load_msg *fw,
90 				 struct k3_sysctrler_privdata *priv,
91 				 ulong addr, ulong size)
92 {
93 	fw->hdr.cmd_id = K3_MSG_R5_TO_M3_M3FW;
94 	fw->hdr.host_id = priv->desc->host_id;
95 	fw->hdr.seq_nr = priv->seq_nr++;
96 	fw->hdr.flags = 0x0;
97 	fw->buffer_address = addr;
98 	fw->buffer_size = size;
99 }
100 
k3_sysctrler_load_response(u32 * buf)101 static int k3_sysctrler_load_response(u32 *buf)
102 {
103 	struct k3_sysctrler_load_msg *fw;
104 
105 	fw = (struct k3_sysctrler_load_msg *)buf;
106 
107 	/* Check for proper response ID */
108 	if (fw->hdr.cmd_id != K3_MSG_M3_TO_R5_CERT_RESULT) {
109 		dev_err(dev, "%s: Command expected 0x%x, but received 0x%x\n",
110 			__func__, K3_MSG_M3_TO_R5_CERT_RESULT, fw->hdr.cmd_id);
111 		return -EINVAL;
112 	}
113 
114 	/* Check for certificate authentication result */
115 	if (fw->hdr.flags == K3_FLAGS_MSG_CERT_AUTH_FAIL) {
116 		dev_err(dev, "%s: Firmware certificate authentication failed\n",
117 			__func__);
118 		return -EINVAL;
119 	} else if (fw->hdr.flags != K3_FLAGS_MSG_CERT_AUTH_PASS) {
120 		dev_err(dev, "%s: Firmware Load response Invalid %d\n",
121 			__func__, fw->hdr.flags);
122 		return -EINVAL;
123 	}
124 
125 	debug("%s: Firmware authentication passed\n", __func__);
126 
127 	return 0;
128 }
129 
k3_sysctrler_boot_notification_response(u32 * buf)130 static int k3_sysctrler_boot_notification_response(u32 *buf)
131 {
132 	struct k3_sysctrler_boot_notification_msg *boot;
133 
134 	boot = (struct k3_sysctrler_boot_notification_msg *)buf;
135 
136 	/* ToDo: Verify checksum */
137 
138 	/* Check for proper response ID */
139 	if (boot->hdr.cmd_id != K3_MSG_M3_TO_R5_BOOT_NOTIFICATION) {
140 		dev_err(dev, "%s: Command expected 0x%x, but received 0x%x\n",
141 			__func__, K3_MSG_M3_TO_R5_BOOT_NOTIFICATION,
142 			boot->hdr.cmd_id);
143 		return -EINVAL;
144 	}
145 
146 	debug("%s: Boot notification received\n", __func__);
147 
148 	return 0;
149 }
150 
151 /**
152  * k3_sysctrler_load() - Loadup the K3 remote processor
153  * @dev:	corresponding K3 remote processor device
154  * @addr:	Address in memory where image binary is stored
155  * @size:	Size in bytes of the image binary
156  *
157  * Return: 0 if all goes good, else appropriate error message.
158  */
k3_sysctrler_load(struct udevice * dev,ulong addr,ulong size)159 static int k3_sysctrler_load(struct udevice *dev, ulong addr, ulong size)
160 {
161 	struct k3_sysctrler_privdata *priv = dev_get_priv(dev);
162 	struct k3_sysctrler_load_msg firmware;
163 	struct k3_sec_proxy_msg msg;
164 	int ret;
165 
166 	debug("%s: Loading binary from 0x%08lX, size 0x%08lX\n",
167 	      __func__, addr, size);
168 
169 	memset(&firmware, 0, sizeof(firmware));
170 	memset(&msg, 0, sizeof(msg));
171 
172 	/* Setup the message */
173 	k3_sysctrler_load_msg_setup(&firmware, priv, addr, size);
174 	msg.len = sizeof(firmware);
175 	msg.buf = (u32 *)&firmware;
176 
177 	/* Send the message */
178 	ret = mbox_send(&priv->chan_tx, &msg);
179 	if (ret) {
180 		dev_err(dev, "%s: Firmware Loading failed. ret = %d\n",
181 			__func__, ret);
182 		return ret;
183 	}
184 
185 	/* Receive the response */
186 	ret = mbox_recv(&priv->chan_rx, &msg, priv->desc->max_rx_timeout_us);
187 	if (ret) {
188 		dev_err(dev, "%s: Firmware Load response failed. ret = %d\n",
189 			__func__, ret);
190 		return ret;
191 	}
192 
193 	/* Process the response */
194 	ret = k3_sysctrler_load_response(msg.buf);
195 	if (ret)
196 		return ret;
197 
198 	debug("%s: Firmware Loaded successfully on dev %s\n",
199 	      __func__, dev->name);
200 
201 	return 0;
202 }
203 
204 /**
205  * k3_sysctrler_start() - Start the remote processor
206  *		Note that while technically the K3 system controller starts up
207  *		automatically after its firmware got loaded we still want to
208  *		utilize the rproc start operation for other startup-related
209  *		tasks.
210  * @dev:	device to operate upon
211  *
212  * Return: 0 if all went ok, else return appropriate error
213  */
k3_sysctrler_start(struct udevice * dev)214 static int k3_sysctrler_start(struct udevice *dev)
215 {
216 	struct k3_sysctrler_privdata *priv = dev_get_priv(dev);
217 	struct k3_sec_proxy_msg msg;
218 	int ret;
219 
220 	debug("%s(dev=%p)\n", __func__, dev);
221 
222 	/* Receive the boot notification. Note that it is sent only once. */
223 	ret = mbox_recv(&priv->chan_rx, &msg, priv->desc->max_rx_timeout_us);
224 	if (ret) {
225 		dev_err(dev, "%s: Boot Notification response failed. ret = %d\n",
226 			__func__, ret);
227 		return ret;
228 	}
229 
230 	/* Process the response */
231 	ret = k3_sysctrler_boot_notification_response(msg.buf);
232 	if (ret)
233 		return ret;
234 
235 	debug("%s: Boot notification received successfully on dev %s\n",
236 	      __func__, dev->name);
237 
238 	return 0;
239 }
240 
241 static const struct dm_rproc_ops k3_sysctrler_ops = {
242 	.load = k3_sysctrler_load,
243 	.start = k3_sysctrler_start,
244 };
245 
246 /**
247  * k3_of_to_priv() - generate private data from device tree
248  * @dev:	corresponding k3 remote processor device
249  * @priv:	pointer to driver specific private data
250  *
251  * Return: 0 if all goes good, else appropriate error message.
252  */
k3_of_to_priv(struct udevice * dev,struct k3_sysctrler_privdata * priv)253 static int k3_of_to_priv(struct udevice *dev,
254 			 struct k3_sysctrler_privdata *priv)
255 {
256 	int ret;
257 
258 	ret = mbox_get_by_name(dev, "tx", &priv->chan_tx);
259 	if (ret) {
260 		dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
261 			__func__, ret);
262 		return ret;
263 	}
264 
265 	ret = mbox_get_by_name(dev, "rx", &priv->chan_rx);
266 	if (ret) {
267 		dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
268 			__func__, ret);
269 		return ret;
270 	}
271 
272 	return 0;
273 }
274 
275 /**
276  * k3_sysctrler_probe() - Basic probe
277  * @dev:	corresponding k3 remote processor device
278  *
279  * Return: 0 if all goes good, else appropriate error message.
280  */
k3_sysctrler_probe(struct udevice * dev)281 static int k3_sysctrler_probe(struct udevice *dev)
282 {
283 	struct k3_sysctrler_privdata *priv;
284 	int ret;
285 
286 	debug("%s(dev=%p)\n", __func__, dev);
287 
288 	priv = dev_get_priv(dev);
289 
290 	ret = k3_of_to_priv(dev, priv);
291 	if (ret) {
292 		dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
293 		return ret;
294 	}
295 
296 	priv->desc = (void *)dev_get_driver_data(dev);
297 	priv->seq_nr = 0;
298 
299 	return 0;
300 }
301 
302 static const struct k3_sysctrler_desc k3_sysctrler_am654_desc = {
303 	.host_id = 4,				/* HOST_ID_R5_1 */
304 	.max_rx_timeout_us = 400000,
305 	.max_msg_size = 60,
306 };
307 
308 static const struct udevice_id k3_sysctrler_ids[] = {
309 	{
310 		.compatible = "ti,am654-system-controller",
311 		.data = (ulong)&k3_sysctrler_am654_desc,
312 	},
313 	{}
314 };
315 
316 U_BOOT_DRIVER(k3_sysctrler) = {
317 	.name = "k3_system_controller",
318 	.of_match = k3_sysctrler_ids,
319 	.id = UCLASS_REMOTEPROC,
320 	.ops = &k3_sysctrler_ops,
321 	.probe = k3_sysctrler_probe,
322 	.priv_auto_alloc_size = sizeof(struct k3_sysctrler_privdata),
323 };
324