mirror of https://gitee.com/openkylin/linux.git
Mailbox related changes for omaps to get it to work with
device tree. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUEhQHAAoJEBvUPslcq6VzmwkP/2pgzQwgYGT+Bq7PHKO2ATKY 6F3/NKJJJiQhU264OcwK+/kR01j9giGOm6+c6KoVoT49S2c3SNFiSK13B7Z4xHh5 thh0kgwSgw1GLjHsP12SqTwNq9nxKjLXr1P4gHP/qER036Yu5cNedVnlII2Wysws UR4E1OcIRtNhQRLJ4snpIepNsAKlzKK8/QfNC2G/5Q9invCVeNeqcxauHAU7DFj/ k0X9LTpSjjgW4IBhXUntSd78My2OLBl28LGO1sjrMlw8w+cs76Z63C4K+VFRLSKE /AbU7dHowVuYgHQf9l86xZb/621aa3H1lvidgDaoa98LQnJAU6cnAp58fAoLGUKX R+xWI8P1r5gC2mnD2icx6QnHLy3TvAfwPSo8X+OnpUZwLpfHUfWXQvyp/RlByWVz BK/aX5dfhVtIH2qMGnwJohcfoZI+L/qrV7c98e5HytzvcDY4FkHsUhXzGyR+k93K WEfx9pXJHAvXJilNBf1mEQlqRGkEvSA4xW8eOgYeUkeEWWPc9uQ5Zlw4x7WsFnyE WJqRuZAAU1f40T9qFWG/nWWFnhKDpgzQHZ2r4pIB4/hxnhVsa47PK4tz8RnrZroK iWbC8ILzAlhFAcjepGyOJ6rMCuKovvHgHgmHoUyWBX7p2RN6SLG9u5K8ckAu3I59 O8b0yMx7voacigN7H8ia =Rph0 -----END PGP SIGNATURE----- Merge tag 'mailbox-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers Mailbox related changes for omaps to get it to work with device tree. * tag 'mailbox-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: mailbox/omap: add support for parsing dt devices Documentation: dt: add omap mailbox bindings Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
791cc88c57
|
@ -0,0 +1,108 @@
|
||||||
|
OMAP2+ Mailbox Driver
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The OMAP mailbox hardware facilitates communication between different processors
|
||||||
|
using a queued mailbox interrupt mechanism. The IP block is external to the
|
||||||
|
various processor subsystems and is connected on an interconnect bus. The
|
||||||
|
communication is achieved through a set of registers for message storage and
|
||||||
|
interrupt configuration registers.
|
||||||
|
|
||||||
|
Each mailbox IP block has a certain number of h/w fifo queues and output
|
||||||
|
interrupt lines. An output interrupt line is routed to an interrupt controller
|
||||||
|
within a processor subsystem, and there can be more than one line going to a
|
||||||
|
specific processor's interrupt controller. The interrupt line connections are
|
||||||
|
fixed for an instance and are dictated by the IP integration into the SoC
|
||||||
|
(excluding the SoCs that have a Interrupt Crossbar IP). Each interrupt line is
|
||||||
|
programmable through a set of interrupt configuration registers, and have a rx
|
||||||
|
and tx interrupt source per h/w fifo. Communication between different processors
|
||||||
|
is achieved through the appropriate programming of the rx and tx interrupt
|
||||||
|
sources on the appropriate interrupt lines.
|
||||||
|
|
||||||
|
The number of h/w fifo queues and interrupt lines dictate the usable registers.
|
||||||
|
All the current OMAP SoCs except for the newest DRA7xx SoC has a single IP
|
||||||
|
instance. DRA7xx has multiple instances with different number of h/w fifo queues
|
||||||
|
and interrupt lines between different instances. The interrupt lines can also be
|
||||||
|
routed to different processor sub-systems on DRA7xx as they are routed through
|
||||||
|
the Crossbar, a kind of interrupt router/multiplexer.
|
||||||
|
|
||||||
|
Mailbox Device Node:
|
||||||
|
====================
|
||||||
|
A Mailbox device node is used to represent a Mailbox IP instance within a SoC.
|
||||||
|
The sub-mailboxes are represented as child nodes of this parent node.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
--------------------
|
||||||
|
- compatible: Should be one of the following,
|
||||||
|
"ti,omap2-mailbox" for OMAP2420, OMAP2430 SoCs
|
||||||
|
"ti,omap3-mailbox" for OMAP3430, OMAP3630 SoCs
|
||||||
|
"ti,omap4-mailbox" for OMAP44xx, OMAP54xx, AM33xx,
|
||||||
|
AM43xx and DRA7xx SoCs
|
||||||
|
- reg: Contains the mailbox register address range (base
|
||||||
|
address and length)
|
||||||
|
- interrupts: Contains the interrupt information for the mailbox
|
||||||
|
device. The format is dependent on which interrupt
|
||||||
|
controller the OMAP device uses
|
||||||
|
- ti,hwmods: Name of the hwmod associated with the mailbox
|
||||||
|
- ti,mbox-num-users: Number of targets (processor devices) that the mailbox
|
||||||
|
device can interrupt
|
||||||
|
- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block
|
||||||
|
|
||||||
|
Child Nodes:
|
||||||
|
============
|
||||||
|
A child node is used for representing the actual sub-mailbox device that is
|
||||||
|
used for the communication between the host processor and a remote processor.
|
||||||
|
Each child node should have a unique node name across all the different
|
||||||
|
mailbox device nodes.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
--------------------
|
||||||
|
- ti,mbox-tx: sub-mailbox descriptor property defining a Tx fifo
|
||||||
|
- ti,mbox-rx: sub-mailbox descriptor property defining a Rx fifo
|
||||||
|
|
||||||
|
Sub-mailbox Descriptor Data
|
||||||
|
---------------------------
|
||||||
|
Each of the above ti,mbox-tx and ti,mbox-rx properties should have 3 cells of
|
||||||
|
data that represent the following:
|
||||||
|
Cell #1 (fifo_id) - mailbox fifo id used either for transmitting
|
||||||
|
(ti,mbox-tx) or for receiving (ti,mbox-rx)
|
||||||
|
Cell #2 (irq_id) - irq identifier index number to use from the parent's
|
||||||
|
interrupts data. Should be 0 for most of the cases, a
|
||||||
|
positive index value is seen only on mailboxes that have
|
||||||
|
multiple interrupt lines connected to the MPU processor.
|
||||||
|
Cell #3 (usr_id) - mailbox user id for identifying the interrupt line
|
||||||
|
associated with generating a tx/rx fifo interrupt.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
--------
|
||||||
|
|
||||||
|
/* OMAP4 */
|
||||||
|
mailbox: mailbox@4a0f4000 {
|
||||||
|
compatible = "ti,omap4-mailbox";
|
||||||
|
reg = <0x4a0f4000 0x200>;
|
||||||
|
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
ti,hwmods = "mailbox";
|
||||||
|
ti,mbox-num-users = <3>;
|
||||||
|
ti,mbox-num-fifos = <8>;
|
||||||
|
mbox_ipu: mbox_ipu {
|
||||||
|
ti,mbox-tx = <0 0 0>;
|
||||||
|
ti,mbox-rx = <1 0 0>;
|
||||||
|
};
|
||||||
|
mbox_dsp: mbox_dsp {
|
||||||
|
ti,mbox-tx = <3 0 0>;
|
||||||
|
ti,mbox-rx = <2 0 0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* AM33xx */
|
||||||
|
mailbox: mailbox@480C8000 {
|
||||||
|
compatible = "ti,omap4-mailbox";
|
||||||
|
reg = <0x480C8000 0x200>;
|
||||||
|
interrupts = <77>;
|
||||||
|
ti,hwmods = "mailbox";
|
||||||
|
ti,mbox-num-users = <4>;
|
||||||
|
ti,mbox-num-fifos = <8>;
|
||||||
|
mbox_wkupm3: wkup_m3 {
|
||||||
|
ti,mbox-tx = <0 0 0>;
|
||||||
|
ti,mbox-rx = <0 0 3>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/platform_data/mailbox-omap.h>
|
#include <linux/platform_data/mailbox-omap.h>
|
||||||
|
@ -94,6 +95,18 @@ struct omap_mbox_device {
|
||||||
struct list_head elem;
|
struct list_head elem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct omap_mbox_fifo_info {
|
||||||
|
int tx_id;
|
||||||
|
int tx_usr;
|
||||||
|
int tx_irq;
|
||||||
|
|
||||||
|
int rx_id;
|
||||||
|
int rx_usr;
|
||||||
|
int rx_irq;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
struct omap_mbox {
|
struct omap_mbox {
|
||||||
const char *name;
|
const char *name;
|
||||||
int irq;
|
int irq;
|
||||||
|
@ -587,24 +600,118 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id omap_mailbox_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "ti,omap2-mailbox",
|
||||||
|
.data = (void *)MBOX_INTR_CFG_TYPE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "ti,omap3-mailbox",
|
||||||
|
.data = (void *)MBOX_INTR_CFG_TYPE1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "ti,omap4-mailbox",
|
||||||
|
.data = (void *)MBOX_INTR_CFG_TYPE2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* end */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, omap_mailbox_of_match);
|
||||||
|
|
||||||
static int omap_mbox_probe(struct platform_device *pdev)
|
static int omap_mbox_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *mem;
|
struct resource *mem;
|
||||||
int ret;
|
int ret;
|
||||||
struct omap_mbox **list, *mbox, *mboxblk;
|
struct omap_mbox **list, *mbox, *mboxblk;
|
||||||
struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
|
struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
|
||||||
struct omap_mbox_dev_info *info;
|
struct omap_mbox_dev_info *info = NULL;
|
||||||
|
struct omap_mbox_fifo_info *finfo, *finfoblk;
|
||||||
struct omap_mbox_device *mdev;
|
struct omap_mbox_device *mdev;
|
||||||
struct omap_mbox_fifo *fifo;
|
struct omap_mbox_fifo *fifo;
|
||||||
u32 intr_type;
|
struct device_node *node = pdev->dev.of_node;
|
||||||
|
struct device_node *child;
|
||||||
|
const struct of_device_id *match;
|
||||||
|
u32 intr_type, info_count;
|
||||||
|
u32 num_users, num_fifos;
|
||||||
|
u32 tmp[3];
|
||||||
u32 l;
|
u32 l;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!pdata || !pdata->info_cnt || !pdata->info) {
|
if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) {
|
||||||
pr_err("%s: platform not supported\n", __func__);
|
pr_err("%s: platform not supported\n", __func__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
match = of_match_device(omap_mailbox_of_match, &pdev->dev);
|
||||||
|
if (!match)
|
||||||
|
return -ENODEV;
|
||||||
|
intr_type = (u32)match->data;
|
||||||
|
|
||||||
|
if (of_property_read_u32(node, "ti,mbox-num-users",
|
||||||
|
&num_users))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (of_property_read_u32(node, "ti,mbox-num-fifos",
|
||||||
|
&num_fifos))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
info_count = of_get_available_child_count(node);
|
||||||
|
if (!info_count) {
|
||||||
|
dev_err(&pdev->dev, "no available mbox devices found\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else { /* non-DT device creation */
|
||||||
|
info_count = pdata->info_cnt;
|
||||||
|
info = pdata->info;
|
||||||
|
intr_type = pdata->intr_type;
|
||||||
|
num_users = pdata->num_users;
|
||||||
|
num_fifos = pdata->num_fifos;
|
||||||
|
}
|
||||||
|
|
||||||
|
finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!finfoblk)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
finfo = finfoblk;
|
||||||
|
child = NULL;
|
||||||
|
for (i = 0; i < info_count; i++, finfo++) {
|
||||||
|
if (node) {
|
||||||
|
child = of_get_next_available_child(node, child);
|
||||||
|
ret = of_property_read_u32_array(child, "ti,mbox-tx",
|
||||||
|
tmp, ARRAY_SIZE(tmp));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
finfo->tx_id = tmp[0];
|
||||||
|
finfo->tx_irq = tmp[1];
|
||||||
|
finfo->tx_usr = tmp[2];
|
||||||
|
|
||||||
|
ret = of_property_read_u32_array(child, "ti,mbox-rx",
|
||||||
|
tmp, ARRAY_SIZE(tmp));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
finfo->rx_id = tmp[0];
|
||||||
|
finfo->rx_irq = tmp[1];
|
||||||
|
finfo->rx_usr = tmp[2];
|
||||||
|
|
||||||
|
finfo->name = child->name;
|
||||||
|
} else {
|
||||||
|
finfo->tx_id = info->tx_id;
|
||||||
|
finfo->rx_id = info->rx_id;
|
||||||
|
finfo->tx_usr = info->usr_id;
|
||||||
|
finfo->tx_irq = info->irq_id;
|
||||||
|
finfo->rx_usr = info->usr_id;
|
||||||
|
finfo->rx_irq = info->irq_id;
|
||||||
|
finfo->name = info->name;
|
||||||
|
info++;
|
||||||
|
}
|
||||||
|
if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos ||
|
||||||
|
finfo->tx_usr >= num_users || finfo->rx_usr >= num_users)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
|
mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
|
||||||
if (!mdev)
|
if (!mdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -615,41 +722,40 @@ static int omap_mbox_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(mdev->mbox_base);
|
return PTR_ERR(mdev->mbox_base);
|
||||||
|
|
||||||
/* allocate one extra for marking end of list */
|
/* allocate one extra for marking end of list */
|
||||||
list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
|
list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!list)
|
if (!list)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
|
mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!mboxblk)
|
if (!mboxblk)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
info = pdata->info;
|
|
||||||
intr_type = pdata->intr_type;
|
|
||||||
mbox = mboxblk;
|
mbox = mboxblk;
|
||||||
for (i = 0; i < pdata->info_cnt; i++, info++) {
|
finfo = finfoblk;
|
||||||
|
for (i = 0; i < info_count; i++, finfo++) {
|
||||||
fifo = &mbox->tx_fifo;
|
fifo = &mbox->tx_fifo;
|
||||||
fifo->msg = MAILBOX_MESSAGE(info->tx_id);
|
fifo->msg = MAILBOX_MESSAGE(finfo->tx_id);
|
||||||
fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
|
fifo->fifo_stat = MAILBOX_FIFOSTATUS(finfo->tx_id);
|
||||||
fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
|
fifo->intr_bit = MAILBOX_IRQ_NOTFULL(finfo->tx_id);
|
||||||
fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
|
fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->tx_usr);
|
||||||
fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
|
fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->tx_usr);
|
||||||
fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
|
fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->tx_usr);
|
||||||
|
|
||||||
fifo = &mbox->rx_fifo;
|
fifo = &mbox->rx_fifo;
|
||||||
fifo->msg = MAILBOX_MESSAGE(info->rx_id);
|
fifo->msg = MAILBOX_MESSAGE(finfo->rx_id);
|
||||||
fifo->msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
|
fifo->msg_stat = MAILBOX_MSGSTATUS(finfo->rx_id);
|
||||||
fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
|
fifo->intr_bit = MAILBOX_IRQ_NEWMSG(finfo->rx_id);
|
||||||
fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
|
fifo->irqenable = MAILBOX_IRQENABLE(intr_type, finfo->rx_usr);
|
||||||
fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
|
fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr);
|
||||||
fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
|
fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr);
|
||||||
|
|
||||||
mbox->intr_type = intr_type;
|
mbox->intr_type = intr_type;
|
||||||
|
|
||||||
mbox->parent = mdev;
|
mbox->parent = mdev;
|
||||||
mbox->name = info->name;
|
mbox->name = finfo->name;
|
||||||
mbox->irq = platform_get_irq(pdev, info->irq_id);
|
mbox->irq = platform_get_irq(pdev, finfo->tx_irq);
|
||||||
if (mbox->irq < 0)
|
if (mbox->irq < 0)
|
||||||
return mbox->irq;
|
return mbox->irq;
|
||||||
list[i] = mbox++;
|
list[i] = mbox++;
|
||||||
|
@ -657,8 +763,8 @@ static int omap_mbox_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
mutex_init(&mdev->cfg_lock);
|
mutex_init(&mdev->cfg_lock);
|
||||||
mdev->dev = &pdev->dev;
|
mdev->dev = &pdev->dev;
|
||||||
mdev->num_users = pdata->num_users;
|
mdev->num_users = num_users;
|
||||||
mdev->num_fifos = pdata->num_fifos;
|
mdev->num_fifos = num_fifos;
|
||||||
mdev->mboxes = list;
|
mdev->mboxes = list;
|
||||||
ret = omap_mbox_register(mdev);
|
ret = omap_mbox_register(mdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -684,6 +790,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto unregister;
|
goto unregister;
|
||||||
|
|
||||||
|
devm_kfree(&pdev->dev, finfoblk);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unregister:
|
unregister:
|
||||||
|
@ -708,6 +815,7 @@ static struct platform_driver omap_mbox_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "omap-mailbox",
|
.name = "omap-mailbox",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = of_match_ptr(omap_mailbox_of_match),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue