Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright Altera Corporation (C) 2013-2014. All rights reserved
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/io.h>
0009 #include <linux/kernel.h>
0010 #include <linux/mailbox_controller.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/platform_device.h>
0014 
0015 #define DRIVER_NAME "altera-mailbox"
0016 
0017 #define MAILBOX_CMD_REG         0x00
0018 #define MAILBOX_PTR_REG         0x04
0019 #define MAILBOX_STS_REG         0x08
0020 #define MAILBOX_INTMASK_REG     0x0C
0021 
0022 #define INT_PENDING_MSK         0x1
0023 #define INT_SPACE_MSK           0x2
0024 
0025 #define STS_PENDING_MSK         0x1
0026 #define STS_FULL_MSK            0x2
0027 #define STS_FULL_OFT            0x1
0028 
0029 #define MBOX_PENDING(status)    (((status) & STS_PENDING_MSK))
0030 #define MBOX_FULL(status)   (((status) & STS_FULL_MSK) >> STS_FULL_OFT)
0031 
0032 enum altera_mbox_msg {
0033     MBOX_CMD = 0,
0034     MBOX_PTR,
0035 };
0036 
0037 #define MBOX_POLLING_MS     5   /* polling interval 5ms */
0038 
0039 struct altera_mbox {
0040     bool is_sender;     /* 1-sender, 0-receiver */
0041     bool intr_mode;
0042     int irq;
0043     void __iomem *mbox_base;
0044     struct device *dev;
0045     struct mbox_controller controller;
0046 
0047     /* If the controller supports only RX polling mode */
0048     struct timer_list rxpoll_timer;
0049     struct mbox_chan *chan;
0050 };
0051 
0052 static struct altera_mbox *mbox_chan_to_altera_mbox(struct mbox_chan *chan)
0053 {
0054     if (!chan || !chan->con_priv)
0055         return NULL;
0056 
0057     return (struct altera_mbox *)chan->con_priv;
0058 }
0059 
0060 static inline int altera_mbox_full(struct altera_mbox *mbox)
0061 {
0062     u32 status;
0063 
0064     status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG);
0065     return MBOX_FULL(status);
0066 }
0067 
0068 static inline int altera_mbox_pending(struct altera_mbox *mbox)
0069 {
0070     u32 status;
0071 
0072     status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG);
0073     return MBOX_PENDING(status);
0074 }
0075 
0076 static void altera_mbox_rx_intmask(struct altera_mbox *mbox, bool enable)
0077 {
0078     u32 mask;
0079 
0080     mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG);
0081     if (enable)
0082         mask |= INT_PENDING_MSK;
0083     else
0084         mask &= ~INT_PENDING_MSK;
0085     writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG);
0086 }
0087 
0088 static void altera_mbox_tx_intmask(struct altera_mbox *mbox, bool enable)
0089 {
0090     u32 mask;
0091 
0092     mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG);
0093     if (enable)
0094         mask |= INT_SPACE_MSK;
0095     else
0096         mask &= ~INT_SPACE_MSK;
0097     writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG);
0098 }
0099 
0100 static bool altera_mbox_is_sender(struct altera_mbox *mbox)
0101 {
0102     u32 reg;
0103     /* Write a magic number to PTR register and read back this register.
0104      * This register is read-write if it is a sender.
0105      */
0106     #define MBOX_MAGIC  0xA5A5AA55
0107     writel_relaxed(MBOX_MAGIC, mbox->mbox_base + MAILBOX_PTR_REG);
0108     reg = readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG);
0109     if (reg == MBOX_MAGIC) {
0110         /* Clear to 0 */
0111         writel_relaxed(0, mbox->mbox_base + MAILBOX_PTR_REG);
0112         return true;
0113     }
0114     return false;
0115 }
0116 
0117 static void altera_mbox_rx_data(struct mbox_chan *chan)
0118 {
0119     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0120     u32 data[2];
0121 
0122     if (altera_mbox_pending(mbox)) {
0123         data[MBOX_PTR] =
0124             readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG);
0125         data[MBOX_CMD] =
0126             readl_relaxed(mbox->mbox_base + MAILBOX_CMD_REG);
0127         mbox_chan_received_data(chan, (void *)data);
0128     }
0129 }
0130 
0131 static void altera_mbox_poll_rx(struct timer_list *t)
0132 {
0133     struct altera_mbox *mbox = from_timer(mbox, t, rxpoll_timer);
0134 
0135     altera_mbox_rx_data(mbox->chan);
0136 
0137     mod_timer(&mbox->rxpoll_timer,
0138           jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
0139 }
0140 
0141 static irqreturn_t altera_mbox_tx_interrupt(int irq, void *p)
0142 {
0143     struct mbox_chan *chan = (struct mbox_chan *)p;
0144     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0145 
0146     altera_mbox_tx_intmask(mbox, false);
0147     mbox_chan_txdone(chan, 0);
0148 
0149     return IRQ_HANDLED;
0150 }
0151 
0152 static irqreturn_t altera_mbox_rx_interrupt(int irq, void *p)
0153 {
0154     struct mbox_chan *chan = (struct mbox_chan *)p;
0155 
0156     altera_mbox_rx_data(chan);
0157     return IRQ_HANDLED;
0158 }
0159 
0160 static int altera_mbox_startup_sender(struct mbox_chan *chan)
0161 {
0162     int ret;
0163     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0164 
0165     if (mbox->intr_mode) {
0166         ret = request_irq(mbox->irq, altera_mbox_tx_interrupt, 0,
0167                   DRIVER_NAME, chan);
0168         if (unlikely(ret)) {
0169             dev_err(mbox->dev,
0170                 "failed to register mailbox interrupt:%d\n",
0171                 ret);
0172             return ret;
0173         }
0174     }
0175 
0176     return 0;
0177 }
0178 
0179 static int altera_mbox_startup_receiver(struct mbox_chan *chan)
0180 {
0181     int ret;
0182     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0183 
0184     if (mbox->intr_mode) {
0185         ret = request_irq(mbox->irq, altera_mbox_rx_interrupt, 0,
0186                   DRIVER_NAME, chan);
0187         if (unlikely(ret)) {
0188             mbox->intr_mode = false;
0189             goto polling; /* use polling if failed */
0190         }
0191 
0192         altera_mbox_rx_intmask(mbox, true);
0193         return 0;
0194     }
0195 
0196 polling:
0197     /* Setup polling timer */
0198     mbox->chan = chan;
0199     timer_setup(&mbox->rxpoll_timer, altera_mbox_poll_rx, 0);
0200     mod_timer(&mbox->rxpoll_timer,
0201           jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
0202 
0203     return 0;
0204 }
0205 
0206 static int altera_mbox_send_data(struct mbox_chan *chan, void *data)
0207 {
0208     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0209     u32 *udata = (u32 *)data;
0210 
0211     if (!mbox || !data)
0212         return -EINVAL;
0213     if (!mbox->is_sender) {
0214         dev_warn(mbox->dev,
0215              "failed to send. This is receiver mailbox.\n");
0216         return -EINVAL;
0217     }
0218 
0219     if (altera_mbox_full(mbox))
0220         return -EBUSY;
0221 
0222     /* Enable interrupt before send */
0223     if (mbox->intr_mode)
0224         altera_mbox_tx_intmask(mbox, true);
0225 
0226     /* Pointer register must write before command register */
0227     writel_relaxed(udata[MBOX_PTR], mbox->mbox_base + MAILBOX_PTR_REG);
0228     writel_relaxed(udata[MBOX_CMD], mbox->mbox_base + MAILBOX_CMD_REG);
0229 
0230     return 0;
0231 }
0232 
0233 static bool altera_mbox_last_tx_done(struct mbox_chan *chan)
0234 {
0235     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0236 
0237     /* Return false if mailbox is full */
0238     return altera_mbox_full(mbox) ? false : true;
0239 }
0240 
0241 static bool altera_mbox_peek_data(struct mbox_chan *chan)
0242 {
0243     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0244 
0245     return altera_mbox_pending(mbox) ? true : false;
0246 }
0247 
0248 static int altera_mbox_startup(struct mbox_chan *chan)
0249 {
0250     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0251     int ret = 0;
0252 
0253     if (!mbox)
0254         return -EINVAL;
0255 
0256     if (mbox->is_sender)
0257         ret = altera_mbox_startup_sender(chan);
0258     else
0259         ret = altera_mbox_startup_receiver(chan);
0260 
0261     return ret;
0262 }
0263 
0264 static void altera_mbox_shutdown(struct mbox_chan *chan)
0265 {
0266     struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
0267 
0268     if (mbox->intr_mode) {
0269         /* Unmask all interrupt masks */
0270         writel_relaxed(~0, mbox->mbox_base + MAILBOX_INTMASK_REG);
0271         free_irq(mbox->irq, chan);
0272     } else if (!mbox->is_sender) {
0273         del_timer_sync(&mbox->rxpoll_timer);
0274     }
0275 }
0276 
0277 static const struct mbox_chan_ops altera_mbox_ops = {
0278     .send_data = altera_mbox_send_data,
0279     .startup = altera_mbox_startup,
0280     .shutdown = altera_mbox_shutdown,
0281     .last_tx_done = altera_mbox_last_tx_done,
0282     .peek_data = altera_mbox_peek_data,
0283 };
0284 
0285 static int altera_mbox_probe(struct platform_device *pdev)
0286 {
0287     struct altera_mbox *mbox;
0288     struct mbox_chan *chans;
0289     int ret;
0290 
0291     mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox),
0292                 GFP_KERNEL);
0293     if (!mbox)
0294         return -ENOMEM;
0295 
0296     /* Allocated one channel */
0297     chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
0298     if (!chans)
0299         return -ENOMEM;
0300 
0301     mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0);
0302     if (IS_ERR(mbox->mbox_base))
0303         return PTR_ERR(mbox->mbox_base);
0304 
0305     /* Check is it a sender or receiver? */
0306     mbox->is_sender = altera_mbox_is_sender(mbox);
0307 
0308     mbox->irq = platform_get_irq(pdev, 0);
0309     if (mbox->irq >= 0)
0310         mbox->intr_mode = true;
0311 
0312     mbox->dev = &pdev->dev;
0313 
0314     /* Hardware supports only one channel. */
0315     chans[0].con_priv = mbox;
0316     mbox->controller.dev = mbox->dev;
0317     mbox->controller.num_chans = 1;
0318     mbox->controller.chans = chans;
0319     mbox->controller.ops = &altera_mbox_ops;
0320 
0321     if (mbox->is_sender) {
0322         if (mbox->intr_mode) {
0323             mbox->controller.txdone_irq = true;
0324         } else {
0325             mbox->controller.txdone_poll = true;
0326             mbox->controller.txpoll_period = MBOX_POLLING_MS;
0327         }
0328     }
0329 
0330     ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
0331     if (ret) {
0332         dev_err(&pdev->dev, "Register mailbox failed\n");
0333         goto err;
0334     }
0335 
0336     platform_set_drvdata(pdev, mbox);
0337 err:
0338     return ret;
0339 }
0340 
0341 static const struct of_device_id altera_mbox_match[] = {
0342     { .compatible = "altr,mailbox-1.0" },
0343     { /* Sentinel */ }
0344 };
0345 
0346 MODULE_DEVICE_TABLE(of, altera_mbox_match);
0347 
0348 static struct platform_driver altera_mbox_driver = {
0349     .probe  = altera_mbox_probe,
0350     .driver = {
0351         .name   = DRIVER_NAME,
0352         .of_match_table = altera_mbox_match,
0353     },
0354 };
0355 
0356 module_platform_driver(altera_mbox_driver);
0357 
0358 MODULE_LICENSE("GPL v2");
0359 MODULE_DESCRIPTION("Altera mailbox specific functions");
0360 MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>");
0361 MODULE_ALIAS("platform:altera-mailbox");