Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
0004  * Copyright (C) 2015 Linaro Ltd.
0005  * Based on ARM MHU driver by Jassi Brar <jaswinder.singh@linaro.org>
0006  * Copyright (C) 2020 ARM Ltd.
0007  */
0008 
0009 #include <linux/amba/bus.h>
0010 #include <linux/device.h>
0011 #include <linux/err.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/mailbox_controller.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019 
0020 #define INTR_STAT_OFS   0x0
0021 #define INTR_SET_OFS    0x8
0022 #define INTR_CLR_OFS    0x10
0023 
0024 #define MHU_LP_OFFSET   0x0
0025 #define MHU_HP_OFFSET   0x20
0026 #define MHU_SEC_OFFSET  0x200
0027 #define TX_REG_OFFSET   0x100
0028 
0029 #define MHU_CHANS   3   /* Secure, Non-Secure High and Low Priority */
0030 #define MHU_CHAN_MAX    20  /* Max channels to save on unused RAM */
0031 #define MHU_NUM_DOORBELLS   32
0032 
0033 struct mhu_db_link {
0034     unsigned int irq;
0035     void __iomem *tx_reg;
0036     void __iomem *rx_reg;
0037 };
0038 
0039 struct arm_mhu {
0040     void __iomem *base;
0041     struct mhu_db_link mlink[MHU_CHANS];
0042     struct mbox_controller mbox;
0043     struct device *dev;
0044 };
0045 
0046 /**
0047  * struct mhu_db_channel - ARM MHU Mailbox allocated channel information
0048  *
0049  * @mhu: Pointer to parent mailbox device
0050  * @pchan: Physical channel within which this doorbell resides in
0051  * @doorbell: doorbell number pertaining to this channel
0052  */
0053 struct mhu_db_channel {
0054     struct arm_mhu *mhu;
0055     unsigned int pchan;
0056     unsigned int doorbell;
0057 };
0058 
0059 static inline struct mbox_chan *
0060 mhu_db_mbox_to_channel(struct mbox_controller *mbox, unsigned int pchan,
0061                unsigned int doorbell)
0062 {
0063     int i;
0064     struct mhu_db_channel *chan_info;
0065 
0066     for (i = 0; i < mbox->num_chans; i++) {
0067         chan_info = mbox->chans[i].con_priv;
0068         if (chan_info && chan_info->pchan == pchan &&
0069             chan_info->doorbell == doorbell)
0070             return &mbox->chans[i];
0071     }
0072 
0073     return NULL;
0074 }
0075 
0076 static void mhu_db_mbox_clear_irq(struct mbox_chan *chan)
0077 {
0078     struct mhu_db_channel *chan_info = chan->con_priv;
0079     void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].rx_reg;
0080 
0081     writel_relaxed(BIT(chan_info->doorbell), base + INTR_CLR_OFS);
0082 }
0083 
0084 static unsigned int mhu_db_mbox_irq_to_pchan_num(struct arm_mhu *mhu, int irq)
0085 {
0086     unsigned int pchan;
0087 
0088     for (pchan = 0; pchan < MHU_CHANS; pchan++)
0089         if (mhu->mlink[pchan].irq == irq)
0090             break;
0091     return pchan;
0092 }
0093 
0094 static struct mbox_chan *
0095 mhu_db_mbox_irq_to_channel(struct arm_mhu *mhu, unsigned int pchan)
0096 {
0097     unsigned long bits;
0098     unsigned int doorbell;
0099     struct mbox_chan *chan = NULL;
0100     struct mbox_controller *mbox = &mhu->mbox;
0101     void __iomem *base = mhu->mlink[pchan].rx_reg;
0102 
0103     bits = readl_relaxed(base + INTR_STAT_OFS);
0104     if (!bits)
0105         /* No IRQs fired in specified physical channel */
0106         return NULL;
0107 
0108     /* An IRQ has fired, find the associated channel */
0109     for (doorbell = 0; bits; doorbell++) {
0110         if (!test_and_clear_bit(doorbell, &bits))
0111             continue;
0112 
0113         chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell);
0114         if (chan)
0115             break;
0116         dev_err(mbox->dev,
0117             "Channel not registered: pchan: %d doorbell: %d\n",
0118             pchan, doorbell);
0119     }
0120 
0121     return chan;
0122 }
0123 
0124 static irqreturn_t mhu_db_mbox_rx_handler(int irq, void *data)
0125 {
0126     struct mbox_chan *chan;
0127     struct arm_mhu *mhu = data;
0128     unsigned int pchan = mhu_db_mbox_irq_to_pchan_num(mhu, irq);
0129 
0130     while (NULL != (chan = mhu_db_mbox_irq_to_channel(mhu, pchan))) {
0131         mbox_chan_received_data(chan, NULL);
0132         mhu_db_mbox_clear_irq(chan);
0133     }
0134 
0135     return IRQ_HANDLED;
0136 }
0137 
0138 static bool mhu_db_last_tx_done(struct mbox_chan *chan)
0139 {
0140     struct mhu_db_channel *chan_info = chan->con_priv;
0141     void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg;
0142 
0143     if (readl_relaxed(base + INTR_STAT_OFS) & BIT(chan_info->doorbell))
0144         return false;
0145 
0146     return true;
0147 }
0148 
0149 static int mhu_db_send_data(struct mbox_chan *chan, void *data)
0150 {
0151     struct mhu_db_channel *chan_info = chan->con_priv;
0152     void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg;
0153 
0154     /* Send event to co-processor */
0155     writel_relaxed(BIT(chan_info->doorbell), base + INTR_SET_OFS);
0156 
0157     return 0;
0158 }
0159 
0160 static int mhu_db_startup(struct mbox_chan *chan)
0161 {
0162     mhu_db_mbox_clear_irq(chan);
0163     return 0;
0164 }
0165 
0166 static void mhu_db_shutdown(struct mbox_chan *chan)
0167 {
0168     struct mhu_db_channel *chan_info = chan->con_priv;
0169     struct mbox_controller *mbox = &chan_info->mhu->mbox;
0170     int i;
0171 
0172     for (i = 0; i < mbox->num_chans; i++)
0173         if (chan == &mbox->chans[i])
0174             break;
0175 
0176     if (mbox->num_chans == i) {
0177         dev_warn(mbox->dev, "Request to free non-existent channel\n");
0178         return;
0179     }
0180 
0181     /* Reset channel */
0182     mhu_db_mbox_clear_irq(chan);
0183     devm_kfree(mbox->dev, chan->con_priv);
0184     chan->con_priv = NULL;
0185 }
0186 
0187 static struct mbox_chan *mhu_db_mbox_xlate(struct mbox_controller *mbox,
0188                        const struct of_phandle_args *spec)
0189 {
0190     struct arm_mhu *mhu = dev_get_drvdata(mbox->dev);
0191     struct mhu_db_channel *chan_info;
0192     struct mbox_chan *chan;
0193     unsigned int pchan = spec->args[0];
0194     unsigned int doorbell = spec->args[1];
0195     int i;
0196 
0197     /* Bounds checking */
0198     if (pchan >= MHU_CHANS || doorbell >= MHU_NUM_DOORBELLS) {
0199         dev_err(mbox->dev,
0200             "Invalid channel requested pchan: %d doorbell: %d\n",
0201             pchan, doorbell);
0202         return ERR_PTR(-EINVAL);
0203     }
0204 
0205     /* Is requested channel free? */
0206     chan = mhu_db_mbox_to_channel(mbox, pchan, doorbell);
0207     if (chan) {
0208         dev_err(mbox->dev, "Channel in use: pchan: %d doorbell: %d\n",
0209             pchan, doorbell);
0210         return ERR_PTR(-EBUSY);
0211     }
0212 
0213     /* Find the first free slot */
0214     for (i = 0; i < mbox->num_chans; i++)
0215         if (!mbox->chans[i].con_priv)
0216             break;
0217 
0218     if (mbox->num_chans == i) {
0219         dev_err(mbox->dev, "No free channels left\n");
0220         return ERR_PTR(-EBUSY);
0221     }
0222 
0223     chan = &mbox->chans[i];
0224 
0225     chan_info = devm_kzalloc(mbox->dev, sizeof(*chan_info), GFP_KERNEL);
0226     if (!chan_info)
0227         return ERR_PTR(-ENOMEM);
0228 
0229     chan_info->mhu = mhu;
0230     chan_info->pchan = pchan;
0231     chan_info->doorbell = doorbell;
0232 
0233     chan->con_priv = chan_info;
0234 
0235     dev_dbg(mbox->dev, "mbox: created channel phys: %d doorbell: %d\n",
0236         pchan, doorbell);
0237 
0238     return chan;
0239 }
0240 
0241 static const struct mbox_chan_ops mhu_db_ops = {
0242     .send_data = mhu_db_send_data,
0243     .startup = mhu_db_startup,
0244     .shutdown = mhu_db_shutdown,
0245     .last_tx_done = mhu_db_last_tx_done,
0246 };
0247 
0248 static int mhu_db_probe(struct amba_device *adev, const struct amba_id *id)
0249 {
0250     u32 cell_count;
0251     int i, err, max_chans;
0252     struct arm_mhu *mhu;
0253     struct mbox_chan *chans;
0254     struct device *dev = &adev->dev;
0255     struct device_node *np = dev->of_node;
0256     int mhu_reg[MHU_CHANS] = {
0257         MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET,
0258     };
0259 
0260     if (!of_device_is_compatible(np, "arm,mhu-doorbell"))
0261         return -ENODEV;
0262 
0263     err = of_property_read_u32(np, "#mbox-cells", &cell_count);
0264     if (err) {
0265         dev_err(dev, "failed to read #mbox-cells in '%pOF'\n", np);
0266         return err;
0267     }
0268 
0269     if (cell_count == 2) {
0270         max_chans = MHU_CHAN_MAX;
0271     } else {
0272         dev_err(dev, "incorrect value of #mbox-cells in '%pOF'\n", np);
0273         return -EINVAL;
0274     }
0275 
0276     mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
0277     if (!mhu)
0278         return -ENOMEM;
0279 
0280     mhu->base = devm_ioremap_resource(dev, &adev->res);
0281     if (IS_ERR(mhu->base))
0282         return PTR_ERR(mhu->base);
0283 
0284     chans = devm_kcalloc(dev, max_chans, sizeof(*chans), GFP_KERNEL);
0285     if (!chans)
0286         return -ENOMEM;
0287 
0288     mhu->dev = dev;
0289     mhu->mbox.dev = dev;
0290     mhu->mbox.chans = chans;
0291     mhu->mbox.num_chans = max_chans;
0292     mhu->mbox.txdone_irq = false;
0293     mhu->mbox.txdone_poll = true;
0294     mhu->mbox.txpoll_period = 1;
0295 
0296     mhu->mbox.of_xlate = mhu_db_mbox_xlate;
0297     amba_set_drvdata(adev, mhu);
0298 
0299     mhu->mbox.ops = &mhu_db_ops;
0300 
0301     err = devm_mbox_controller_register(dev, &mhu->mbox);
0302     if (err) {
0303         dev_err(dev, "Failed to register mailboxes %d\n", err);
0304         return err;
0305     }
0306 
0307     for (i = 0; i < MHU_CHANS; i++) {
0308         int irq = mhu->mlink[i].irq = adev->irq[i];
0309 
0310         if (irq <= 0) {
0311             dev_dbg(dev, "No IRQ found for Channel %d\n", i);
0312             continue;
0313         }
0314 
0315         mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
0316         mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
0317 
0318         err = devm_request_threaded_irq(dev, irq, NULL,
0319                         mhu_db_mbox_rx_handler,
0320                         IRQF_ONESHOT, "mhu_db_link", mhu);
0321         if (err) {
0322             dev_err(dev, "Can't claim IRQ %d\n", irq);
0323             mbox_controller_unregister(&mhu->mbox);
0324             return err;
0325         }
0326     }
0327 
0328     dev_info(dev, "ARM MHU Doorbell mailbox registered\n");
0329     return 0;
0330 }
0331 
0332 static struct amba_id mhu_ids[] = {
0333     {
0334         .id = 0x1bb098,
0335         .mask   = 0xffffff,
0336     },
0337     { 0, 0 },
0338 };
0339 MODULE_DEVICE_TABLE(amba, mhu_ids);
0340 
0341 static struct amba_driver arm_mhu_db_driver = {
0342     .drv = {
0343         .name   = "mhu-doorbell",
0344     },
0345     .id_table   = mhu_ids,
0346     .probe      = mhu_db_probe,
0347 };
0348 module_amba_driver(arm_mhu_db_driver);
0349 
0350 MODULE_LICENSE("GPL v2");
0351 MODULE_DESCRIPTION("ARM MHU Doorbell Driver");
0352 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");