Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Hisilicon's Hi6220 mailbox driver
0004  *
0005  * Copyright (c) 2015 HiSilicon Limited.
0006  * Copyright (c) 2015 Linaro Limited.
0007  *
0008  * Author: Leo Yan <leo.yan@linaro.org>
0009  */
0010 
0011 #include <linux/device.h>
0012 #include <linux/err.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/io.h>
0015 #include <linux/kfifo.h>
0016 #include <linux/mailbox_controller.h>
0017 #include <linux/module.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 
0021 #define MBOX_CHAN_MAX           32
0022 
0023 #define MBOX_TX             0x1
0024 
0025 /* Mailbox message length: 8 words */
0026 #define MBOX_MSG_LEN            8
0027 
0028 /* Mailbox Registers */
0029 #define MBOX_OFF(m)         (0x40 * (m))
0030 #define MBOX_MODE_REG(m)        (MBOX_OFF(m) + 0x0)
0031 #define MBOX_DATA_REG(m)        (MBOX_OFF(m) + 0x4)
0032 
0033 #define MBOX_STATE_MASK         (0xF << 4)
0034 #define MBOX_STATE_IDLE         (0x1 << 4)
0035 #define MBOX_STATE_TX           (0x2 << 4)
0036 #define MBOX_STATE_RX           (0x4 << 4)
0037 #define MBOX_STATE_ACK          (0x8 << 4)
0038 #define MBOX_ACK_CONFIG_MASK        (0x1 << 0)
0039 #define MBOX_ACK_AUTOMATIC      (0x1 << 0)
0040 #define MBOX_ACK_IRQ            (0x0 << 0)
0041 
0042 /* IPC registers */
0043 #define ACK_INT_RAW_REG(i)      ((i) + 0x400)
0044 #define ACK_INT_MSK_REG(i)      ((i) + 0x404)
0045 #define ACK_INT_STAT_REG(i)     ((i) + 0x408)
0046 #define ACK_INT_CLR_REG(i)      ((i) + 0x40c)
0047 #define ACK_INT_ENA_REG(i)      ((i) + 0x500)
0048 #define ACK_INT_DIS_REG(i)      ((i) + 0x504)
0049 #define DST_INT_RAW_REG(i)      ((i) + 0x420)
0050 
0051 
0052 struct hi6220_mbox_chan {
0053 
0054     /*
0055      * Description for channel's hardware info:
0056      *  - direction: tx or rx
0057      *  - dst irq: peer core's irq number
0058      *  - ack irq: local irq number
0059      *  - slot number
0060      */
0061     unsigned int dir, dst_irq, ack_irq;
0062     unsigned int slot;
0063 
0064     struct hi6220_mbox *parent;
0065 };
0066 
0067 struct hi6220_mbox {
0068     struct device *dev;
0069 
0070     int irq;
0071 
0072     /* flag of enabling tx's irq mode */
0073     bool tx_irq_mode;
0074 
0075     /* region for ipc event */
0076     void __iomem *ipc;
0077 
0078     /* region for mailbox */
0079     void __iomem *base;
0080 
0081     unsigned int chan_num;
0082     struct hi6220_mbox_chan *mchan;
0083 
0084     void *irq_map_chan[MBOX_CHAN_MAX];
0085     struct mbox_chan *chan;
0086     struct mbox_controller controller;
0087 };
0088 
0089 static void mbox_set_state(struct hi6220_mbox *mbox,
0090                unsigned int slot, u32 val)
0091 {
0092     u32 status;
0093 
0094     status = readl(mbox->base + MBOX_MODE_REG(slot));
0095     status = (status & ~MBOX_STATE_MASK) | val;
0096     writel(status, mbox->base + MBOX_MODE_REG(slot));
0097 }
0098 
0099 static void mbox_set_mode(struct hi6220_mbox *mbox,
0100               unsigned int slot, u32 val)
0101 {
0102     u32 mode;
0103 
0104     mode = readl(mbox->base + MBOX_MODE_REG(slot));
0105     mode = (mode & ~MBOX_ACK_CONFIG_MASK) | val;
0106     writel(mode, mbox->base + MBOX_MODE_REG(slot));
0107 }
0108 
0109 static bool hi6220_mbox_last_tx_done(struct mbox_chan *chan)
0110 {
0111     struct hi6220_mbox_chan *mchan = chan->con_priv;
0112     struct hi6220_mbox *mbox = mchan->parent;
0113     u32 state;
0114 
0115     /* Only set idle state for polling mode */
0116     BUG_ON(mbox->tx_irq_mode);
0117 
0118     state = readl(mbox->base + MBOX_MODE_REG(mchan->slot));
0119     return ((state & MBOX_STATE_MASK) == MBOX_STATE_IDLE);
0120 }
0121 
0122 static int hi6220_mbox_send_data(struct mbox_chan *chan, void *msg)
0123 {
0124     struct hi6220_mbox_chan *mchan = chan->con_priv;
0125     struct hi6220_mbox *mbox = mchan->parent;
0126     unsigned int slot = mchan->slot;
0127     u32 *buf = msg;
0128     int i;
0129 
0130     /* indicate as a TX channel */
0131     mchan->dir = MBOX_TX;
0132 
0133     mbox_set_state(mbox, slot, MBOX_STATE_TX);
0134 
0135     if (mbox->tx_irq_mode)
0136         mbox_set_mode(mbox, slot, MBOX_ACK_IRQ);
0137     else
0138         mbox_set_mode(mbox, slot, MBOX_ACK_AUTOMATIC);
0139 
0140     for (i = 0; i < MBOX_MSG_LEN; i++)
0141         writel(buf[i], mbox->base + MBOX_DATA_REG(slot) + i * 4);
0142 
0143     /* trigger remote request */
0144     writel(BIT(mchan->dst_irq), DST_INT_RAW_REG(mbox->ipc));
0145     return 0;
0146 }
0147 
0148 static irqreturn_t hi6220_mbox_interrupt(int irq, void *p)
0149 {
0150     struct hi6220_mbox *mbox = p;
0151     struct hi6220_mbox_chan *mchan;
0152     struct mbox_chan *chan;
0153     unsigned int state, intr_bit, i;
0154     u32 msg[MBOX_MSG_LEN];
0155 
0156     state = readl(ACK_INT_STAT_REG(mbox->ipc));
0157     if (!state) {
0158         dev_warn(mbox->dev, "%s: spurious interrupt\n",
0159              __func__);
0160         return IRQ_HANDLED;
0161     }
0162 
0163     while (state) {
0164         intr_bit = __ffs(state);
0165         state &= (state - 1);
0166 
0167         chan = mbox->irq_map_chan[intr_bit];
0168         if (!chan) {
0169             dev_warn(mbox->dev, "%s: unexpected irq vector %d\n",
0170                  __func__, intr_bit);
0171             continue;
0172         }
0173 
0174         mchan = chan->con_priv;
0175         if (mchan->dir == MBOX_TX)
0176             mbox_chan_txdone(chan, 0);
0177         else {
0178             for (i = 0; i < MBOX_MSG_LEN; i++)
0179                 msg[i] = readl(mbox->base +
0180                     MBOX_DATA_REG(mchan->slot) + i * 4);
0181 
0182             mbox_chan_received_data(chan, (void *)msg);
0183         }
0184 
0185         /* clear IRQ source */
0186         writel(BIT(mchan->ack_irq), ACK_INT_CLR_REG(mbox->ipc));
0187         mbox_set_state(mbox, mchan->slot, MBOX_STATE_IDLE);
0188     }
0189 
0190     return IRQ_HANDLED;
0191 }
0192 
0193 static int hi6220_mbox_startup(struct mbox_chan *chan)
0194 {
0195     struct hi6220_mbox_chan *mchan = chan->con_priv;
0196     struct hi6220_mbox *mbox = mchan->parent;
0197 
0198     mchan->dir = 0;
0199 
0200     /* enable interrupt */
0201     writel(BIT(mchan->ack_irq), ACK_INT_ENA_REG(mbox->ipc));
0202     return 0;
0203 }
0204 
0205 static void hi6220_mbox_shutdown(struct mbox_chan *chan)
0206 {
0207     struct hi6220_mbox_chan *mchan = chan->con_priv;
0208     struct hi6220_mbox *mbox = mchan->parent;
0209 
0210     /* disable interrupt */
0211     writel(BIT(mchan->ack_irq), ACK_INT_DIS_REG(mbox->ipc));
0212     mbox->irq_map_chan[mchan->ack_irq] = NULL;
0213 }
0214 
0215 static const struct mbox_chan_ops hi6220_mbox_ops = {
0216     .send_data    = hi6220_mbox_send_data,
0217     .startup      = hi6220_mbox_startup,
0218     .shutdown     = hi6220_mbox_shutdown,
0219     .last_tx_done = hi6220_mbox_last_tx_done,
0220 };
0221 
0222 static struct mbox_chan *hi6220_mbox_xlate(struct mbox_controller *controller,
0223                        const struct of_phandle_args *spec)
0224 {
0225     struct hi6220_mbox *mbox = dev_get_drvdata(controller->dev);
0226     struct hi6220_mbox_chan *mchan;
0227     struct mbox_chan *chan;
0228     unsigned int i = spec->args[0];
0229     unsigned int dst_irq = spec->args[1];
0230     unsigned int ack_irq = spec->args[2];
0231 
0232     /* Bounds checking */
0233     if (i >= mbox->chan_num || dst_irq >= mbox->chan_num ||
0234         ack_irq >= mbox->chan_num) {
0235         dev_err(mbox->dev,
0236             "Invalid channel idx %d dst_irq %d ack_irq %d\n",
0237             i, dst_irq, ack_irq);
0238         return ERR_PTR(-EINVAL);
0239     }
0240 
0241     /* Is requested channel free? */
0242     chan = &mbox->chan[i];
0243     if (mbox->irq_map_chan[ack_irq] == (void *)chan) {
0244         dev_err(mbox->dev, "Channel in use\n");
0245         return ERR_PTR(-EBUSY);
0246     }
0247 
0248     mchan = chan->con_priv;
0249     mchan->dst_irq = dst_irq;
0250     mchan->ack_irq = ack_irq;
0251 
0252     mbox->irq_map_chan[ack_irq] = (void *)chan;
0253     return chan;
0254 }
0255 
0256 static const struct of_device_id hi6220_mbox_of_match[] = {
0257     { .compatible = "hisilicon,hi6220-mbox", },
0258     {},
0259 };
0260 MODULE_DEVICE_TABLE(of, hi6220_mbox_of_match);
0261 
0262 static int hi6220_mbox_probe(struct platform_device *pdev)
0263 {
0264     struct device_node *node = pdev->dev.of_node;
0265     struct device *dev = &pdev->dev;
0266     struct hi6220_mbox *mbox;
0267     int i, err;
0268 
0269     mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
0270     if (!mbox)
0271         return -ENOMEM;
0272 
0273     mbox->dev = dev;
0274     mbox->chan_num = MBOX_CHAN_MAX;
0275     mbox->mchan = devm_kcalloc(dev,
0276         mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL);
0277     if (!mbox->mchan)
0278         return -ENOMEM;
0279 
0280     mbox->chan = devm_kcalloc(dev,
0281         mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL);
0282     if (!mbox->chan)
0283         return -ENOMEM;
0284 
0285     mbox->irq = platform_get_irq(pdev, 0);
0286     if (mbox->irq < 0)
0287         return mbox->irq;
0288 
0289     mbox->ipc = devm_platform_ioremap_resource(pdev, 0);
0290     if (IS_ERR(mbox->ipc)) {
0291         dev_err(dev, "ioremap ipc failed\n");
0292         return PTR_ERR(mbox->ipc);
0293     }
0294 
0295     mbox->base = devm_platform_ioremap_resource(pdev, 1);
0296     if (IS_ERR(mbox->base)) {
0297         dev_err(dev, "ioremap buffer failed\n");
0298         return PTR_ERR(mbox->base);
0299     }
0300 
0301     err = devm_request_irq(dev, mbox->irq, hi6220_mbox_interrupt, 0,
0302             dev_name(dev), mbox);
0303     if (err) {
0304         dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
0305             err);
0306         return -ENODEV;
0307     }
0308 
0309     mbox->controller.dev = dev;
0310     mbox->controller.chans = &mbox->chan[0];
0311     mbox->controller.num_chans = mbox->chan_num;
0312     mbox->controller.ops = &hi6220_mbox_ops;
0313     mbox->controller.of_xlate = hi6220_mbox_xlate;
0314 
0315     for (i = 0; i < mbox->chan_num; i++) {
0316         mbox->chan[i].con_priv = &mbox->mchan[i];
0317         mbox->irq_map_chan[i] = NULL;
0318 
0319         mbox->mchan[i].parent = mbox;
0320         mbox->mchan[i].slot   = i;
0321     }
0322 
0323     /* mask and clear all interrupt vectors */
0324     writel(0x0,  ACK_INT_MSK_REG(mbox->ipc));
0325     writel(~0x0, ACK_INT_CLR_REG(mbox->ipc));
0326 
0327     /* use interrupt for tx's ack */
0328     if (of_find_property(node, "hi6220,mbox-tx-noirq", NULL))
0329         mbox->tx_irq_mode = false;
0330     else
0331         mbox->tx_irq_mode = true;
0332 
0333     if (mbox->tx_irq_mode)
0334         mbox->controller.txdone_irq = true;
0335     else {
0336         mbox->controller.txdone_poll = true;
0337         mbox->controller.txpoll_period = 5;
0338     }
0339 
0340     err = devm_mbox_controller_register(dev, &mbox->controller);
0341     if (err) {
0342         dev_err(dev, "Failed to register mailbox %d\n", err);
0343         return err;
0344     }
0345 
0346     platform_set_drvdata(pdev, mbox);
0347     dev_info(dev, "Mailbox enabled\n");
0348     return 0;
0349 }
0350 
0351 static struct platform_driver hi6220_mbox_driver = {
0352     .driver = {
0353         .name = "hi6220-mbox",
0354         .of_match_table = hi6220_mbox_of_match,
0355     },
0356     .probe  = hi6220_mbox_probe,
0357 };
0358 
0359 static int __init hi6220_mbox_init(void)
0360 {
0361     return platform_driver_register(&hi6220_mbox_driver);
0362 }
0363 core_initcall(hi6220_mbox_init);
0364 
0365 static void __exit hi6220_mbox_exit(void)
0366 {
0367     platform_driver_unregister(&hi6220_mbox_driver);
0368 }
0369 module_exit(hi6220_mbox_exit);
0370 
0371 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
0372 MODULE_DESCRIPTION("Hi6220 mailbox driver");
0373 MODULE_LICENSE("GPL v2");