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 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 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 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 */ 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 */ 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 */ 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 */ 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