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