0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/io.h>
0012 #include <linux/mailbox_controller.h>
0013 #include <linux/module.h>
0014 #include <linux/of_device.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/clk.h>
0017
0018 #define SPRD_MBOX_ID 0x0
0019 #define SPRD_MBOX_MSG_LOW 0x4
0020 #define SPRD_MBOX_MSG_HIGH 0x8
0021 #define SPRD_MBOX_TRIGGER 0xc
0022 #define SPRD_MBOX_FIFO_RST 0x10
0023 #define SPRD_MBOX_FIFO_STS 0x14
0024 #define SPRD_MBOX_IRQ_STS 0x18
0025 #define SPRD_MBOX_IRQ_MSK 0x1c
0026 #define SPRD_MBOX_LOCK 0x20
0027 #define SPRD_MBOX_FIFO_DEPTH 0x24
0028
0029
0030 #define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16)
0031 #define SPRD_INBOX_FIFO_OVERLOW_MASK GENMASK(15, 8)
0032 #define SPRD_INBOX_FIFO_DELIVER_SHIFT 16
0033 #define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0)
0034
0035
0036 #define SPRD_MBOX_IRQ_CLR BIT(0)
0037
0038
0039 #define SPRD_OUTBOX_FIFO_FULL BIT(2)
0040 #define SPRD_OUTBOX_FIFO_WR_SHIFT 16
0041 #define SPRD_OUTBOX_FIFO_RD_SHIFT 24
0042 #define SPRD_OUTBOX_FIFO_POS_MASK GENMASK(7, 0)
0043
0044
0045 #define SPRD_INBOX_FIFO_BLOCK_IRQ BIT(0)
0046 #define SPRD_INBOX_FIFO_OVERFLOW_IRQ BIT(1)
0047 #define SPRD_INBOX_FIFO_DELIVER_IRQ BIT(2)
0048 #define SPRD_INBOX_FIFO_IRQ_MASK GENMASK(2, 0)
0049
0050
0051 #define SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ BIT(0)
0052 #define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0)
0053
0054 #define SPRD_OUTBOX_BASE_SPAN 0x1000
0055 #define SPRD_MBOX_CHAN_MAX 8
0056 #define SPRD_SUPP_INBOX_ID_SC9863A 7
0057
0058 struct sprd_mbox_priv {
0059 struct mbox_controller mbox;
0060 struct device *dev;
0061 void __iomem *inbox_base;
0062 void __iomem *outbox_base;
0063
0064 void __iomem *supp_base;
0065 struct clk *clk;
0066 u32 outbox_fifo_depth;
0067
0068 struct mutex lock;
0069 u32 refcnt;
0070 struct mbox_chan chan[SPRD_MBOX_CHAN_MAX];
0071 };
0072
0073 static struct sprd_mbox_priv *to_sprd_mbox_priv(struct mbox_controller *mbox)
0074 {
0075 return container_of(mbox, struct sprd_mbox_priv, mbox);
0076 }
0077
0078 static u32 sprd_mbox_get_fifo_len(struct sprd_mbox_priv *priv, u32 fifo_sts)
0079 {
0080 u32 wr_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_WR_SHIFT) &
0081 SPRD_OUTBOX_FIFO_POS_MASK;
0082 u32 rd_pos = (fifo_sts >> SPRD_OUTBOX_FIFO_RD_SHIFT) &
0083 SPRD_OUTBOX_FIFO_POS_MASK;
0084 u32 fifo_len;
0085
0086
0087
0088
0089
0090 if (wr_pos == rd_pos) {
0091 if (fifo_sts & SPRD_OUTBOX_FIFO_FULL)
0092 fifo_len = priv->outbox_fifo_depth;
0093 else
0094 fifo_len = 0;
0095 } else if (wr_pos > rd_pos) {
0096 fifo_len = wr_pos - rd_pos;
0097 } else {
0098 fifo_len = priv->outbox_fifo_depth - rd_pos + wr_pos;
0099 }
0100
0101 return fifo_len;
0102 }
0103
0104 static irqreturn_t do_outbox_isr(void __iomem *base, struct sprd_mbox_priv *priv)
0105 {
0106 struct mbox_chan *chan;
0107 u32 fifo_sts, fifo_len, msg[2];
0108 int i, id;
0109
0110 fifo_sts = readl(base + SPRD_MBOX_FIFO_STS);
0111
0112 fifo_len = sprd_mbox_get_fifo_len(priv, fifo_sts);
0113 if (!fifo_len) {
0114 dev_warn_ratelimited(priv->dev, "spurious outbox interrupt\n");
0115 return IRQ_NONE;
0116 }
0117
0118 for (i = 0; i < fifo_len; i++) {
0119 msg[0] = readl(base + SPRD_MBOX_MSG_LOW);
0120 msg[1] = readl(base + SPRD_MBOX_MSG_HIGH);
0121 id = readl(base + SPRD_MBOX_ID);
0122
0123 chan = &priv->chan[id];
0124 if (chan->cl)
0125 mbox_chan_received_data(chan, (void *)msg);
0126 else
0127 dev_warn_ratelimited(priv->dev,
0128 "message's been dropped at ch[%d]\n", id);
0129
0130
0131 writel(0x1, base + SPRD_MBOX_TRIGGER);
0132 }
0133
0134
0135 writel(SPRD_MBOX_IRQ_CLR, base + SPRD_MBOX_IRQ_STS);
0136
0137 return IRQ_HANDLED;
0138 }
0139
0140 static irqreturn_t sprd_mbox_outbox_isr(int irq, void *data)
0141 {
0142 struct sprd_mbox_priv *priv = data;
0143
0144 return do_outbox_isr(priv->outbox_base, priv);
0145 }
0146
0147 static irqreturn_t sprd_mbox_supp_isr(int irq, void *data)
0148 {
0149 struct sprd_mbox_priv *priv = data;
0150
0151 return do_outbox_isr(priv->supp_base, priv);
0152 }
0153
0154 static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
0155 {
0156 struct sprd_mbox_priv *priv = data;
0157 struct mbox_chan *chan;
0158 u32 fifo_sts, send_sts, busy, id;
0159
0160 fifo_sts = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS);
0161
0162
0163 send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
0164 SPRD_INBOX_FIFO_DELIVER_SHIFT;
0165 if (!send_sts) {
0166 dev_warn_ratelimited(priv->dev, "spurious inbox interrupt\n");
0167 return IRQ_NONE;
0168 }
0169
0170 while (send_sts) {
0171 id = __ffs(send_sts);
0172 send_sts &= (send_sts - 1);
0173
0174 chan = &priv->chan[id];
0175
0176
0177
0178
0179
0180 busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
0181 if (!(busy & BIT(id)))
0182 mbox_chan_txdone(chan, 0);
0183 }
0184
0185
0186 writel(fifo_sts &
0187 (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
0188 priv->inbox_base + SPRD_MBOX_FIFO_RST);
0189
0190
0191 writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS);
0192
0193 return IRQ_HANDLED;
0194 }
0195
0196 static int sprd_mbox_send_data(struct mbox_chan *chan, void *msg)
0197 {
0198 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
0199 unsigned long id = (unsigned long)chan->con_priv;
0200 u32 *data = msg;
0201
0202
0203 writel(data[0], priv->inbox_base + SPRD_MBOX_MSG_LOW);
0204 writel(data[1], priv->inbox_base + SPRD_MBOX_MSG_HIGH);
0205
0206
0207 writel(id, priv->inbox_base + SPRD_MBOX_ID);
0208
0209
0210 writel(0x1, priv->inbox_base + SPRD_MBOX_TRIGGER);
0211
0212 return 0;
0213 }
0214
0215 static int sprd_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
0216 {
0217 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
0218 unsigned long id = (unsigned long)chan->con_priv;
0219 u32 busy;
0220
0221 timeout = jiffies + msecs_to_jiffies(timeout);
0222
0223 while (time_before(jiffies, timeout)) {
0224 busy = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS) &
0225 SPRD_INBOX_FIFO_BUSY_MASK;
0226 if (!(busy & BIT(id))) {
0227 mbox_chan_txdone(chan, 0);
0228 return 0;
0229 }
0230
0231 udelay(1);
0232 }
0233
0234 return -ETIME;
0235 }
0236
0237 static int sprd_mbox_startup(struct mbox_chan *chan)
0238 {
0239 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
0240 u32 val;
0241
0242 mutex_lock(&priv->lock);
0243 if (priv->refcnt++ == 0) {
0244
0245 writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST);
0246
0247
0248 val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK);
0249 val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ);
0250 writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
0251
0252
0253 val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK);
0254 val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
0255 writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
0256
0257
0258 if (priv->supp_base) {
0259 writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST);
0260 val = readl(priv->supp_base + SPRD_MBOX_IRQ_MSK);
0261 val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
0262 writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK);
0263 }
0264 }
0265 mutex_unlock(&priv->lock);
0266
0267 return 0;
0268 }
0269
0270 static void sprd_mbox_shutdown(struct mbox_chan *chan)
0271 {
0272 struct sprd_mbox_priv *priv = to_sprd_mbox_priv(chan->mbox);
0273
0274 mutex_lock(&priv->lock);
0275 if (--priv->refcnt == 0) {
0276
0277 writel(SPRD_INBOX_FIFO_IRQ_MASK, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
0278 writel(SPRD_OUTBOX_FIFO_IRQ_MASK, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
0279
0280 if (priv->supp_base)
0281 writel(SPRD_OUTBOX_FIFO_IRQ_MASK,
0282 priv->supp_base + SPRD_MBOX_IRQ_MSK);
0283 }
0284 mutex_unlock(&priv->lock);
0285 }
0286
0287 static const struct mbox_chan_ops sprd_mbox_ops = {
0288 .send_data = sprd_mbox_send_data,
0289 .flush = sprd_mbox_flush,
0290 .startup = sprd_mbox_startup,
0291 .shutdown = sprd_mbox_shutdown,
0292 };
0293
0294 static void sprd_mbox_disable(void *data)
0295 {
0296 struct sprd_mbox_priv *priv = data;
0297
0298 clk_disable_unprepare(priv->clk);
0299 }
0300
0301 static int sprd_mbox_probe(struct platform_device *pdev)
0302 {
0303 struct device *dev = &pdev->dev;
0304 struct sprd_mbox_priv *priv;
0305 int ret, inbox_irq, outbox_irq, supp_irq;
0306 unsigned long id, supp;
0307
0308 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0309 if (!priv)
0310 return -ENOMEM;
0311
0312 priv->dev = dev;
0313 mutex_init(&priv->lock);
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326 priv->inbox_base = devm_platform_ioremap_resource(pdev, 0);
0327 if (IS_ERR(priv->inbox_base))
0328 return PTR_ERR(priv->inbox_base);
0329
0330 priv->outbox_base = devm_platform_ioremap_resource(pdev, 1);
0331 if (IS_ERR(priv->outbox_base))
0332 return PTR_ERR(priv->outbox_base);
0333
0334 priv->clk = devm_clk_get(dev, "enable");
0335 if (IS_ERR(priv->clk)) {
0336 dev_err(dev, "failed to get mailbox clock\n");
0337 return PTR_ERR(priv->clk);
0338 }
0339
0340 ret = clk_prepare_enable(priv->clk);
0341 if (ret)
0342 return ret;
0343
0344 ret = devm_add_action_or_reset(dev, sprd_mbox_disable, priv);
0345 if (ret) {
0346 dev_err(dev, "failed to add mailbox disable action\n");
0347 return ret;
0348 }
0349
0350 inbox_irq = platform_get_irq_byname(pdev, "inbox");
0351 if (inbox_irq < 0)
0352 return inbox_irq;
0353
0354 ret = devm_request_irq(dev, inbox_irq, sprd_mbox_inbox_isr,
0355 IRQF_NO_SUSPEND, dev_name(dev), priv);
0356 if (ret) {
0357 dev_err(dev, "failed to request inbox IRQ: %d\n", ret);
0358 return ret;
0359 }
0360
0361 outbox_irq = platform_get_irq_byname(pdev, "outbox");
0362 if (outbox_irq < 0)
0363 return outbox_irq;
0364
0365 ret = devm_request_irq(dev, outbox_irq, sprd_mbox_outbox_isr,
0366 IRQF_NO_SUSPEND, dev_name(dev), priv);
0367 if (ret) {
0368 dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
0369 return ret;
0370 }
0371
0372
0373 supp_irq = platform_get_irq_byname(pdev, "supp-outbox");
0374 if (supp_irq > 0) {
0375 ret = devm_request_irq(dev, supp_irq, sprd_mbox_supp_isr,
0376 IRQF_NO_SUSPEND, dev_name(dev), priv);
0377 if (ret) {
0378 dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
0379 return ret;
0380 }
0381
0382 supp = (unsigned long) of_device_get_match_data(dev);
0383 if (!supp) {
0384 dev_err(dev, "no supplementary outbox specified\n");
0385 return -ENODEV;
0386 }
0387 priv->supp_base = priv->outbox_base + (SPRD_OUTBOX_BASE_SPAN * supp);
0388 }
0389
0390
0391 priv->outbox_fifo_depth =
0392 readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
0393 priv->mbox.dev = dev;
0394 priv->mbox.chans = &priv->chan[0];
0395 priv->mbox.num_chans = SPRD_MBOX_CHAN_MAX;
0396 priv->mbox.ops = &sprd_mbox_ops;
0397 priv->mbox.txdone_irq = true;
0398
0399 for (id = 0; id < SPRD_MBOX_CHAN_MAX; id++)
0400 priv->chan[id].con_priv = (void *)id;
0401
0402 ret = devm_mbox_controller_register(dev, &priv->mbox);
0403 if (ret) {
0404 dev_err(dev, "failed to register mailbox: %d\n", ret);
0405 return ret;
0406 }
0407
0408 return 0;
0409 }
0410
0411 static const struct of_device_id sprd_mbox_of_match[] = {
0412 { .compatible = "sprd,sc9860-mailbox" },
0413 { .compatible = "sprd,sc9863a-mailbox",
0414 .data = (void *)SPRD_SUPP_INBOX_ID_SC9863A },
0415 { },
0416 };
0417 MODULE_DEVICE_TABLE(of, sprd_mbox_of_match);
0418
0419 static struct platform_driver sprd_mbox_driver = {
0420 .driver = {
0421 .name = "sprd-mailbox",
0422 .of_match_table = sprd_mbox_of_match,
0423 },
0424 .probe = sprd_mbox_probe,
0425 };
0426 module_platform_driver(sprd_mbox_driver);
0427
0428 MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>");
0429 MODULE_DESCRIPTION("Spreadtrum mailbox driver");
0430 MODULE_LICENSE("GPL v2");