1135 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>4 * Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>5 */6 7#include <linux/bitfield.h>8#include <linux/clk.h>9#include <linux/firmware/imx/ipc.h>10#include <linux/firmware/imx/s4.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/iopoll.h>14#include <linux/jiffies.h>15#include <linux/kernel.h>16#include <linux/mailbox_controller.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/of_platform.h>20#include <linux/platform_device.h>21#include <linux/pm_runtime.h>22#include <linux/suspend.h>23#include <linux/slab.h>24#include <linux/workqueue.h>25 26#include "mailbox.h"27 28#define IMX_MU_CHANS 2429/* TX0/RX0/RXDB[0-3] */30#define IMX_MU_SCU_CHANS 631/* TX0/RX0 */32#define IMX_MU_S4_CHANS 233#define IMX_MU_CHAN_NAME_SIZE 3234 35#define IMX_MU_V2_PAR_OFF 0x436#define IMX_MU_V2_TR_MASK GENMASK(7, 0)37#define IMX_MU_V2_RR_MASK GENMASK(15, 8)38 39#define IMX_MU_SECO_TX_TOUT (msecs_to_jiffies(3000))40#define IMX_MU_SECO_RX_TOUT (msecs_to_jiffies(3000))41 42/* Please not change TX & RX */43enum imx_mu_chan_type {44 IMX_MU_TYPE_TX = 0, /* Tx */45 IMX_MU_TYPE_RX = 1, /* Rx */46 IMX_MU_TYPE_TXDB = 2, /* Tx doorbell */47 IMX_MU_TYPE_RXDB = 3, /* Rx doorbell */48 IMX_MU_TYPE_RST = 4, /* Reset */49 IMX_MU_TYPE_TXDB_V2 = 5, /* Tx doorbell with S/W ACK */50};51 52enum imx_mu_xcr {53 IMX_MU_CR,54 IMX_MU_GIER,55 IMX_MU_GCR,56 IMX_MU_TCR,57 IMX_MU_RCR,58 IMX_MU_xCR_MAX,59};60 61enum imx_mu_xsr {62 IMX_MU_SR,63 IMX_MU_GSR,64 IMX_MU_TSR,65 IMX_MU_RSR,66 IMX_MU_xSR_MAX,67};68 69struct imx_sc_rpc_msg_max {70 struct imx_sc_rpc_msg hdr;71 u32 data[30];72};73 74struct imx_s4_rpc_msg_max {75 struct imx_s4_rpc_msg hdr;76 u32 data[254];77};78 79struct imx_mu_con_priv {80 unsigned int idx;81 char irq_desc[IMX_MU_CHAN_NAME_SIZE];82 enum imx_mu_chan_type type;83 struct mbox_chan *chan;84 struct work_struct txdb_work;85};86 87struct imx_mu_priv {88 struct device *dev;89 void __iomem *base;90 void *msg;91 spinlock_t xcr_lock; /* control register lock */92 93 struct mbox_controller mbox;94 struct mbox_chan mbox_chans[IMX_MU_CHANS];95 96 struct imx_mu_con_priv con_priv[IMX_MU_CHANS];97 const struct imx_mu_dcfg *dcfg;98 struct clk *clk;99 int irq[IMX_MU_CHANS];100 bool suspend;101 bool side_b;102 103 u32 xcr[IMX_MU_xCR_MAX];104 u32 num_tr;105 u32 num_rr;106};107 108enum imx_mu_type {109 IMX_MU_V1,110 IMX_MU_V2 = BIT(1),111 IMX_MU_V2_S4 = BIT(15),112 IMX_MU_V2_IRQ = BIT(16),113};114 115struct imx_mu_dcfg {116 int (*tx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp, void *data);117 int (*rx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp);118 int (*rxdb)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp);119 int (*init)(struct imx_mu_priv *priv);120 enum imx_mu_type type;121 u32 xTR; /* Transmit Register0 */122 u32 xRR; /* Receive Register0 */123 u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */124 u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */125};126 127#define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))128#define IMX_MU_xSR_RFn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))129#define IMX_MU_xSR_TEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))130 131/* General Purpose Interrupt Enable */132#define IMX_MU_xCR_GIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))133/* Receive Interrupt Enable */134#define IMX_MU_xCR_RIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x))))135/* Transmit Interrupt Enable */136#define IMX_MU_xCR_TIEn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x))))137/* General Purpose Interrupt Request */138#define IMX_MU_xCR_GIRn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x))))139/* MU reset */140#define IMX_MU_xCR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(5))141#define IMX_MU_xSR_RST(type) (type & IMX_MU_V2 ? BIT(0) : BIT(7))142 143 144static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)145{146 return container_of(mbox, struct imx_mu_priv, mbox);147}148 149static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)150{151 iowrite32(val, priv->base + offs);152}153 154static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)155{156 return ioread32(priv->base + offs);157}158 159static int imx_mu_tx_waiting_write(struct imx_mu_priv *priv, u32 val, u32 idx)160{161 u64 timeout_time = get_jiffies_64() + IMX_MU_SECO_TX_TOUT;162 u32 status;163 u32 can_write;164 165 dev_dbg(priv->dev, "Trying to write %.8x to idx %d\n", val, idx);166 167 do {168 status = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_TSR]);169 can_write = status & IMX_MU_xSR_TEn(priv->dcfg->type, idx % 4);170 } while (!can_write && time_is_after_jiffies64(timeout_time));171 172 if (!can_write) {173 dev_err(priv->dev, "timeout trying to write %.8x at %d(%.8x)\n",174 val, idx, status);175 return -ETIME;176 }177 178 imx_mu_write(priv, val, priv->dcfg->xTR + (idx % 4) * 4);179 180 return 0;181}182 183static int imx_mu_rx_waiting_read(struct imx_mu_priv *priv, u32 *val, u32 idx)184{185 u64 timeout_time = get_jiffies_64() + IMX_MU_SECO_RX_TOUT;186 u32 status;187 u32 can_read;188 189 dev_dbg(priv->dev, "Trying to read from idx %d\n", idx);190 191 do {192 status = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_RSR]);193 can_read = status & IMX_MU_xSR_RFn(priv->dcfg->type, idx % 4);194 } while (!can_read && time_is_after_jiffies64(timeout_time));195 196 if (!can_read) {197 dev_err(priv->dev, "timeout trying to read idx %d (%.8x)\n",198 idx, status);199 return -ETIME;200 }201 202 *val = imx_mu_read(priv, priv->dcfg->xRR + (idx % 4) * 4);203 dev_dbg(priv->dev, "Read %.8x\n", *val);204 205 return 0;206}207 208static u32 imx_mu_xcr_rmw(struct imx_mu_priv *priv, enum imx_mu_xcr type, u32 set, u32 clr)209{210 unsigned long flags;211 u32 val;212 213 spin_lock_irqsave(&priv->xcr_lock, flags);214 val = imx_mu_read(priv, priv->dcfg->xCR[type]);215 val &= ~clr;216 val |= set;217 imx_mu_write(priv, val, priv->dcfg->xCR[type]);218 spin_unlock_irqrestore(&priv->xcr_lock, flags);219 220 return val;221}222 223static int imx_mu_generic_tx(struct imx_mu_priv *priv,224 struct imx_mu_con_priv *cp,225 void *data)226{227 u32 *arg = data;228 u32 val;229 int ret;230 231 switch (cp->type) {232 case IMX_MU_TYPE_TX:233 imx_mu_write(priv, *arg, priv->dcfg->xTR + cp->idx * 4);234 imx_mu_xcr_rmw(priv, IMX_MU_TCR, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx), 0);235 break;236 case IMX_MU_TYPE_TXDB:237 imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);238 queue_work(system_bh_wq, &cp->txdb_work);239 break;240 case IMX_MU_TYPE_TXDB_V2:241 imx_mu_write(priv, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx),242 priv->dcfg->xCR[IMX_MU_GCR]);243 ret = readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val,244 !(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)),245 0, 1000);246 if (ret)247 dev_warn_ratelimited(priv->dev, "channel type: %d failure\n", cp->type);248 break;249 default:250 dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);251 return -EINVAL;252 }253 254 return 0;255}256 257static int imx_mu_generic_rx(struct imx_mu_priv *priv,258 struct imx_mu_con_priv *cp)259{260 u32 dat;261 262 dat = imx_mu_read(priv, priv->dcfg->xRR + (cp->idx) * 4);263 mbox_chan_received_data(cp->chan, (void *)&dat);264 265 return 0;266}267 268static int imx_mu_generic_rxdb(struct imx_mu_priv *priv,269 struct imx_mu_con_priv *cp)270{271 imx_mu_write(priv, IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx),272 priv->dcfg->xSR[IMX_MU_GSR]);273 mbox_chan_received_data(cp->chan, NULL);274 275 return 0;276}277 278static int imx_mu_specific_tx(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp, void *data)279{280 u32 *arg = data;281 u32 num_tr = priv->num_tr;282 int i, ret;283 u32 xsr;284 u32 size, max_size;285 286 if (priv->dcfg->type & IMX_MU_V2_S4) {287 size = ((struct imx_s4_rpc_msg_max *)data)->hdr.size;288 max_size = sizeof(struct imx_s4_rpc_msg_max);289 } else {290 size = ((struct imx_sc_rpc_msg_max *)data)->hdr.size;291 max_size = sizeof(struct imx_sc_rpc_msg_max);292 }293 294 switch (cp->type) {295 case IMX_MU_TYPE_TX:296 /*297 * msg->hdr.size specifies the number of u32 words while298 * sizeof yields bytes.299 */300 301 if (size > max_size / 4) {302 /*303 * The real message size can be different to304 * struct imx_sc_rpc_msg_max/imx_s4_rpc_msg_max size305 */306 dev_err(priv->dev, "Maximal message size (%u bytes) exceeded on TX; got: %i bytes\n", max_size, size << 2);307 return -EINVAL;308 }309 310 for (i = 0; i < num_tr && i < size; i++)311 imx_mu_write(priv, *arg++, priv->dcfg->xTR + (i % num_tr) * 4);312 for (; i < size; i++) {313 ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_TSR],314 xsr,315 xsr & IMX_MU_xSR_TEn(priv->dcfg->type, i % num_tr),316 0, 5 * USEC_PER_SEC);317 if (ret) {318 dev_err(priv->dev, "Send data index: %d timeout\n", i);319 return ret;320 }321 imx_mu_write(priv, *arg++, priv->dcfg->xTR + (i % num_tr) * 4);322 }323 324 imx_mu_xcr_rmw(priv, IMX_MU_TCR, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx), 0);325 break;326 default:327 dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);328 return -EINVAL;329 }330 331 return 0;332}333 334static int imx_mu_specific_rx(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp)335{336 u32 *data;337 int i, ret;338 u32 xsr;339 u32 size, max_size;340 u32 num_rr = priv->num_rr;341 342 data = (u32 *)priv->msg;343 344 imx_mu_xcr_rmw(priv, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(priv->dcfg->type, 0));345 *data++ = imx_mu_read(priv, priv->dcfg->xRR);346 347 if (priv->dcfg->type & IMX_MU_V2_S4) {348 size = ((struct imx_s4_rpc_msg_max *)priv->msg)->hdr.size;349 max_size = sizeof(struct imx_s4_rpc_msg_max);350 } else {351 size = ((struct imx_sc_rpc_msg_max *)priv->msg)->hdr.size;352 max_size = sizeof(struct imx_sc_rpc_msg_max);353 }354 355 if (size > max_size / 4) {356 dev_err(priv->dev, "Maximal message size (%u bytes) exceeded on RX; got: %i bytes\n", max_size, size << 2);357 return -EINVAL;358 }359 360 for (i = 1; i < size; i++) {361 ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_RSR], xsr,362 xsr & IMX_MU_xSR_RFn(priv->dcfg->type, i % num_rr), 0,363 5 * USEC_PER_SEC);364 if (ret) {365 dev_err(priv->dev, "timeout read idx %d\n", i);366 return ret;367 }368 *data++ = imx_mu_read(priv, priv->dcfg->xRR + (i % num_rr) * 4);369 }370 371 imx_mu_xcr_rmw(priv, IMX_MU_RCR, IMX_MU_xCR_RIEn(priv->dcfg->type, 0), 0);372 mbox_chan_received_data(cp->chan, (void *)priv->msg);373 374 return 0;375}376 377static int imx_mu_seco_tx(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp,378 void *data)379{380 struct imx_sc_rpc_msg_max *msg = data;381 u32 *arg = data;382 u32 byte_size;383 int err;384 int i;385 386 dev_dbg(priv->dev, "Sending message\n");387 388 switch (cp->type) {389 case IMX_MU_TYPE_TXDB:390 byte_size = msg->hdr.size * sizeof(u32);391 if (byte_size > sizeof(*msg)) {392 /*393 * The real message size can be different to394 * struct imx_sc_rpc_msg_max size395 */396 dev_err(priv->dev,397 "Exceed max msg size (%zu) on TX, got: %i\n",398 sizeof(*msg), byte_size);399 return -EINVAL;400 }401 402 print_hex_dump_debug("from client ", DUMP_PREFIX_OFFSET, 4, 4,403 data, byte_size, false);404 405 /* Send first word */406 dev_dbg(priv->dev, "Sending header\n");407 imx_mu_write(priv, *arg++, priv->dcfg->xTR);408 409 /* Send signaling */410 dev_dbg(priv->dev, "Sending signaling\n");411 imx_mu_xcr_rmw(priv, IMX_MU_GCR,412 IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);413 414 /* Send words to fill the mailbox */415 for (i = 1; i < 4 && i < msg->hdr.size; i++) {416 dev_dbg(priv->dev, "Sending word %d\n", i);417 imx_mu_write(priv, *arg++,418 priv->dcfg->xTR + (i % 4) * 4);419 }420 421 /* Send rest of message waiting for remote read */422 for (; i < msg->hdr.size; i++) {423 dev_dbg(priv->dev, "Sending word %d\n", i);424 err = imx_mu_tx_waiting_write(priv, *arg++, i);425 if (err) {426 dev_err(priv->dev, "Timeout tx %d\n", i);427 return err;428 }429 }430 431 /* Simulate hack for mbox framework */432 queue_work(system_bh_wq, &cp->txdb_work);433 434 break;435 default:436 dev_warn_ratelimited(priv->dev,437 "Send data on wrong channel type: %d\n",438 cp->type);439 return -EINVAL;440 }441 442 return 0;443}444 445static int imx_mu_seco_rxdb(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp)446{447 struct imx_sc_rpc_msg_max msg;448 u32 *data = (u32 *)&msg;449 u32 byte_size;450 int err = 0;451 int i;452 453 dev_dbg(priv->dev, "Receiving message\n");454 455 /* Read header */456 dev_dbg(priv->dev, "Receiving header\n");457 *data++ = imx_mu_read(priv, priv->dcfg->xRR);458 byte_size = msg.hdr.size * sizeof(u32);459 if (byte_size > sizeof(msg)) {460 dev_err(priv->dev, "Exceed max msg size (%zu) on RX, got: %i\n",461 sizeof(msg), byte_size);462 err = -EINVAL;463 goto error;464 }465 466 /* Read message waiting they are written */467 for (i = 1; i < msg.hdr.size; i++) {468 dev_dbg(priv->dev, "Receiving word %d\n", i);469 err = imx_mu_rx_waiting_read(priv, data++, i);470 if (err) {471 dev_err(priv->dev, "Timeout rx %d\n", i);472 goto error;473 }474 }475 476 /* Clear GIP */477 imx_mu_write(priv, IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx),478 priv->dcfg->xSR[IMX_MU_GSR]);479 480 print_hex_dump_debug("to client ", DUMP_PREFIX_OFFSET, 4, 4,481 &msg, byte_size, false);482 483 /* send data to client */484 dev_dbg(priv->dev, "Sending message to client\n");485 mbox_chan_received_data(cp->chan, (void *)&msg);486 487 goto exit;488 489error:490 mbox_chan_received_data(cp->chan, ERR_PTR(err));491 492exit:493 return err;494}495 496static void imx_mu_txdb_work(struct work_struct *t)497{498 struct imx_mu_con_priv *cp = from_work(cp, t, txdb_work);499 500 mbox_chan_txdone(cp->chan, 0);501}502 503static irqreturn_t imx_mu_isr(int irq, void *p)504{505 struct mbox_chan *chan = p;506 struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);507 struct imx_mu_con_priv *cp = chan->con_priv;508 u32 val, ctrl;509 510 switch (cp->type) {511 case IMX_MU_TYPE_TX:512 ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_TCR]);513 val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_TSR]);514 val &= IMX_MU_xSR_TEn(priv->dcfg->type, cp->idx) &515 (ctrl & IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));516 break;517 case IMX_MU_TYPE_RX:518 ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_RCR]);519 val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_RSR]);520 val &= IMX_MU_xSR_RFn(priv->dcfg->type, cp->idx) &521 (ctrl & IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx));522 break;523 case IMX_MU_TYPE_RXDB:524 ctrl = imx_mu_read(priv, priv->dcfg->xCR[IMX_MU_GIER]);525 val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_GSR]);526 val &= IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx) &527 (ctrl & IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));528 break;529 case IMX_MU_TYPE_RST:530 return IRQ_NONE;531 default:532 dev_warn_ratelimited(priv->dev, "Unhandled channel type %d\n",533 cp->type);534 return IRQ_NONE;535 }536 537 if (!val)538 return IRQ_NONE;539 540 if ((val == IMX_MU_xSR_TEn(priv->dcfg->type, cp->idx)) &&541 (cp->type == IMX_MU_TYPE_TX)) {542 imx_mu_xcr_rmw(priv, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));543 mbox_chan_txdone(chan, 0);544 } else if ((val == IMX_MU_xSR_RFn(priv->dcfg->type, cp->idx)) &&545 (cp->type == IMX_MU_TYPE_RX)) {546 priv->dcfg->rx(priv, cp);547 } else if ((val == IMX_MU_xSR_GIPn(priv->dcfg->type, cp->idx)) &&548 (cp->type == IMX_MU_TYPE_RXDB)) {549 priv->dcfg->rxdb(priv, cp);550 } else {551 dev_warn_ratelimited(priv->dev, "Not handled interrupt\n");552 return IRQ_NONE;553 }554 555 if (priv->suspend)556 pm_system_wakeup();557 558 return IRQ_HANDLED;559}560 561static int imx_mu_send_data(struct mbox_chan *chan, void *data)562{563 struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);564 struct imx_mu_con_priv *cp = chan->con_priv;565 566 return priv->dcfg->tx(priv, cp, data);567}568 569static int imx_mu_startup(struct mbox_chan *chan)570{571 struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);572 struct imx_mu_con_priv *cp = chan->con_priv;573 unsigned long irq_flag = 0;574 int ret;575 576 pm_runtime_get_sync(priv->dev);577 if (cp->type == IMX_MU_TYPE_TXDB_V2)578 return 0;579 580 if (cp->type == IMX_MU_TYPE_TXDB) {581 /* Tx doorbell don't have ACK support */582 INIT_WORK(&cp->txdb_work, imx_mu_txdb_work);583 return 0;584 }585 586 /* IPC MU should be with IRQF_NO_SUSPEND set */587 if (!priv->dev->pm_domain)588 irq_flag |= IRQF_NO_SUSPEND;589 590 if (!(priv->dcfg->type & IMX_MU_V2_IRQ))591 irq_flag |= IRQF_SHARED;592 593 ret = request_irq(priv->irq[cp->type], imx_mu_isr, irq_flag, cp->irq_desc, chan);594 if (ret) {595 dev_err(priv->dev, "Unable to acquire IRQ %d\n", priv->irq[cp->type]);596 return ret;597 }598 599 switch (cp->type) {600 case IMX_MU_TYPE_RX:601 imx_mu_xcr_rmw(priv, IMX_MU_RCR, IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx), 0);602 break;603 case IMX_MU_TYPE_RXDB:604 imx_mu_xcr_rmw(priv, IMX_MU_GIER, IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx), 0);605 break;606 default:607 break;608 }609 610 return 0;611}612 613static void imx_mu_shutdown(struct mbox_chan *chan)614{615 struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);616 struct imx_mu_con_priv *cp = chan->con_priv;617 int ret;618 u32 sr;619 620 if (cp->type == IMX_MU_TYPE_TXDB_V2) {621 pm_runtime_put_sync(priv->dev);622 return;623 }624 625 if (cp->type == IMX_MU_TYPE_TXDB) {626 cancel_work_sync(&cp->txdb_work);627 pm_runtime_put_sync(priv->dev);628 return;629 }630 631 switch (cp->type) {632 case IMX_MU_TYPE_TX:633 imx_mu_xcr_rmw(priv, IMX_MU_TCR, 0, IMX_MU_xCR_TIEn(priv->dcfg->type, cp->idx));634 break;635 case IMX_MU_TYPE_RX:636 imx_mu_xcr_rmw(priv, IMX_MU_RCR, 0, IMX_MU_xCR_RIEn(priv->dcfg->type, cp->idx));637 break;638 case IMX_MU_TYPE_RXDB:639 imx_mu_xcr_rmw(priv, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(priv->dcfg->type, cp->idx));640 break;641 case IMX_MU_TYPE_RST:642 imx_mu_xcr_rmw(priv, IMX_MU_CR, IMX_MU_xCR_RST(priv->dcfg->type), 0);643 ret = readl_poll_timeout(priv->base + priv->dcfg->xSR[IMX_MU_SR], sr,644 !(sr & IMX_MU_xSR_RST(priv->dcfg->type)), 1, 5);645 if (ret)646 dev_warn(priv->dev, "RST channel timeout\n");647 break;648 default:649 break;650 }651 652 free_irq(priv->irq[cp->type], chan);653 pm_runtime_put_sync(priv->dev);654}655 656static const struct mbox_chan_ops imx_mu_ops = {657 .send_data = imx_mu_send_data,658 .startup = imx_mu_startup,659 .shutdown = imx_mu_shutdown,660};661 662static struct mbox_chan *imx_mu_specific_xlate(struct mbox_controller *mbox,663 const struct of_phandle_args *sp)664{665 u32 type, idx, chan;666 667 if (sp->args_count != 2) {668 dev_err(mbox->dev, "Invalid argument count %d\n", sp->args_count);669 return ERR_PTR(-EINVAL);670 }671 672 type = sp->args[0]; /* channel type */673 idx = sp->args[1]; /* index */674 675 switch (type) {676 case IMX_MU_TYPE_TX:677 case IMX_MU_TYPE_RX:678 if (idx != 0)679 dev_err(mbox->dev, "Invalid chan idx: %d\n", idx);680 chan = type;681 break;682 case IMX_MU_TYPE_RXDB:683 chan = 2 + idx;684 break;685 default:686 dev_err(mbox->dev, "Invalid chan type: %d\n", type);687 return ERR_PTR(-EINVAL);688 }689 690 if (chan >= mbox->num_chans) {691 dev_err(mbox->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", chan, type, idx);692 return ERR_PTR(-EINVAL);693 }694 695 return &mbox->chans[chan];696}697 698static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,699 const struct of_phandle_args *sp)700{701 struct mbox_chan *p_chan;702 u32 type, idx, chan;703 704 if (sp->args_count != 2) {705 dev_err(mbox->dev, "Invalid argument count %d\n", sp->args_count);706 return ERR_PTR(-EINVAL);707 }708 709 type = sp->args[0]; /* channel type */710 idx = sp->args[1]; /* index */711 712 /* RST only supports 1 channel */713 if ((type == IMX_MU_TYPE_RST) && idx) {714 dev_err(mbox->dev, "Invalid RST channel %d\n", idx);715 return ERR_PTR(-EINVAL);716 }717 718 chan = type * 4 + idx;719 if (chan >= mbox->num_chans) {720 dev_err(mbox->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", chan, type, idx);721 return ERR_PTR(-EINVAL);722 }723 724 p_chan = &mbox->chans[chan];725 726 if (type == IMX_MU_TYPE_TXDB_V2)727 p_chan->txdone_method = TXDONE_BY_ACK;728 729 return p_chan;730}731 732static struct mbox_chan *imx_mu_seco_xlate(struct mbox_controller *mbox,733 const struct of_phandle_args *sp)734{735 u32 type;736 737 if (sp->args_count < 1) {738 dev_err(mbox->dev, "Invalid argument count %d\n", sp->args_count);739 return ERR_PTR(-EINVAL);740 }741 742 type = sp->args[0]; /* channel type */743 744 /* Only supports TXDB and RXDB */745 if (type == IMX_MU_TYPE_TX || type == IMX_MU_TYPE_RX) {746 dev_err(mbox->dev, "Invalid type: %d\n", type);747 return ERR_PTR(-EINVAL);748 }749 750 return imx_mu_xlate(mbox, sp);751}752 753static void imx_mu_get_tr_rr(struct imx_mu_priv *priv)754{755 u32 val;756 757 if (priv->dcfg->type & IMX_MU_V2) {758 val = imx_mu_read(priv, IMX_MU_V2_PAR_OFF);759 priv->num_tr = FIELD_GET(IMX_MU_V2_TR_MASK, val);760 priv->num_rr = FIELD_GET(IMX_MU_V2_RR_MASK, val);761 } else {762 priv->num_tr = 4;763 priv->num_rr = 4;764 }765}766 767static int imx_mu_init_generic(struct imx_mu_priv *priv)768{769 unsigned int i;770 unsigned int val;771 772 if (priv->num_rr > 4 || priv->num_tr > 4) {773 WARN_ONCE(true, "%s not support TR/RR larger than 4\n", __func__);774 return -EOPNOTSUPP;775 }776 777 for (i = 0; i < IMX_MU_CHANS; i++) {778 struct imx_mu_con_priv *cp = &priv->con_priv[i];779 780 cp->idx = i % 4;781 cp->type = i >> 2;782 cp->chan = &priv->mbox_chans[i];783 priv->mbox_chans[i].con_priv = cp;784 snprintf(cp->irq_desc, sizeof(cp->irq_desc),785 "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);786 }787 788 priv->mbox.num_chans = IMX_MU_CHANS;789 priv->mbox.of_xlate = imx_mu_xlate;790 791 if (priv->side_b)792 return 0;793 794 /* Set default MU configuration */795 for (i = 0; i < IMX_MU_xCR_MAX; i++)796 imx_mu_write(priv, 0, priv->dcfg->xCR[i]);797 798 /* Clear any pending GIP */799 val = imx_mu_read(priv, priv->dcfg->xSR[IMX_MU_GSR]);800 imx_mu_write(priv, val, priv->dcfg->xSR[IMX_MU_GSR]);801 802 /* Clear any pending RSR */803 for (i = 0; i < priv->num_rr; i++)804 imx_mu_read(priv, priv->dcfg->xRR + i * 4);805 806 return 0;807}808 809static int imx_mu_init_specific(struct imx_mu_priv *priv)810{811 unsigned int i;812 int num_chans = priv->dcfg->type & IMX_MU_V2_S4 ? IMX_MU_S4_CHANS : IMX_MU_SCU_CHANS;813 814 for (i = 0; i < num_chans; i++) {815 struct imx_mu_con_priv *cp = &priv->con_priv[i];816 817 cp->idx = i < 2 ? 0 : i - 2;818 cp->type = i < 2 ? i : IMX_MU_TYPE_RXDB;819 cp->chan = &priv->mbox_chans[i];820 priv->mbox_chans[i].con_priv = cp;821 snprintf(cp->irq_desc, sizeof(cp->irq_desc),822 "%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);823 }824 825 priv->mbox.num_chans = num_chans;826 priv->mbox.of_xlate = imx_mu_specific_xlate;827 828 /* Set default MU configuration */829 for (i = 0; i < IMX_MU_xCR_MAX; i++)830 imx_mu_write(priv, 0, priv->dcfg->xCR[i]);831 832 return 0;833}834 835static int imx_mu_init_seco(struct imx_mu_priv *priv)836{837 int ret;838 839 ret = imx_mu_init_generic(priv);840 if (ret)841 return ret;842 priv->mbox.of_xlate = imx_mu_seco_xlate;843 844 return 0;845}846 847static int imx_mu_probe(struct platform_device *pdev)848{849 struct device *dev = &pdev->dev;850 struct device_node *np = dev->of_node;851 struct imx_mu_priv *priv;852 const struct imx_mu_dcfg *dcfg;853 int i, ret;854 u32 size;855 856 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);857 if (!priv)858 return -ENOMEM;859 860 priv->dev = dev;861 862 priv->base = devm_platform_ioremap_resource(pdev, 0);863 if (IS_ERR(priv->base))864 return PTR_ERR(priv->base);865 866 dcfg = of_device_get_match_data(dev);867 if (!dcfg)868 return -EINVAL;869 priv->dcfg = dcfg;870 if (priv->dcfg->type & IMX_MU_V2_IRQ) {871 priv->irq[IMX_MU_TYPE_TX] = platform_get_irq_byname(pdev, "tx");872 if (priv->irq[IMX_MU_TYPE_TX] < 0)873 return priv->irq[IMX_MU_TYPE_TX];874 priv->irq[IMX_MU_TYPE_RX] = platform_get_irq_byname(pdev, "rx");875 if (priv->irq[IMX_MU_TYPE_RX] < 0)876 return priv->irq[IMX_MU_TYPE_RX];877 } else {878 ret = platform_get_irq(pdev, 0);879 if (ret < 0)880 return ret;881 882 for (i = 0; i < IMX_MU_CHANS; i++)883 priv->irq[i] = ret;884 }885 886 if (priv->dcfg->type & IMX_MU_V2_S4)887 size = sizeof(struct imx_s4_rpc_msg_max);888 else889 size = sizeof(struct imx_sc_rpc_msg_max);890 891 priv->msg = devm_kzalloc(dev, size, GFP_KERNEL);892 if (!priv->msg)893 return -ENOMEM;894 895 priv->clk = devm_clk_get(dev, NULL);896 if (IS_ERR(priv->clk)) {897 if (PTR_ERR(priv->clk) != -ENOENT)898 return PTR_ERR(priv->clk);899 900 priv->clk = NULL;901 }902 903 ret = clk_prepare_enable(priv->clk);904 if (ret) {905 dev_err(dev, "Failed to enable clock\n");906 return ret;907 }908 909 imx_mu_get_tr_rr(priv);910 911 priv->side_b = of_property_read_bool(np, "fsl,mu-side-b");912 913 ret = priv->dcfg->init(priv);914 if (ret) {915 dev_err(dev, "Failed to init MU\n");916 goto disable_clk;917 }918 919 spin_lock_init(&priv->xcr_lock);920 921 priv->mbox.dev = dev;922 priv->mbox.ops = &imx_mu_ops;923 priv->mbox.chans = priv->mbox_chans;924 priv->mbox.txdone_irq = true;925 926 platform_set_drvdata(pdev, priv);927 928 ret = devm_mbox_controller_register(dev, &priv->mbox);929 if (ret)930 goto disable_clk;931 932 of_platform_populate(dev->of_node, NULL, NULL, dev);933 934 pm_runtime_enable(dev);935 936 ret = pm_runtime_resume_and_get(dev);937 if (ret < 0)938 goto disable_runtime_pm;939 940 ret = pm_runtime_put_sync(dev);941 if (ret < 0)942 goto disable_runtime_pm;943 944 clk_disable_unprepare(priv->clk);945 946 return 0;947 948disable_runtime_pm:949 pm_runtime_disable(dev);950disable_clk:951 clk_disable_unprepare(priv->clk);952 return ret;953}954 955static void imx_mu_remove(struct platform_device *pdev)956{957 struct imx_mu_priv *priv = platform_get_drvdata(pdev);958 959 pm_runtime_disable(priv->dev);960}961 962static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = {963 .tx = imx_mu_generic_tx,964 .rx = imx_mu_generic_rx,965 .rxdb = imx_mu_generic_rxdb,966 .init = imx_mu_init_generic,967 .xTR = 0x0,968 .xRR = 0x10,969 .xSR = {0x20, 0x20, 0x20, 0x20},970 .xCR = {0x24, 0x24, 0x24, 0x24, 0x24},971};972 973static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {974 .tx = imx_mu_generic_tx,975 .rx = imx_mu_generic_rx,976 .rxdb = imx_mu_generic_rxdb,977 .init = imx_mu_init_generic,978 .xTR = 0x20,979 .xRR = 0x40,980 .xSR = {0x60, 0x60, 0x60, 0x60},981 .xCR = {0x64, 0x64, 0x64, 0x64, 0x64},982};983 984static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {985 .tx = imx_mu_generic_tx,986 .rx = imx_mu_generic_rx,987 .rxdb = imx_mu_generic_rxdb,988 .init = imx_mu_init_generic,989 .type = IMX_MU_V2,990 .xTR = 0x200,991 .xRR = 0x280,992 .xSR = {0xC, 0x118, 0x124, 0x12C},993 .xCR = {0x8, 0x110, 0x114, 0x120, 0x128},994};995 996static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp_s4 = {997 .tx = imx_mu_specific_tx,998 .rx = imx_mu_specific_rx,999 .init = imx_mu_init_specific,1000 .type = IMX_MU_V2 | IMX_MU_V2_S4,1001 .xTR = 0x200,1002 .xRR = 0x280,1003 .xSR = {0xC, 0x118, 0x124, 0x12C},1004 .xCR = {0x8, 0x110, 0x114, 0x120, 0x128},1005};1006 1007static const struct imx_mu_dcfg imx_mu_cfg_imx93_s4 = {1008 .tx = imx_mu_specific_tx,1009 .rx = imx_mu_specific_rx,1010 .init = imx_mu_init_specific,1011 .type = IMX_MU_V2 | IMX_MU_V2_S4 | IMX_MU_V2_IRQ,1012 .xTR = 0x200,1013 .xRR = 0x280,1014 .xSR = {0xC, 0x118, 0x124, 0x12C},1015 .xCR = {0x8, 0x110, 0x114, 0x120, 0x128},1016};1017 1018static const struct imx_mu_dcfg imx_mu_cfg_imx8_scu = {1019 .tx = imx_mu_specific_tx,1020 .rx = imx_mu_specific_rx,1021 .init = imx_mu_init_specific,1022 .rxdb = imx_mu_generic_rxdb,1023 .xTR = 0x0,1024 .xRR = 0x10,1025 .xSR = {0x20, 0x20, 0x20, 0x20},1026 .xCR = {0x24, 0x24, 0x24, 0x24, 0x24},1027};1028 1029static const struct imx_mu_dcfg imx_mu_cfg_imx8_seco = {1030 .tx = imx_mu_seco_tx,1031 .rx = imx_mu_generic_rx,1032 .rxdb = imx_mu_seco_rxdb,1033 .init = imx_mu_init_seco,1034 .xTR = 0x0,1035 .xRR = 0x10,1036 .xSR = {0x20, 0x20, 0x20, 0x20},1037 .xCR = {0x24, 0x24, 0x24, 0x24, 0x24},1038};1039 1040static const struct of_device_id imx_mu_dt_ids[] = {1041 { .compatible = "fsl,imx7ulp-mu", .data = &imx_mu_cfg_imx7ulp },1042 { .compatible = "fsl,imx6sx-mu", .data = &imx_mu_cfg_imx6sx },1043 { .compatible = "fsl,imx8ulp-mu", .data = &imx_mu_cfg_imx8ulp },1044 { .compatible = "fsl,imx8ulp-mu-s4", .data = &imx_mu_cfg_imx8ulp_s4 },1045 { .compatible = "fsl,imx93-mu-s4", .data = &imx_mu_cfg_imx93_s4 },1046 { .compatible = "fsl,imx95-mu", .data = &imx_mu_cfg_imx8ulp },1047 { .compatible = "fsl,imx95-mu-ele", .data = &imx_mu_cfg_imx8ulp_s4 },1048 { .compatible = "fsl,imx95-mu-v2x", .data = &imx_mu_cfg_imx8ulp_s4 },1049 { .compatible = "fsl,imx8-mu-scu", .data = &imx_mu_cfg_imx8_scu },1050 { .compatible = "fsl,imx8-mu-seco", .data = &imx_mu_cfg_imx8_seco },1051 { },1052};1053MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);1054 1055static int __maybe_unused imx_mu_suspend_noirq(struct device *dev)1056{1057 struct imx_mu_priv *priv = dev_get_drvdata(dev);1058 int i;1059 1060 if (!priv->clk) {1061 for (i = 0; i < IMX_MU_xCR_MAX; i++)1062 priv->xcr[i] = imx_mu_read(priv, priv->dcfg->xCR[i]);1063 }1064 1065 priv->suspend = true;1066 1067 return 0;1068}1069 1070static int __maybe_unused imx_mu_resume_noirq(struct device *dev)1071{1072 struct imx_mu_priv *priv = dev_get_drvdata(dev);1073 int i;1074 1075 /*1076 * ONLY restore MU when context lost, the TIE could1077 * be set during noirq resume as there is MU data1078 * communication going on, and restore the saved1079 * value will overwrite the TIE and cause MU data1080 * send failed, may lead to system freeze. This issue1081 * is observed by testing freeze mode suspend.1082 */1083 if (!priv->clk && !imx_mu_read(priv, priv->dcfg->xCR[0])) {1084 for (i = 0; i < IMX_MU_xCR_MAX; i++)1085 imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]);1086 }1087 1088 priv->suspend = false;1089 1090 return 0;1091}1092 1093static int __maybe_unused imx_mu_runtime_suspend(struct device *dev)1094{1095 struct imx_mu_priv *priv = dev_get_drvdata(dev);1096 1097 clk_disable_unprepare(priv->clk);1098 1099 return 0;1100}1101 1102static int __maybe_unused imx_mu_runtime_resume(struct device *dev)1103{1104 struct imx_mu_priv *priv = dev_get_drvdata(dev);1105 int ret;1106 1107 ret = clk_prepare_enable(priv->clk);1108 if (ret)1109 dev_err(dev, "failed to enable clock\n");1110 1111 return ret;1112}1113 1114static const struct dev_pm_ops imx_mu_pm_ops = {1115 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_mu_suspend_noirq,1116 imx_mu_resume_noirq)1117 SET_RUNTIME_PM_OPS(imx_mu_runtime_suspend,1118 imx_mu_runtime_resume, NULL)1119};1120 1121static struct platform_driver imx_mu_driver = {1122 .probe = imx_mu_probe,1123 .remove_new = imx_mu_remove,1124 .driver = {1125 .name = "imx_mu",1126 .of_match_table = imx_mu_dt_ids,1127 .pm = &imx_mu_pm_ops,1128 },1129};1130module_platform_driver(imx_mu_driver);1131 1132MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");1133MODULE_DESCRIPTION("Message Unit driver for i.MX");1134MODULE_LICENSE("GPL v2");1135