1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Spreadtrum mailbox driver 4 * 5 * Copyright (c) 2020 Spreadtrum Communications Inc. 6 */ 7 8#include <linux/delay.h> 9#include <linux/err.h> 10#include <linux/interrupt.h> 11#include <linux/io.h> 12#include <linux/mailbox_controller.h> 13#include <linux/module.h> 14#include <linux/platform_device.h> 15#include <linux/clk.h> 16 17#define SPRD_MBOX_ID 0x0 18#define SPRD_MBOX_MSG_LOW 0x4 19#define SPRD_MBOX_MSG_HIGH 0x8 20#define SPRD_MBOX_TRIGGER 0xc 21#define SPRD_MBOX_FIFO_RST 0x10 22#define SPRD_MBOX_FIFO_STS 0x14 23#define SPRD_MBOX_IRQ_STS 0x18 24#define SPRD_MBOX_IRQ_MSK 0x1c 25#define SPRD_MBOX_LOCK 0x20 26#define SPRD_MBOX_FIFO_DEPTH 0x24 27 28/* Bit and mask definiation for inbox's SPRD_MBOX_FIFO_STS register */ 29#define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16) 30#define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8) 31#define SPRD_INBOX_FIFO_DELIVER_SHIFT 16 32#define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0) 33 34/* Bit and mask definiation for SPRD_MBOX_IRQ_STS register */ 35#define SPRD_MBOX_IRQ_CLR BIT(0) 36 37/* Bit and mask definiation for outbox's SPRD_MBOX_FIFO_STS register */ 38#define SPRD_OUTBOX_FIFO_FULL BIT(2) 39#define SPRD_OUTBOX_FIFO_WR_SHIFT 16 40#define SPRD_OUTBOX_FIFO_RD_SHIFT 24 41#define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0) 42 43/* Bit and mask definiation for inbox's SPRD_MBOX_IRQ_MSK register */ 44#define SPRD_INBOX_FIFO_BLOCK_IRQ BIT(0) 45#define SPRD_INBOX_FIFO_OVERFLOW_IRQ BIT(1) 46#define SPRD_INBOX_FIFO_DELIVER_IRQ BIT(2) 47#define SPRD_INBOX_FIFO_IRQ_MASK GENMASK(2, 0) 48 49/* Bit and mask definiation for outbox's SPRD_MBOX_IRQ_MSK register */ 50#define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ BIT(0) 51#define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0) 52 53#define SPRD_MBOX_CHAN_MAX 8 54 55struct sprd_mbox_priv { 56 struct mbox_controller mbox; 57 struct device *dev; 58 void __iomem *inbox_base; 59 void __iomem *outbox_base; 60 struct clk *clk; 61 u32 outbox_fifo_depth; 62 63 struct mutex lock; 64 u32 refcnt; 65 struct mbox_chan chan[SPRD_MBOX_CHAN_MAX]; 66}; 67 68static struct sprd_mbox_priv *to_sprd_mbox_priv(struct mbox_controller *mbox) 69{ 70 return container_of(mbox, struct sprd_mbox_priv, mbox); 71} 72 73static u32 sprd_mbox_get_fifo_len(struct sprd_mbox_priv *priv, u32 fifo_sts) 74{ 75 u32 wr_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_WR_SHIFT) & 76 SPRD_OUTBOX_FIFO_POS_MASK; 77 u32 rd_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_RD_SHIFT) & 78 SPRD_OUTBOX_FIFO_POS_MASK; 79 u32 fifo_len; 80 81 /* 82 * If the read pointer is equal with write pointer, which means the fifo 83 * is full or empty. 84 */ 85 if (wr_pos == rd_pos) { 86 if (fifo_sts & SPRD_OUTBOX_FIFO_FULL) 87 fifo_len = priv->outbox_fifo_depth; 88 else 89 fifo_len = 0; 90 } else if (wr_pos > rd_pos) { 91 fifo_len = wr_pos - rd_pos; 92 } else { 93 fifo_len = priv->outbox_fifo_depth - rd_pos + wr_pos; 94 } 95 96 return fifo_len; 97} 98 99static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data) 100{ 101 struct sprd_mbox_priv *priv = data; 102 struct mbox_chan *chan; 103 u32 fifo_sts, fifo_len, msg[2]; 104 int i, id; 105 106 fifo_sts = readl(priv->outbox_base + SPRD_MBOX_FIFO_STS); 107 108 fifo_len = sprd_mbox_get_fifo_len(priv, fifo_sts); 109 if (!fifo_len) { 110 dev_warn_ratelimited(priv->dev, "spurious outbox interrupt\n"); 111 return IRQ_NONE; 112 } 113 114 for (i = 0; i < fifo_len; i++) { 115 msg[0] = readl(priv->outbox_base + SPRD_MBOX_MSG_LOW); 116 msg[1] = readl(priv->outbox_base + SPRD_MBOX_MSG_HIGH); 117 id = readl(priv->outbox_base + SPRD_MBOX_ID); 118 119 chan = &priv->chan[id]; 120 if (chan->cl) 121 mbox_chan_received_data(chan, (void *)msg); 122 else 123 dev_warn_ratelimited(priv->dev, 124 "message's been dropped at ch[%d]\n", id); 125 126 /* Trigger to update outbox FIFO pointer */ 127 writel(0x1, priv->outbox_base + SPRD_MBOX_TRIGGER); 128 } 129 130 /* Clear irq status after reading all message. */ 131 writel(SPRD_MBOX_IRQ_CLR, priv->outbox_base + SPRD_MBOX_IRQ_STS); 132 133 return IRQ_HANDLED; 134} 135 136static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data) 137{ 138 struct sprd_mbox_priv *priv = data; 139 struct mbox_chan *chan; 140 u32 fifo_sts, send_sts, busy, id; 141 142 fifo_sts = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS); 143 144 /* Get the inbox data delivery status */ 145 send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >> 146 SPRD_INBOX_FIFO_DELIVER_SHIFT; 147 if (!send_sts) { 148 dev_warn_ratelimited(priv->dev, "spurious inbox interrupt\n"); 149 return IRQ_NONE; 150 } 151 152 while (send_sts) { 153 id = __ffs(send_sts); 154 send_sts &= (send_sts - 1); 155 156 chan = &priv->chan[id]; 157 158 /* 159 * Check if the message was fetched by remote traget, if yes, 160 * that means the transmission has been completed. 161 */ 162 busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK; 163 if (!(busy & BIT(id))) 164 mbox_chan_txdone(chan, 0); 165 } 166 167 /* Clear FIFO delivery and overflow status */ 168 writel(fifo_sts & 169 (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK), 170 priv->inbox_base + SPRD_MBOX_FIFO_RST); 171 172 /* Clear irq status */ 173 writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS); 174 175 return IRQ_HANDLED; 176} 177 178static int sprd_mbox_send_data(struct mbox_chan *chan, void *msg) 179{ 180 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); 181 unsigned long id = (unsigned long)chan->con_priv; 182 u32 *data = msg; 183 184 /* Write data into inbox FIFO, and only support 8 bytes every time */ 185 writel(data[0], priv->inbox_base + SPRD_MBOX_MSG_LOW); 186 writel(data[1], priv->inbox_base + SPRD_MBOX_MSG_HIGH); 187 188 /* Set target core id */ 189 writel(id, priv->inbox_base + SPRD_MBOX_ID); 190 191 /* Trigger remote request */ 192 writel(0x1, priv->inbox_base + SPRD_MBOX_TRIGGER); 193 194 return 0; 195} 196 197static int sprd_mbox_flush(struct mbox_chan *chan, unsigned long timeout) 198{ 199 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); 200 unsigned long id = (unsigned long)chan->con_priv; 201 u32 busy; 202 203 timeout = jiffies + msecs_to_jiffies(timeout); 204 205 while (time_before(jiffies, timeout)) { 206 busy = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS) & 207 SPRD_INBOX_FIFO_BUSY_MASK; 208 if (!(busy & BIT(id))) { 209 mbox_chan_txdone(chan, 0); 210 return 0; 211 } 212 213 udelay(1); 214 } 215 216 return -ETIME; 217} 218 219static int sprd_mbox_startup(struct mbox_chan *chan) 220{ 221 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); 222 u32 val; 223 224 mutex_lock(&priv->lock); 225 if (priv->refcnt++ == 0) { 226 /* Select outbox FIFO mode and reset the outbox FIFO status */ 227 writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST); 228 229 /* Enable inbox FIFO overflow and delivery interrupt */ 230 val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK); 231 val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ); 232 writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK); 233 234 /* Enable outbox FIFO not empty interrupt */ 235 val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK); 236 val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ; 237 writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK); 238 } 239 mutex_unlock(&priv->lock); 240 241 return 0; 242} 243 244static void sprd_mbox_shutdown(struct mbox_chan *chan) 245{ 246 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox); 247 248 mutex_lock(&priv->lock); 249 if (--priv->refcnt == 0) { 250 /* Disable inbox & outbox interrupt */ 251 writel(SPRD_INBOX_FIFO_IRQ_MASK, priv->inbox_base + SPRD_MBOX_IRQ_MSK); 252 writel(SPRD_OUTBOX_FIFO_IRQ_MASK, priv->outbox_base + SPRD_MBOX_IRQ_MSK); 253 } 254 mutex_unlock(&priv->lock); 255} 256 257static const struct mbox_chan_ops sprd_mbox_ops = { 258 .send_data = sprd_mbox_send_data, 259 .flush = sprd_mbox_flush, 260 .startup = sprd_mbox_startup, 261 .shutdown = sprd_mbox_shutdown, 262}; 263 264static void sprd_mbox_disable(void *data) 265{ 266 struct sprd_mbox_priv *priv = data; 267 268 clk_disable_unprepare(priv->clk); 269} 270 271static int sprd_mbox_probe(struct platform_device *pdev) 272{ 273 struct device *dev = &pdev->dev; 274 struct sprd_mbox_priv *priv; 275 int ret, inbox_irq, outbox_irq; 276 unsigned long id; 277 278 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 279 if (!priv) 280 return -ENOMEM; 281 282 priv->dev = dev; 283 mutex_init(&priv->lock); 284 285 /* 286 * The Spreadtrum mailbox uses an inbox to send messages to the target 287 * core, and uses an outbox to receive messages from other cores. 288 * 289 * Thus the mailbox controller supplies 2 different register addresses 290 * and IRQ numbers for inbox and outbox. 291 */ 292 priv->inbox_base = devm_platform_ioremap_resource(pdev, 0); 293 if (IS_ERR(priv->inbox_base)) 294 return PTR_ERR(priv->inbox_base); 295 296 priv->outbox_base = devm_platform_ioremap_resource(pdev, 1); 297 if (IS_ERR(priv->outbox_base)) 298 return PTR_ERR(priv->outbox_base); 299 300 priv->clk = devm_clk_get(dev, "enable"); 301 if (IS_ERR(priv->clk)) { 302 dev_err(dev, "failed to get mailbox clock\n"); 303 return PTR_ERR(priv->clk); 304 } 305 306 ret = clk_prepare_enable(priv->clk); 307 if (ret) 308 return ret; 309 310 ret = devm_add_action_or_reset(dev, sprd_mbox_disable, priv); 311 if (ret) { 312 dev_err(dev, "failed to add mailbox disable action\n"); 313 return ret; 314 } 315 316 inbox_irq = platform_get_irq(pdev, 0); 317 if (inbox_irq < 0) 318 return inbox_irq; 319 320 ret = devm_request_irq(dev, inbox_irq, sprd_mbox_inbox_isr, 321 IRQF_NO_SUSPEND, dev_name(dev), priv); 322 if (ret) { 323 dev_err(dev, "failed to request inbox IRQ: %d\n", ret); 324 return ret; 325 } 326 327 outbox_irq = platform_get_irq(pdev, 1); 328 if (outbox_irq < 0) 329 return outbox_irq; 330 331 ret = devm_request_irq(dev, outbox_irq, sprd_mbox_outbox_isr, 332 IRQF_NO_SUSPEND, dev_name(dev), priv); 333 if (ret) { 334 dev_err(dev, "failed to request outbox IRQ: %d\n", ret); 335 return ret; 336 } 337 338 /* Get the default outbox FIFO depth */ 339 priv->outbox_fifo_depth = 340 readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1; 341 priv->mbox.dev = dev; 342 priv->mbox.chans = &priv->chan[0]; 343 priv->mbox.num_chans = SPRD_MBOX_CHAN_MAX; 344 priv->mbox.ops = &sprd_mbox_ops; 345 priv->mbox.txdone_irq = true; 346 347 for (id = 0; id < SPRD_MBOX_CHAN_MAX; id++) 348 priv->chan[id].con_priv = (void *)id; 349 350 ret = devm_mbox_controller_register(dev, &priv->mbox); 351 if (ret) { 352 dev_err(dev, "failed to register mailbox: %d\n", ret); 353 return ret; 354 } 355 356 return 0; 357} 358 359static const struct of_device_id sprd_mbox_of_match[] = { 360 { .compatible = "sprd,sc9860-mailbox", }, 361 { }, 362}; 363MODULE_DEVICE_TABLE(of, sprd_mbox_of_match); 364 365static struct platform_driver sprd_mbox_driver = { 366 .driver = { 367 .name = "sprd-mailbox", 368 .of_match_table = sprd_mbox_of_match, 369 }, 370 .probe = sprd_mbox_probe, 371}; 372module_platform_driver(sprd_mbox_driver); 373 374MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>"); 375MODULE_DESCRIPTION("Spreadtrum mailbox driver"); 376MODULE_LICENSE("GPL v2"); 377