Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Spreadtrum mailbox driver
0004  *
0005  * Copyright (c) 2020 Spreadtrum Communications Inc.
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 /* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */
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 /* Bit and mask definition for SPRD_MBOX_IRQ_STS register */
0036 #define SPRD_MBOX_IRQ_CLR           BIT(0)
0037 
0038 /* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */
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 /* Bit and mask definition for inbox's SPRD_MBOX_IRQ_MSK register */
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 /* Bit and mask definition for outbox's SPRD_MBOX_IRQ_MSK register */
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     /*  Base register address for supplementary outbox */
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      * If the read pointer is equal with write pointer, which means the fifo
0088      * is full or empty.
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         /* Trigger to update outbox FIFO pointer */
0131         writel(0x1, base + SPRD_MBOX_TRIGGER);
0132     }
0133 
0134     /* Clear irq status after reading all message. */
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     /* Get the inbox data delivery status */
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          * Check if the message was fetched by remote target, if yes,
0178          * that means the transmission has been completed.
0179          */
0180         busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
0181         if (!(busy & BIT(id)))
0182             mbox_chan_txdone(chan, 0);
0183     }
0184 
0185     /* Clear FIFO delivery and overflow status */
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     /* Clear irq status */
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     /* Write data into inbox FIFO, and only support 8 bytes every time */
0203     writel(data[0], priv->inbox_base + SPRD_MBOX_MSG_LOW);
0204     writel(data[1], priv->inbox_base + SPRD_MBOX_MSG_HIGH);
0205 
0206     /* Set target core id */
0207     writel(id, priv->inbox_base + SPRD_MBOX_ID);
0208 
0209     /* Trigger remote request */
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         /* Select outbox FIFO mode and reset the outbox FIFO status */
0245         writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST);
0246 
0247         /* Enable inbox FIFO overflow and delivery interrupt */
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         /* Enable outbox FIFO not empty interrupt */
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         /* Enable supplementary outbox as the fundamental one */
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         /* Disable inbox & outbox interrupt */
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      * Unisoc mailbox uses an inbox to send messages to the target
0317      * core, and uses (an) outbox(es) to receive messages from other
0318      * cores.
0319      *
0320      * Thus in general the mailbox controller supplies 2 different
0321      * register addresses and IRQ numbers for inbox and outbox.
0322      *
0323      * If necessary, a supplementary inbox could be enabled optionally
0324      * with an independent FIFO and an extra interrupt.
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     /* Supplementary outbox IRQ is optional */
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     /* Get the default outbox FIFO depth */
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");