Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Copyright (C) 2010,2015 Broadcom
0004  *  Copyright (C) 2013-2014 Lubomir Rintel
0005  *  Copyright (C) 2013 Craig McGeachie
0006  *
0007  * Parts of the driver are based on:
0008  *  - arch/arm/mach-bcm2708/vcio.c file written by Gray Girling that was
0009  *    obtained from branch "rpi-3.6.y" of git://github.com/raspberrypi/
0010  *    linux.git
0011  *  - drivers/mailbox/bcm2835-ipc.c by Lubomir Rintel at
0012  *    https://github.com/hackerspace/rpi-linux/blob/lr-raspberry-pi/drivers/
0013  *    mailbox/bcm2835-ipc.c
0014  *  - documentation available on the following web site:
0015  *    https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
0016  */
0017 
0018 #include <linux/device.h>
0019 #include <linux/dma-mapping.h>
0020 #include <linux/err.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/irq.h>
0023 #include <linux/kernel.h>
0024 #include <linux/mailbox_controller.h>
0025 #include <linux/module.h>
0026 #include <linux/of_address.h>
0027 #include <linux/of_irq.h>
0028 #include <linux/platform_device.h>
0029 #include <linux/spinlock.h>
0030 
0031 /* Mailboxes */
0032 #define ARM_0_MAIL0 0x00
0033 #define ARM_0_MAIL1 0x20
0034 
0035 /*
0036  * Mailbox registers. We basically only support mailbox 0 & 1. We
0037  * deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See
0038  * BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about
0039  * the placement of memory barriers.
0040  */
0041 #define MAIL0_RD    (ARM_0_MAIL0 + 0x00)
0042 #define MAIL0_POL   (ARM_0_MAIL0 + 0x10)
0043 #define MAIL0_STA   (ARM_0_MAIL0 + 0x18)
0044 #define MAIL0_CNF   (ARM_0_MAIL0 + 0x1C)
0045 #define MAIL1_WRT   (ARM_0_MAIL1 + 0x00)
0046 #define MAIL1_STA   (ARM_0_MAIL1 + 0x18)
0047 
0048 /* Status register: FIFO state. */
0049 #define ARM_MS_FULL     BIT(31)
0050 #define ARM_MS_EMPTY        BIT(30)
0051 
0052 /* Configuration register: Enable interrupts. */
0053 #define ARM_MC_IHAVEDATAIRQEN   BIT(0)
0054 
0055 struct bcm2835_mbox {
0056     void __iomem *regs;
0057     spinlock_t lock;
0058     struct mbox_controller controller;
0059 };
0060 
0061 static struct bcm2835_mbox *bcm2835_link_mbox(struct mbox_chan *link)
0062 {
0063     return container_of(link->mbox, struct bcm2835_mbox, controller);
0064 }
0065 
0066 static irqreturn_t bcm2835_mbox_irq(int irq, void *dev_id)
0067 {
0068     struct bcm2835_mbox *mbox = dev_id;
0069     struct device *dev = mbox->controller.dev;
0070     struct mbox_chan *link = &mbox->controller.chans[0];
0071 
0072     while (!(readl(mbox->regs + MAIL0_STA) & ARM_MS_EMPTY)) {
0073         u32 msg = readl(mbox->regs + MAIL0_RD);
0074         dev_dbg(dev, "Reply 0x%08X\n", msg);
0075         mbox_chan_received_data(link, &msg);
0076     }
0077     return IRQ_HANDLED;
0078 }
0079 
0080 static int bcm2835_send_data(struct mbox_chan *link, void *data)
0081 {
0082     struct bcm2835_mbox *mbox = bcm2835_link_mbox(link);
0083     u32 msg = *(u32 *)data;
0084 
0085     spin_lock(&mbox->lock);
0086     writel(msg, mbox->regs + MAIL1_WRT);
0087     dev_dbg(mbox->controller.dev, "Request 0x%08X\n", msg);
0088     spin_unlock(&mbox->lock);
0089     return 0;
0090 }
0091 
0092 static int bcm2835_startup(struct mbox_chan *link)
0093 {
0094     struct bcm2835_mbox *mbox = bcm2835_link_mbox(link);
0095 
0096     /* Enable the interrupt on data reception */
0097     writel(ARM_MC_IHAVEDATAIRQEN, mbox->regs + MAIL0_CNF);
0098 
0099     return 0;
0100 }
0101 
0102 static void bcm2835_shutdown(struct mbox_chan *link)
0103 {
0104     struct bcm2835_mbox *mbox = bcm2835_link_mbox(link);
0105 
0106     writel(0, mbox->regs + MAIL0_CNF);
0107 }
0108 
0109 static bool bcm2835_last_tx_done(struct mbox_chan *link)
0110 {
0111     struct bcm2835_mbox *mbox = bcm2835_link_mbox(link);
0112     bool ret;
0113 
0114     spin_lock(&mbox->lock);
0115     ret = !(readl(mbox->regs + MAIL1_STA) & ARM_MS_FULL);
0116     spin_unlock(&mbox->lock);
0117     return ret;
0118 }
0119 
0120 static const struct mbox_chan_ops bcm2835_mbox_chan_ops = {
0121     .send_data  = bcm2835_send_data,
0122     .startup    = bcm2835_startup,
0123     .shutdown   = bcm2835_shutdown,
0124     .last_tx_done   = bcm2835_last_tx_done
0125 };
0126 
0127 static struct mbox_chan *bcm2835_mbox_index_xlate(struct mbox_controller *mbox,
0128             const struct of_phandle_args *sp)
0129 {
0130     if (sp->args_count != 0)
0131         return ERR_PTR(-EINVAL);
0132 
0133     return &mbox->chans[0];
0134 }
0135 
0136 static int bcm2835_mbox_probe(struct platform_device *pdev)
0137 {
0138     struct device *dev = &pdev->dev;
0139     int ret = 0;
0140     struct bcm2835_mbox *mbox;
0141 
0142     mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
0143     if (mbox == NULL)
0144         return -ENOMEM;
0145     spin_lock_init(&mbox->lock);
0146 
0147     ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0),
0148                    bcm2835_mbox_irq, 0, dev_name(dev), mbox);
0149     if (ret) {
0150         dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
0151             ret);
0152         return -ENODEV;
0153     }
0154 
0155     mbox->regs = devm_platform_ioremap_resource(pdev, 0);
0156     if (IS_ERR(mbox->regs)) {
0157         ret = PTR_ERR(mbox->regs);
0158         return ret;
0159     }
0160 
0161     mbox->controller.txdone_poll = true;
0162     mbox->controller.txpoll_period = 5;
0163     mbox->controller.ops = &bcm2835_mbox_chan_ops;
0164     mbox->controller.of_xlate = &bcm2835_mbox_index_xlate;
0165     mbox->controller.dev = dev;
0166     mbox->controller.num_chans = 1;
0167     mbox->controller.chans = devm_kzalloc(dev,
0168         sizeof(*mbox->controller.chans), GFP_KERNEL);
0169     if (!mbox->controller.chans)
0170         return -ENOMEM;
0171 
0172     ret = devm_mbox_controller_register(dev, &mbox->controller);
0173     if (ret)
0174         return ret;
0175 
0176     platform_set_drvdata(pdev, mbox);
0177     dev_info(dev, "mailbox enabled\n");
0178 
0179     return ret;
0180 }
0181 
0182 static const struct of_device_id bcm2835_mbox_of_match[] = {
0183     { .compatible = "brcm,bcm2835-mbox", },
0184     {},
0185 };
0186 MODULE_DEVICE_TABLE(of, bcm2835_mbox_of_match);
0187 
0188 static struct platform_driver bcm2835_mbox_driver = {
0189     .driver = {
0190         .name = "bcm2835-mbox",
0191         .of_match_table = bcm2835_mbox_of_match,
0192     },
0193     .probe      = bcm2835_mbox_probe,
0194 };
0195 module_platform_driver(bcm2835_mbox_driver);
0196 
0197 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
0198 MODULE_DESCRIPTION("BCM2835 mailbox IPC driver");
0199 MODULE_LICENSE("GPL v2");