分享

mailbox的controller...

 李清龙1023 2021-02-28


tiantao20122017-09-19 14:41:44 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
mailbox是kernel提供的一种板子上的硬件和soc通过messages queue,interrupt 进行通讯的一个架构。正式版的英文翻译如下:
menuconfig MAILBOX
bool "Mailbox Hardware Support"
help
  Mailbox is a framework to control hardware communication between
  on-chip processors through queued messages and interrupt driven
  signals. Say Y if your platform supports hardware mailboxes.
mailbox的实现分为contoller和client。简单的说就是clinet 可以通过controller提供的channle发送信息给conroller
因此在drivers/mailbox下实现的都是controller的源码
具体到某个厂商的硬件,则描述如下:
config ARM_MHU
    tristate "ARM MHU Mailbox"
    depends on ARM_AMBA
    help
      Say Y here if you want to build the ARM MHU controller driver.
      The controller has 3 mailbox channels, the last of which can be
      used in Secure mode only.
通过makefile我们知道要实现mailbox的源文件其实只有两个
obj-$(CONFIG_MAILBOX)+= mailbox.o
obj-$(CONFIG_ARM_MHU)+= arm_mhu.o
其中mailbox.c 是kernel提供的framework,arm_mhu.c 则是具体厂商的实现
这里直接看arm_mhu.c的probe函数
static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
{
int i, err;
struct arm_mhu *mhu;
struct device *dev = &adev->dev;
int mhu_reg[MHU_CHANS] = {MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET};

/* Allocate memory for device */
mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
if (!mhu)
return -ENOMEM;

mhu->base = devm_ioremap_resource(dev, &adev->res);
if (IS_ERR(mhu->base)) {
dev_err(dev, "ioremap failed\n");
return PTR_ERR(mhu->base);
}
//mailbox的channel 表示可以发送信息的寄存器
for (i = 0; i < MHU_CHANS; i++) {
mhu->chan[i].con_priv = &mhu->mlink[i];
mhu->mlink[i].irq = adev->irq[i];
mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
}
//初始化mbox的结构体
mhu->mbox.dev = dev;
mhu->mbox.chans = &mhu->chan[0];
mhu->mbox.num_chans = MHU_CHANS;
//mbox.ops 表示mailbox这个硬件具体的操作,例如发送数据,初始化等
mhu->mbox.ops = &mhu_ops;
//发送数据采用poll的方式
mhu->mbox.txdone_irq = false;
mhu->mbox.txdone_poll = true;
mhu->mbox.txpoll_period = 1;

amba_set_drvdata(adev, mhu);
//所有的controller 最终都要通过mbox_controller_register 来注册自己
err = mbox_controller_register(&mhu->mbox);
if (err) {
dev_err(dev, "Failed to register mailboxes %d\n", err);
return err;
}

dev_info(dev, "ARM MHU Mailbox registered\n");
return 0;
}

int mbox_controller_register(struct mbox_controller *mbox)
{
int i, txdone;
//下面这四个任何一个为null,就退出注册
/* Sanity check */
if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
return -EINVAL;
//client发送数据是通过poll的方式还是irq的方式,后面针对两种方式有不同的处理方式
if (mbox->txdone_irq)
txdone = TXDONE_BY_IRQ;
else if (mbox->txdone_poll)
txdone = TXDONE_BY_POLL;
else /* It has to be ACK then */
txdone = TXDONE_BY_ACK;
//如果是poll的方式,则注册一个timer,定时查询
if (txdone == TXDONE_BY_POLL) {

if (!mbox->ops->last_tx_done) {
dev_err(mbox->dev, "last_tx_done method is absent\n");
return -EINVAL;
}

hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
     HRTIMER_MODE_REL);
mbox->poll_hrt.function = txdone_hrtimer;
}
//初始化controller的channel,表示contoller 同时能尽量几路信息的传递
for (i = 0; i < mbox->num_chans; i++) {
struct mbox_chan *chan = &mbox->chans[i];

chan->cl = NULL;
chan->mbox = mbox;
chan->txdone_method = txdone;
spin_lock_init(&chan->lock);
}

if (!mbox->of_xlate)
mbox->of_xlate = of_mbox_index_xlate;
//所有的mailbox最终都会添加到mbox_cons 这个list中
mutex_lock(&con_mutex);
list_add_tail(&mbox->node, &mbox_cons);
mutex_unlock(&con_mutex);

return 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多