1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP 4 * Author: Dong Aisheng <aisheng.dong@nxp.com> 5 * 6 * Implementation of the SCU IPC functions using MUs (client side). 7 * 8 */ 9 10 #include <linux/err.h> 11 #include <linux/firmware/imx/ipc.h> 12 #include <linux/firmware/imx/sci.h> 13 #include <linux/interrupt.h> 14 #include <linux/irq.h> 15 #include <linux/kernel.h> 16 #include <linux/mailbox_client.h> 17 #include <linux/module.h> 18 #include <linux/mutex.h> 19 #include <linux/of.h> 20 #include <linux/of_platform.h> 21 #include <linux/platform_device.h> 22 23 #define SCU_MU_CHAN_NUM 8 24 #define MAX_RX_TIMEOUT (msecs_to_jiffies(3000)) 25 26 struct imx_sc_chan { 27 struct imx_sc_ipc *sc_ipc; 28 29 struct mbox_client cl; 30 struct mbox_chan *ch; 31 int idx; 32 struct completion tx_done; 33 }; 34 35 struct imx_sc_ipc { 36 /* SCU uses 4 Tx and 4 Rx channels */ 37 struct imx_sc_chan chans[SCU_MU_CHAN_NUM]; 38 struct device *dev; 39 struct mutex lock; 40 struct completion done; 41 bool fast_ipc; 42 43 /* temporarily store the SCU msg */ 44 u32 *msg; 45 u8 rx_size; 46 u8 count; 47 }; 48 49 /* 50 * This type is used to indicate error response for most functions. 51 */ 52 enum imx_sc_error_codes { 53 IMX_SC_ERR_NONE = 0, /* Success */ 54 IMX_SC_ERR_VERSION = 1, /* Incompatible API version */ 55 IMX_SC_ERR_CONFIG = 2, /* Configuration error */ 56 IMX_SC_ERR_PARM = 3, /* Bad parameter */ 57 IMX_SC_ERR_NOACCESS = 4, /* Permission error (no access) */ 58 IMX_SC_ERR_LOCKED = 5, /* Permission error (locked) */ 59 IMX_SC_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */ 60 IMX_SC_ERR_NOTFOUND = 7, /* Not found */ 61 IMX_SC_ERR_NOPOWER = 8, /* No power */ 62 IMX_SC_ERR_IPC = 9, /* Generic IPC error */ 63 IMX_SC_ERR_BUSY = 10, /* Resource is currently busy/active */ 64 IMX_SC_ERR_FAIL = 11, /* General I/O failure */ 65 IMX_SC_ERR_LAST 66 }; 67 68 static int imx_sc_linux_errmap[IMX_SC_ERR_LAST] = { 69 0, /* IMX_SC_ERR_NONE */ 70 -EINVAL, /* IMX_SC_ERR_VERSION */ 71 -EINVAL, /* IMX_SC_ERR_CONFIG */ 72 -EINVAL, /* IMX_SC_ERR_PARM */ 73 -EACCES, /* IMX_SC_ERR_NOACCESS */ 74 -EACCES, /* IMX_SC_ERR_LOCKED */ 75 -ERANGE, /* IMX_SC_ERR_UNAVAILABLE */ 76 -EEXIST, /* IMX_SC_ERR_NOTFOUND */ 77 -EPERM, /* IMX_SC_ERR_NOPOWER */ 78 -EPIPE, /* IMX_SC_ERR_IPC */ 79 -EBUSY, /* IMX_SC_ERR_BUSY */ 80 -EIO, /* IMX_SC_ERR_FAIL */ 81 }; 82 83 static struct imx_sc_ipc *imx_sc_ipc_handle; 84 85 static inline int imx_sc_to_linux_errno(int errno) 86 { 87 if (errno >= IMX_SC_ERR_NONE && errno < IMX_SC_ERR_LAST) 88 return imx_sc_linux_errmap[errno]; 89 return -EIO; 90 } 91 92 /* 93 * Get the default handle used by SCU 94 */ 95 int imx_scu_get_handle(struct imx_sc_ipc **ipc) 96 { 97 if (!imx_sc_ipc_handle) 98 return -EPROBE_DEFER; 99 100 *ipc = imx_sc_ipc_handle; 101 return 0; 102 } 103 EXPORT_SYMBOL(imx_scu_get_handle); 104 105 /* Callback called when the word of a message is ack-ed, eg read by SCU */ 106 static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r) 107 { 108 struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl); 109 110 complete(&sc_chan->tx_done); 111 } 112 113 static void imx_scu_rx_callback(struct mbox_client *c, void *msg) 114 { 115 struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl); 116 struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc; 117 struct imx_sc_rpc_msg *hdr; 118 u32 *data = msg; 119 int i; 120 121 if (!sc_ipc->msg) { 122 dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n", 123 sc_chan->idx, *data); 124 return; 125 } 126 127 if (sc_ipc->fast_ipc) { 128 hdr = msg; 129 sc_ipc->rx_size = hdr->size; 130 sc_ipc->msg[0] = *data++; 131 132 for (i = 1; i < sc_ipc->rx_size; i++) 133 sc_ipc->msg[i] = *data++; 134 135 complete(&sc_ipc->done); 136 137 return; 138 } 139 140 if (sc_chan->idx == 0) { 141 hdr = msg; 142 sc_ipc->rx_size = hdr->size; 143 dev_dbg(sc_ipc->dev, "msg rx size %u\n", sc_ipc->rx_size); 144 if (sc_ipc->rx_size > 4) 145 dev_warn(sc_ipc->dev, "RPC does not support receiving over 4 words: %u\n", 146 sc_ipc->rx_size); 147 } 148 149 sc_ipc->msg[sc_chan->idx] = *data; 150 sc_ipc->count++; 151 152 dev_dbg(sc_ipc->dev, "mu %u msg %u 0x%x\n", sc_chan->idx, 153 sc_ipc->count, *data); 154 155 if ((sc_ipc->rx_size != 0) && (sc_ipc->count == sc_ipc->rx_size)) 156 complete(&sc_ipc->done); 157 } 158 159 static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg) 160 { 161 struct imx_sc_rpc_msg hdr = *(struct imx_sc_rpc_msg *)msg; 162 struct imx_sc_chan *sc_chan; 163 u32 *data = msg; 164 int ret; 165 int size; 166 int i; 167 168 /* Check size */ 169 if (hdr.size > IMX_SC_RPC_MAX_MSG) 170 return -EINVAL; 171 172 dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr.svc, 173 hdr.func, hdr.size); 174 175 size = sc_ipc->fast_ipc ? 1 : hdr.size; 176 for (i = 0; i < size; i++) { 177 sc_chan = &sc_ipc->chans[i % 4]; 178 179 /* 180 * SCU requires that all messages words are written 181 * sequentially but linux MU driver implements multiple 182 * independent channels for each register so ordering between 183 * different channels must be ensured by SCU API interface. 184 * 185 * Wait for tx_done before every send to ensure that no 186 * queueing happens at the mailbox channel level. 187 */ 188 if (!sc_ipc->fast_ipc) { 189 wait_for_completion(&sc_chan->tx_done); 190 reinit_completion(&sc_chan->tx_done); 191 } 192 193 ret = mbox_send_message(sc_chan->ch, &data[i]); 194 if (ret < 0) 195 return ret; 196 } 197 198 return 0; 199 } 200 201 /* 202 * RPC command/response 203 */ 204 int imx_scu_call_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp) 205 { 206 uint8_t saved_svc, saved_func; 207 struct imx_sc_rpc_msg *hdr; 208 int ret; 209 210 if (WARN_ON(!sc_ipc || !msg)) 211 return -EINVAL; 212 213 mutex_lock(&sc_ipc->lock); 214 reinit_completion(&sc_ipc->done); 215 216 if (have_resp) { 217 sc_ipc->msg = msg; 218 saved_svc = ((struct imx_sc_rpc_msg *)msg)->svc; 219 saved_func = ((struct imx_sc_rpc_msg *)msg)->func; 220 } 221 sc_ipc->count = 0; 222 ret = imx_scu_ipc_write(sc_ipc, msg); 223 if (ret < 0) { 224 dev_err(sc_ipc->dev, "RPC send msg failed: %d\n", ret); 225 goto out; 226 } 227 228 if (have_resp) { 229 if (!wait_for_completion_timeout(&sc_ipc->done, 230 MAX_RX_TIMEOUT)) { 231 dev_err(sc_ipc->dev, "RPC send msg timeout\n"); 232 mutex_unlock(&sc_ipc->lock); 233 return -ETIMEDOUT; 234 } 235 236 /* response status is stored in hdr->func field */ 237 hdr = msg; 238 ret = hdr->func; 239 /* 240 * Some special SCU firmware APIs do NOT have return value 241 * in hdr->func, but they do have response data, those special 242 * APIs are defined as void function in SCU firmware, so they 243 * should be treated as return success always. 244 */ 245 if ((saved_svc == IMX_SC_RPC_SVC_MISC) && 246 (saved_func == IMX_SC_MISC_FUNC_UNIQUE_ID || 247 saved_func == IMX_SC_MISC_FUNC_GET_BUTTON_STATUS)) 248 ret = 0; 249 } 250 251 out: 252 sc_ipc->msg = NULL; 253 mutex_unlock(&sc_ipc->lock); 254 255 dev_dbg(sc_ipc->dev, "RPC SVC done\n"); 256 257 return imx_sc_to_linux_errno(ret); 258 } 259 EXPORT_SYMBOL(imx_scu_call_rpc); 260 261 static int imx_scu_probe(struct platform_device *pdev) 262 { 263 struct device *dev = &pdev->dev; 264 struct imx_sc_ipc *sc_ipc; 265 struct imx_sc_chan *sc_chan; 266 struct mbox_client *cl; 267 char *chan_name; 268 struct of_phandle_args args; 269 int num_channel; 270 int ret; 271 int i; 272 273 sc_ipc = devm_kzalloc(dev, sizeof(*sc_ipc), GFP_KERNEL); 274 if (!sc_ipc) 275 return -ENOMEM; 276 277 ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes", 278 "#mbox-cells", 0, &args); 279 if (ret) 280 return ret; 281 282 sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu"); 283 284 num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM; 285 for (i = 0; i < num_channel; i++) { 286 if (i < num_channel / 2) 287 chan_name = kasprintf(GFP_KERNEL, "tx%d", i); 288 else 289 chan_name = kasprintf(GFP_KERNEL, "rx%d", 290 i - num_channel / 2); 291 292 if (!chan_name) 293 return -ENOMEM; 294 295 sc_chan = &sc_ipc->chans[i]; 296 cl = &sc_chan->cl; 297 cl->dev = dev; 298 cl->tx_block = false; 299 cl->knows_txdone = true; 300 cl->rx_callback = imx_scu_rx_callback; 301 302 if (!sc_ipc->fast_ipc) { 303 /* Initial tx_done completion as "done" */ 304 cl->tx_done = imx_scu_tx_done; 305 init_completion(&sc_chan->tx_done); 306 complete(&sc_chan->tx_done); 307 } 308 309 sc_chan->sc_ipc = sc_ipc; 310 sc_chan->idx = i % (num_channel / 2); 311 sc_chan->ch = mbox_request_channel_byname(cl, chan_name); 312 if (IS_ERR(sc_chan->ch)) { 313 ret = PTR_ERR(sc_chan->ch); 314 dev_err_probe(dev, ret, "Failed to request mbox chan %s\n", 315 chan_name); 316 kfree(chan_name); 317 return ret; 318 } 319 320 dev_dbg(dev, "request mbox chan %s\n", chan_name); 321 /* chan_name is not used anymore by framework */ 322 kfree(chan_name); 323 } 324 325 sc_ipc->dev = dev; 326 mutex_init(&sc_ipc->lock); 327 init_completion(&sc_ipc->done); 328 329 imx_sc_ipc_handle = sc_ipc; 330 331 ret = imx_scu_soc_init(dev); 332 if (ret) 333 dev_warn(dev, "failed to initialize SoC info: %d\n", ret); 334 335 ret = imx_scu_enable_general_irq_channel(dev); 336 if (ret) 337 dev_warn(dev, 338 "failed to enable general irq channel: %d\n", ret); 339 340 dev_info(dev, "NXP i.MX SCU Initialized\n"); 341 342 return devm_of_platform_populate(dev); 343 } 344 345 static const struct of_device_id imx_scu_match[] = { 346 { .compatible = "fsl,imx-scu", }, 347 { /* Sentinel */ } 348 }; 349 350 static struct platform_driver imx_scu_driver = { 351 .driver = { 352 .name = "imx-scu", 353 .of_match_table = imx_scu_match, 354 }, 355 .probe = imx_scu_probe, 356 }; 357 358 static int __init imx_scu_driver_init(void) 359 { 360 return platform_driver_register(&imx_scu_driver); 361 } 362 subsys_initcall_sync(imx_scu_driver_init); 363 364 MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>"); 365 MODULE_DESCRIPTION("IMX SCU firmware protocol driver"); 366 MODULE_LICENSE("GPL v2"); 367