Commit 76044b05 authored by Tony Lindgren's avatar Tony Lindgren

Merge branch 'for-tony-mailbox'

Conflicts:

	arch/arm/plat-omap/Kconfig
	arch/arm/plat-omap/include/mach/omap34xx.h
	arch/arm/plat-omap/mailbox.c
parents 4a374e24 bf71df90
...@@ -86,7 +86,7 @@ static struct resource mbox_resources[] = { ...@@ -86,7 +86,7 @@ static struct resource mbox_resources[] = {
}; };
static struct platform_device mbox_device = { static struct platform_device mbox_device = {
.name = "mailbox", .name = "omap1-mailbox",
.id = -1, .id = -1,
.num_resources = ARRAY_SIZE(mbox_resources), .num_resources = ARRAY_SIZE(mbox_resources),
.resource = mbox_resources, .resource = mbox_resources,
......
/* /*
* Mailbox reservation modules for DSP * Mailbox reservation modules for DSP
* *
* Copyright (C) 2006 Nokia Corporation * Copyright (C) 2006-2008 Nokia Corporation
* Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* *
* This file is subject to the terms and conditions of the GNU General Public * This file is subject to the terms and conditions of the GNU General Public
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <mach/mailbox.h> #include <mach/mailbox.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#define DRV_NAME "omap1-mailbox"
#define MAILBOX_ARM2DSP1 0x00 #define MAILBOX_ARM2DSP1 0x00
#define MAILBOX_ARM2DSP1b 0x04 #define MAILBOX_ARM2DSP1b 0x04
#define MAILBOX_DSP2ARM1 0x08 #define MAILBOX_DSP2ARM1 0x08
...@@ -27,7 +29,7 @@ ...@@ -27,7 +29,7 @@
#define MAILBOX_DSP2ARM1_Flag 0x1c #define MAILBOX_DSP2ARM1_Flag 0x1c
#define MAILBOX_DSP2ARM2_Flag 0x20 #define MAILBOX_DSP2ARM2_Flag 0x20
unsigned long mbox_base; static void __iomem *mbox_base;
struct omap_mbox1_fifo { struct omap_mbox1_fifo {
unsigned long cmd; unsigned long cmd;
...@@ -40,14 +42,14 @@ struct omap_mbox1_priv { ...@@ -40,14 +42,14 @@ struct omap_mbox1_priv {
struct omap_mbox1_fifo rx_fifo; struct omap_mbox1_fifo rx_fifo;
}; };
static inline int mbox_read_reg(unsigned int reg) static inline int mbox_read_reg(size_t ofs)
{ {
return __raw_readw(mbox_base + reg); return __raw_readw(mbox_base + ofs);
} }
static inline void mbox_write_reg(unsigned int val, unsigned int reg) static inline void mbox_write_reg(u32 val, size_t ofs)
{ {
__raw_writew(val, mbox_base + reg); __raw_writew(val, mbox_base + ofs);
} }
/* msg */ /* msg */
...@@ -143,7 +145,7 @@ struct omap_mbox mbox_dsp_info = { ...@@ -143,7 +145,7 @@ struct omap_mbox mbox_dsp_info = {
}; };
EXPORT_SYMBOL(mbox_dsp_info); EXPORT_SYMBOL(mbox_dsp_info);
static int __init omap1_mbox_probe(struct platform_device *pdev) static int __devinit omap1_mbox_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int ret = 0; int ret = 0;
...@@ -170,12 +172,10 @@ static int __init omap1_mbox_probe(struct platform_device *pdev) ...@@ -170,12 +172,10 @@ static int __init omap1_mbox_probe(struct platform_device *pdev)
} }
mbox_dsp_info.irq = res->start; mbox_dsp_info.irq = res->start;
ret = omap_mbox_register(&mbox_dsp_info); return omap_mbox_register(&pdev->dev, &mbox_dsp_info);
return ret;
} }
static int omap1_mbox_remove(struct platform_device *pdev) static int __devexit omap1_mbox_remove(struct platform_device *pdev)
{ {
omap_mbox_unregister(&mbox_dsp_info); omap_mbox_unregister(&mbox_dsp_info);
...@@ -184,9 +184,9 @@ static int omap1_mbox_remove(struct platform_device *pdev) ...@@ -184,9 +184,9 @@ static int omap1_mbox_remove(struct platform_device *pdev)
static struct platform_driver omap1_mbox_driver = { static struct platform_driver omap1_mbox_driver = {
.probe = omap1_mbox_probe, .probe = omap1_mbox_probe,
.remove = omap1_mbox_remove, .remove = __devexit_p(omap1_mbox_remove),
.driver = { .driver = {
.name = "mailbox", .name = DRV_NAME,
}, },
}; };
...@@ -203,4 +203,7 @@ static void __exit omap1_mbox_exit(void) ...@@ -203,4 +203,7 @@ static void __exit omap1_mbox_exit(void)
module_init(omap1_mbox_init); module_init(omap1_mbox_init);
module_exit(omap1_mbox_exit); module_exit(omap1_mbox_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU" <Hiroshi.DOYU@nokia.com>);
MODULE_ALIAS("platform:"DRV_NAME);
...@@ -85,13 +85,14 @@ static inline void omap_init_camera(void) ...@@ -85,13 +85,14 @@ static inline void omap_init_camera(void)
} }
#endif #endif
#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) #if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
static struct resource mbox_resources[] = { #define MBOX_REG_SIZE 0x120
static struct resource omap2_mbox_resources[] = {
{ {
.start = OMAP2_MBOX_BASE, .start = OMAP24XX_MAILBOX_BASE,
.end = OMAP2_MBOX_BASE + 0x11f, .end = OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ {
...@@ -104,20 +105,39 @@ static struct resource mbox_resources[] = { ...@@ -104,20 +105,39 @@ static struct resource mbox_resources[] = {
}, },
}; };
static struct resource omap3_mbox_resources[] = {
{
.start = OMAP34XX_MAILBOX_BASE,
.end = OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
.start = INT_34XX_MAIL_U0_MPU,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device mbox_device = { static struct platform_device mbox_device = {
.name = "mailbox", .name = "omap2-mailbox",
.id = -1, .id = -1,
.num_resources = ARRAY_SIZE(mbox_resources),
.resource = mbox_resources,
}; };
static inline void omap_init_mbox(void) static inline void omap_init_mbox(void)
{ {
if (cpu_is_omap2420()) {
mbox_device.num_resources = ARRAY_SIZE(omap2_mbox_resources);
mbox_device.resource = omap2_mbox_resources;
} else if (cpu_is_omap3430()) {
mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
mbox_device.resource = omap3_mbox_resources;
} else {
return;
}
platform_device_register(&mbox_device); platform_device_register(&mbox_device);
} }
#else #else
static inline void omap_init_mbox(void) { } static inline void omap_init_mbox(void) { }
#endif #endif /* CONFIG_OMAP_MBOX_FWK */
#if defined(CONFIG_OMAP_STI) #if defined(CONFIG_OMAP_STI)
......
/* /*
* Mailbox reservation modules for OMAP2 * Mailbox reservation modules for OMAP2/3
* *
* Copyright (C) 2006 Nokia Corporation * Copyright (C) 2006-2008 Nokia Corporation
* Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* and Paul Mundt <paul.mundt@nokia.com> * and Paul Mundt
* *
* This file is subject to the terms and conditions of the GNU General Public * This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
...@@ -18,40 +18,23 @@ ...@@ -18,40 +18,23 @@
#include <mach/mailbox.h> #include <mach/mailbox.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#define MAILBOX_REVISION 0x00 #define DRV_NAME "omap2-mailbox"
#define MAILBOX_SYSCONFIG 0x10
#define MAILBOX_SYSSTATUS 0x14 #define MAILBOX_REVISION 0x000
#define MAILBOX_MESSAGE_0 0x40 #define MAILBOX_SYSCONFIG 0x010
#define MAILBOX_MESSAGE_1 0x44 #define MAILBOX_SYSSTATUS 0x014
#define MAILBOX_MESSAGE_2 0x48 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
#define MAILBOX_MESSAGE_3 0x4c #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
#define MAILBOX_MESSAGE_4 0x50 #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
#define MAILBOX_MESSAGE_5 0x54 #define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
#define MAILBOX_FIFOSTATUS_0 0x80 #define MAILBOX_IRQENABLE(u) (0x108 + 8 * (u))
#define MAILBOX_FIFOSTATUS_1 0x84
#define MAILBOX_FIFOSTATUS_2 0x88 #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u)))
#define MAILBOX_FIFOSTATUS_3 0x8c #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1))
#define MAILBOX_FIFOSTATUS_4 0x90
#define MAILBOX_FIFOSTATUS_5 0x94 #define MBOX_REG_SIZE 0x120
#define MAILBOX_MSGSTATUS_0 0xc0
#define MAILBOX_MSGSTATUS_1 0xc4 static void __iomem *mbox_base;
#define MAILBOX_MSGSTATUS_2 0xc8
#define MAILBOX_MSGSTATUS_3 0xcc
#define MAILBOX_MSGSTATUS_4 0xd0
#define MAILBOX_MSGSTATUS_5 0xd4
#define MAILBOX_IRQSTATUS_0 0x100
#define MAILBOX_IRQENABLE_0 0x104
#define MAILBOX_IRQSTATUS_1 0x108
#define MAILBOX_IRQENABLE_1 0x10c
#define MAILBOX_IRQSTATUS_2 0x110
#define MAILBOX_IRQENABLE_2 0x114
#define MAILBOX_IRQSTATUS_3 0x118
#define MAILBOX_IRQENABLE_3 0x11c
static unsigned long mbox_base;
#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1))
#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n)))
struct omap_mbox2_fifo { struct omap_mbox2_fifo {
unsigned long msg; unsigned long msg;
...@@ -66,6 +49,7 @@ struct omap_mbox2_priv { ...@@ -66,6 +49,7 @@ struct omap_mbox2_priv {
unsigned long irqstatus; unsigned long irqstatus;
u32 newmsg_bit; u32 newmsg_bit;
u32 notfull_bit; u32 notfull_bit;
char ctx[MBOX_REG_SIZE];
}; };
static struct clk *mbox_ick_handle; static struct clk *mbox_ick_handle;
...@@ -73,14 +57,14 @@ static struct clk *mbox_ick_handle; ...@@ -73,14 +57,14 @@ static struct clk *mbox_ick_handle;
static void omap2_mbox_enable_irq(struct omap_mbox *mbox, static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq); omap_mbox_type_t irq);
static inline unsigned int mbox_read_reg(unsigned int reg) static inline unsigned int mbox_read_reg(size_t ofs)
{ {
return __raw_readl(mbox_base + reg); return __raw_readl(mbox_base + ofs);
} }
static inline void mbox_write_reg(unsigned int val, unsigned int reg) static inline void mbox_write_reg(u32 val, size_t ofs)
{ {
__raw_writel(val, mbox_base + reg); __raw_writel(val, mbox_base + ofs);
} }
/* Mailbox H/W preparations */ /* Mailbox H/W preparations */
...@@ -95,6 +79,9 @@ static int omap2_mbox_startup(struct omap_mbox *mbox) ...@@ -95,6 +79,9 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
} }
clk_enable(mbox_ick_handle); clk_enable(mbox_ick_handle);
l = mbox_read_reg(MAILBOX_REVISION);
pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
/* set smart-idle & autoidle */ /* set smart-idle & autoidle */
l = mbox_read_reg(MAILBOX_SYSCONFIG); l = mbox_read_reg(MAILBOX_SYSCONFIG);
l |= 0x00000011; l |= 0x00000011;
...@@ -183,6 +170,36 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox, ...@@ -183,6 +170,36 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox,
return (enable & status & bit); return (enable & status & bit);
} }
static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
{
int i;
struct omap_mbox2_priv *p = mbox->priv;
for (i = 0; i < MBOX_REG_SIZE; i += sizeof(u32)) {
u32 val;
val = mbox_read_reg(i);
*(u32 *)(p->ctx + i) = val;
dev_dbg(mbox->dev, "%s\t[%02d] %08x\n", __func__, i, val);
}
}
static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
{
int i;
struct omap_mbox2_priv *p = mbox->priv;
for (i = 0; i < MBOX_REG_SIZE; i += sizeof(u32)) {
u32 val;
val = *(u32 *)(p->ctx + i);
mbox_write_reg(val, i);
dev_dbg(mbox->dev, "%s\t[%02d] %08x\n", __func__, i, val);
}
}
static struct omap_mbox_ops omap2_mbox_ops = { static struct omap_mbox_ops omap2_mbox_ops = {
.type = OMAP_MBOX_TYPE2, .type = OMAP_MBOX_TYPE2,
.startup = omap2_mbox_startup, .startup = omap2_mbox_startup,
...@@ -195,6 +212,8 @@ static struct omap_mbox_ops omap2_mbox_ops = { ...@@ -195,6 +212,8 @@ static struct omap_mbox_ops omap2_mbox_ops = {
.disable_irq = omap2_mbox_disable_irq, .disable_irq = omap2_mbox_disable_irq,
.ack_irq = omap2_mbox_ack_irq, .ack_irq = omap2_mbox_ack_irq,
.is_irq = omap2_mbox_is_irq, .is_irq = omap2_mbox_is_irq,
.save_ctx = omap2_mbox_save_ctx,
.restore_ctx = omap2_mbox_restore_ctx,
}; };
/* /*
...@@ -209,15 +228,15 @@ static struct omap_mbox_ops omap2_mbox_ops = { ...@@ -209,15 +228,15 @@ static struct omap_mbox_ops omap2_mbox_ops = {
/* DSP */ /* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = { static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
.tx_fifo = { .tx_fifo = {
.msg = MAILBOX_MESSAGE_0, .msg = MAILBOX_MESSAGE(0),
.fifo_stat = MAILBOX_FIFOSTATUS_0, .fifo_stat = MAILBOX_FIFOSTATUS(0),
}, },
.rx_fifo = { .rx_fifo = {
.msg = MAILBOX_MESSAGE_1, .msg = MAILBOX_MESSAGE(1),
.msg_stat = MAILBOX_MSGSTATUS_1, .msg_stat = MAILBOX_MSGSTATUS(1),
}, },
.irqenable = MAILBOX_IRQENABLE_0, .irqenable = MAILBOX_IRQENABLE(0),
.irqstatus = MAILBOX_IRQSTATUS_0, .irqstatus = MAILBOX_IRQSTATUS(0),
.notfull_bit = MAILBOX_IRQ_NOTFULL(0), .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(1), .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
}; };
...@@ -229,18 +248,18 @@ struct omap_mbox mbox_dsp_info = { ...@@ -229,18 +248,18 @@ struct omap_mbox mbox_dsp_info = {
}; };
EXPORT_SYMBOL(mbox_dsp_info); EXPORT_SYMBOL(mbox_dsp_info);
/* IVA */ #if defined(CONFIG_ARCH_OMAP2420) /* IVA */
static struct omap_mbox2_priv omap2_mbox_iva_priv = { static struct omap_mbox2_priv omap2_mbox_iva_priv = {
.tx_fifo = { .tx_fifo = {
.msg = MAILBOX_MESSAGE_2, .msg = MAILBOX_MESSAGE(2),
.fifo_stat = MAILBOX_FIFOSTATUS_2, .fifo_stat = MAILBOX_FIFOSTATUS(2),
}, },
.rx_fifo = { .rx_fifo = {
.msg = MAILBOX_MESSAGE_3, .msg = MAILBOX_MESSAGE(3),
.msg_stat = MAILBOX_MSGSTATUS_3, .msg_stat = MAILBOX_MSGSTATUS(3),
}, },
.irqenable = MAILBOX_IRQENABLE_3, .irqenable = MAILBOX_IRQENABLE(3),
.irqstatus = MAILBOX_IRQSTATUS_3, .irqstatus = MAILBOX_IRQSTATUS(3),
.notfull_bit = MAILBOX_IRQ_NOTFULL(2), .notfull_bit = MAILBOX_IRQ_NOTFULL(2),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(3), .newmsg_bit = MAILBOX_IRQ_NEWMSG(3),
}; };
...@@ -250,17 +269,12 @@ static struct omap_mbox mbox_iva_info = { ...@@ -250,17 +269,12 @@ static struct omap_mbox mbox_iva_info = {
.ops = &omap2_mbox_ops, .ops = &omap2_mbox_ops,
.priv = &omap2_mbox_iva_priv, .priv = &omap2_mbox_iva_priv,
}; };
#endif
static int __init omap2_mbox_probe(struct platform_device *pdev) static int __devinit omap2_mbox_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int ret = 0; int ret;
if (pdev->num_resources != 3) {
dev_err(&pdev->dev, "invalid number of resources: %d\n",
pdev->num_resources);
return -ENODEV;
}
/* MBOX base */ /* MBOX base */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -268,42 +282,62 @@ static int __init omap2_mbox_probe(struct platform_device *pdev) ...@@ -268,42 +282,62 @@ static int __init omap2_mbox_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "invalid mem resource\n"); dev_err(&pdev->dev, "invalid mem resource\n");
return -ENODEV; return -ENODEV;
} }
mbox_base = res->start; mbox_base = ioremap(res->start, res->end - res->start);
if (!mbox_base)
return -ENOMEM;
/* DSP IRQ */ /* DSP or IVA2 IRQ */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (unlikely(!res)) { if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n"); dev_err(&pdev->dev, "invalid irq resource\n");
return -ENODEV; ret = -ENODEV;
goto err_dsp;
} }
mbox_dsp_info.irq = res->start; mbox_dsp_info.irq = res->start;
ret = omap_mbox_register(&mbox_dsp_info); ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
if (ret)
/* IVA IRQ */ goto err_dsp;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (unlikely(!res)) { #if defined(CONFIG_ARCH_OMAP2420) /* IVA */
dev_err(&pdev->dev, "invalid irq resource\n"); if (cpu_is_omap2420()) {
return -ENODEV; /* IVA IRQ */
res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n");
ret = -ENODEV;
goto err_iva1;
}
mbox_iva_info.irq = res->start;
ret = omap_mbox_register(&pdev->dev, &mbox_iva_info);
if (ret)
goto err_iva1;
} }
mbox_iva_info.irq = res->start; #endif
return 0;
ret = omap_mbox_register(&mbox_iva_info);
err_iva1:
omap_mbox_unregister(&mbox_dsp_info);
err_dsp:
iounmap(mbox_base);
return ret; return ret;
} }
static int omap2_mbox_remove(struct platform_device *pdev) static int __devexit omap2_mbox_remove(struct platform_device *pdev)
{ {
#if defined(CONFIG_ARCH_OMAP2420)
omap_mbox_unregister(&mbox_iva_info);
#endif
omap_mbox_unregister(&mbox_dsp_info); omap_mbox_unregister(&mbox_dsp_info);
iounmap(mbox_base);
return 0; return 0;
} }
static struct platform_driver omap2_mbox_driver = { static struct platform_driver omap2_mbox_driver = {
.probe = omap2_mbox_probe, .probe = omap2_mbox_probe,
.remove = omap2_mbox_remove, .remove = __devexit_p(omap2_mbox_remove),
.driver = { .driver = {
.name = "mailbox", .name = DRV_NAME,
}, },
}; };
...@@ -320,4 +354,7 @@ static void __exit omap2_mbox_exit(void) ...@@ -320,4 +354,7 @@ static void __exit omap2_mbox_exit(void)
module_init(omap2_mbox_init); module_init(omap2_mbox_init);
module_exit(omap2_mbox_exit); module_exit(omap2_mbox_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
MODULE_ALIAS("platform:"DRV_NAME);
...@@ -180,7 +180,7 @@ config OMAP_MBOX_FWK ...@@ -180,7 +180,7 @@ config OMAP_MBOX_FWK
default n default n
help help
Say Y here if you want to use OMAP Mailbox framework support for Say Y here if you want to use OMAP Mailbox framework support for
DSP and IVA1.0 in OMAP1/2. DSP, IVA1.0 and IVA2 in OMAP1/2/3.
choice choice
prompt "System timer" prompt "System timer"
......
...@@ -33,6 +33,9 @@ struct omap_mbox_ops { ...@@ -33,6 +33,9 @@ struct omap_mbox_ops {
void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
/* ctx */
void (*save_ctx)(struct omap_mbox *mbox);
void (*restore_ctx)(struct omap_mbox *mbox);
}; };
struct omap_mbox_queue { struct omap_mbox_queue {
...@@ -53,7 +56,7 @@ struct omap_mbox { ...@@ -53,7 +56,7 @@ struct omap_mbox {
mbox_msg_t seq_snd, seq_rcv; mbox_msg_t seq_snd, seq_rcv;
struct device dev; struct device *dev;
struct omap_mbox *next; struct omap_mbox *next;
void *priv; void *priv;
...@@ -67,7 +70,27 @@ void omap_mbox_init_seq(struct omap_mbox *); ...@@ -67,7 +70,27 @@ void omap_mbox_init_seq(struct omap_mbox *);
struct omap_mbox *omap_mbox_get(const char *); struct omap_mbox *omap_mbox_get(const char *);
void omap_mbox_put(struct omap_mbox *); void omap_mbox_put(struct omap_mbox *);
int omap_mbox_register(struct omap_mbox *); int omap_mbox_register(struct device *parent, struct omap_mbox *);
int omap_mbox_unregister(struct omap_mbox *); int omap_mbox_unregister(struct omap_mbox *);
static inline void omap_mbox_save_ctx(struct omap_mbox *mbox)
{
if (!mbox->ops->save_ctx) {
dev_err(mbox->dev, "%s:\tno save\n", __func__);
return;
}
mbox->ops->save_ctx(mbox);
}
static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
{
if (!mbox->ops->restore_ctx) {
dev_err(mbox->dev, "%s:\tno restore\n", __func__);
return;
}
mbox->ops->restore_ctx(mbox);
}
#endif /* MAILBOX_H */ #endif /* MAILBOX_H */
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_PRM_BASE OMAP3430_PRM_BASE
#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE)
#define OMAP34XX_CAMERA_BASE (L4_34XX_BASE + 0xBC000) #define OMAP34XX_CAMERA_BASE (L4_34XX_BASE + 0xBC000)
#define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000)
#endif #endif
......
/* /*
* OMAP mailbox driver * OMAP mailbox driver
* *
* Copyright (C) 2006 Nokia Corporation. All rights reserved. * Copyright (C) 2006-2008 Nokia Corporation. All rights reserved.
* *
* Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -22,21 +21,98 @@ ...@@ -22,21 +21,98 @@
* *
*/ */
#include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/blkdev.h>
#include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h>
#include <mach/mailbox.h> #include <mach/mailbox.h>
#include "mailbox.h"
static int enable_seq_bit;
module_param(enable_seq_bit, bool, 0);
MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking.");
static struct omap_mbox *mboxes; static struct omap_mbox *mboxes;
static DEFINE_RWLOCK(mboxes_lock); static DEFINE_RWLOCK(mboxes_lock);
/*
* Mailbox sequence bit API
*/
/* seq_rcv should be initialized with any value other than
* 0 and 1 << 31, to allow either value for the first
* message. */
static inline void mbox_seq_init(struct omap_mbox *mbox)
{
if (!enable_seq_bit)
return;
/* any value other than 0 and 1 << 31 */
mbox->seq_rcv = 0xffffffff;
}
static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
{
if (!enable_seq_bit)
return;
/* add seq_snd to msg */
*msg = (*msg & 0x7fffffff) | mbox->seq_snd;
/* flip seq_snd */
mbox->seq_snd ^= 1 << 31;
}
static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
{
mbox_msg_t seq;
if (!enable_seq_bit)
return 0;
seq = msg & (1 << 31);
if (seq == mbox->seq_rcv)
return -1;
mbox->seq_rcv = seq;
return 0;
}
/* Mailbox FIFO handle functions */
static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{
return mbox->ops->fifo_read(mbox);
}
static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
mbox->ops->fifo_write(mbox, msg);
}
static inline int mbox_fifo_empty(struct omap_mbox *mbox)
{
return mbox->ops->fifo_empty(mbox);
}
static inline int mbox_fifo_full(struct omap_mbox *mbox)
{
return mbox->ops->fifo_full(mbox);
}
/* Mailbox IRQ handle functions */
static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->enable_irq(mbox, irq);
}
static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->disable_irq(mbox, irq);
}
static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
if (mbox->ops->ack_irq)
mbox->ops->ack_irq(mbox, irq);
}
static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
return mbox->ops->is_irq(mbox, irq);
}
/* Mailbox Sequence Bit function */ /* Mailbox Sequence Bit function */
void omap_mbox_init_seq(struct omap_mbox *mbox) void omap_mbox_init_seq(struct omap_mbox *mbox)
{ {
...@@ -136,7 +212,7 @@ static void mbox_rx_work(struct work_struct *work) ...@@ -136,7 +212,7 @@ static void mbox_rx_work(struct work_struct *work)
unsigned long flags; unsigned long flags;
if (mbox->rxq->callback == NULL) { if (mbox->rxq->callback == NULL) {
sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); sysfs_notify(&mbox->dev->kobj, NULL, "mbox");
return; return;
} }
...@@ -204,7 +280,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) ...@@ -204,7 +280,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
/* no more messages in the fifo. clear IRQ source. */ /* no more messages in the fifo. clear IRQ source. */
ack_mbox_irq(mbox, IRQ_RX); ack_mbox_irq(mbox, IRQ_RX);
enable_mbox_irq(mbox, IRQ_RX); enable_mbox_irq(mbox, IRQ_RX);
nomem: nomem:
schedule_work(&mbox->rxq->work); schedule_work(&mbox->rxq->work);
} }
...@@ -286,7 +362,7 @@ static ssize_t mbox_show(struct class *class, char *buf) ...@@ -286,7 +362,7 @@ static ssize_t mbox_show(struct class *class, char *buf)
static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
static struct class omap_mbox_class = { static struct class omap_mbox_class = {
.name = "omap_mbox", .name = "omap-mailbox",
}; };
static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
...@@ -333,21 +409,6 @@ static int omap_mbox_init(struct omap_mbox *mbox) ...@@ -333,21 +409,6 @@ static int omap_mbox_init(struct omap_mbox *mbox)
return ret; return ret;
} }
mbox->dev.class = &omap_mbox_class;
dev_set_name(&mbox->dev, "%s", mbox->name);
dev_set_drvdata(&mbox->dev, mbox);
ret = device_register(&mbox->dev);
if (unlikely(ret))
goto fail_device_reg;
ret = device_create_file(&mbox->dev, &dev_attr_mbox);
if (unlikely(ret)) {
printk(KERN_ERR
"device_create_file failed: %d\n", ret);
goto fail_create_mbox;
}
ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
mbox->name, mbox); mbox->name, mbox);
if (unlikely(ret)) { if (unlikely(ret)) {
...@@ -377,10 +438,6 @@ static int omap_mbox_init(struct omap_mbox *mbox) ...@@ -377,10 +438,6 @@ static int omap_mbox_init(struct omap_mbox *mbox)
fail_alloc_txq: fail_alloc_txq:
free_irq(mbox->irq, mbox); free_irq(mbox->irq, mbox);
fail_request_irq: fail_request_irq:
device_remove_file(&mbox->dev, &dev_attr_mbox);
fail_create_mbox:
device_unregister(&mbox->dev);
fail_device_reg:
if (unlikely(mbox->ops->shutdown)) if (unlikely(mbox->ops->shutdown))
mbox->ops->shutdown(mbox); mbox->ops->shutdown(mbox);
...@@ -393,8 +450,6 @@ static void omap_mbox_fini(struct omap_mbox *mbox) ...@@ -393,8 +450,6 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
mbox_queue_free(mbox->rxq); mbox_queue_free(mbox->rxq);
free_irq(mbox->irq, mbox); free_irq(mbox->irq, mbox);
device_remove_file(&mbox->dev, &dev_attr_mbox);
class_unregister(&omap_mbox_class);
if (unlikely(mbox->ops->shutdown)) if (unlikely(mbox->ops->shutdown))
mbox->ops->shutdown(mbox); mbox->ops->shutdown(mbox);
...@@ -440,7 +495,7 @@ void omap_mbox_put(struct omap_mbox *mbox) ...@@ -440,7 +495,7 @@ void omap_mbox_put(struct omap_mbox *mbox)
} }
EXPORT_SYMBOL(omap_mbox_put); EXPORT_SYMBOL(omap_mbox_put);
int omap_mbox_register(struct omap_mbox *mbox) int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
{ {
int ret = 0; int ret = 0;
struct omap_mbox **tmp; struct omap_mbox **tmp;
...@@ -450,14 +505,31 @@ int omap_mbox_register(struct omap_mbox *mbox) ...@@ -450,14 +505,31 @@ int omap_mbox_register(struct omap_mbox *mbox)
if (mbox->next) if (mbox->next)
return -EBUSY; return -EBUSY;
mbox->dev = device_create(&omap_mbox_class,
parent, 0, mbox, "%s", mbox->name);
if (IS_ERR(mbox->dev))
return PTR_ERR(mbox->dev);
ret = device_create_file(mbox->dev, &dev_attr_mbox);
if (ret)
goto err_sysfs;
write_lock(&mboxes_lock); write_lock(&mboxes_lock);
tmp = find_mboxes(mbox->name); tmp = find_mboxes(mbox->name);
if (*tmp) if (*tmp) {
ret = -EBUSY; ret = -EBUSY;
else write_unlock(&mboxes_lock);
*tmp = mbox; goto err_find;
}
*tmp = mbox;
write_unlock(&mboxes_lock); write_unlock(&mboxes_lock);
return 0;
err_find:
device_remove_file(mbox->dev, &dev_attr_mbox);
err_sysfs:
device_unregister(mbox->dev);
return ret; return ret;
} }
EXPORT_SYMBOL(omap_mbox_register); EXPORT_SYMBOL(omap_mbox_register);
...@@ -473,6 +545,8 @@ int omap_mbox_unregister(struct omap_mbox *mbox) ...@@ -473,6 +545,8 @@ int omap_mbox_unregister(struct omap_mbox *mbox)
*tmp = mbox->next; *tmp = mbox->next;
mbox->next = NULL; mbox->next = NULL;
write_unlock(&mboxes_lock); write_unlock(&mboxes_lock);
device_remove_file(mbox->dev, &dev_attr_mbox);
device_unregister(mbox->dev);
return 0; return 0;
} }
tmp = &(*tmp)->next; tmp = &(*tmp)->next;
...@@ -501,4 +575,6 @@ static void __exit omap_mbox_class_exit(void) ...@@ -501,4 +575,6 @@ static void __exit omap_mbox_class_exit(void)
subsys_initcall(omap_mbox_class_init); subsys_initcall(omap_mbox_class_init);
module_exit(omap_mbox_class_exit); module_exit(omap_mbox_class_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
MODULE_AUTHOR("Toshihiro Kobayashi and Hiroshi DOYU");
/*
* Mailbox internal functions
*
* Copyright (C) 2006 Nokia Corporation
* Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#ifndef __ARCH_ARM_PLAT_MAILBOX_H
#define __ARCH_ARM_PLAT_MAILBOX_H
/*
* Mailbox sequence bit API
*/
#if defined(CONFIG_ARCH_OMAP1)
# define MBOX_USE_SEQ_BIT
#elif defined(CONFIG_ARCH_OMAP2)
# define MBOX_USE_SEQ_BIT
#endif
#ifdef MBOX_USE_SEQ_BIT
/* seq_rcv should be initialized with any value other than
* 0 and 1 << 31, to allow either value for the first
* message. */
static inline void mbox_seq_init(struct omap_mbox *mbox)
{
/* any value other than 0 and 1 << 31 */
mbox->seq_rcv = 0xffffffff;
}
static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
{
/* add seq_snd to msg */
*msg = (*msg & 0x7fffffff) | mbox->seq_snd;
/* flip seq_snd */
mbox->seq_snd ^= 1 << 31;
}
static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
{
mbox_msg_t seq = msg & (1 << 31);
if (seq == mbox->seq_rcv)
return -1;
mbox->seq_rcv = seq;
return 0;
}
#else
static inline void mbox_seq_init(struct omap_mbox *mbox)
{
}
static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
{
}
static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
{
return 0;
}
#endif
/* Mailbox FIFO handle functions */
static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{
return mbox->ops->fifo_read(mbox);
}
static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
mbox->ops->fifo_write(mbox, msg);
}
static inline int mbox_fifo_empty(struct omap_mbox *mbox)
{
return mbox->ops->fifo_empty(mbox);
}
static inline int mbox_fifo_full(struct omap_mbox *mbox)
{
return mbox->ops->fifo_full(mbox);
}
/* Mailbox IRQ handle functions */
static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->enable_irq(mbox, irq);
}
static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
mbox->ops->disable_irq(mbox, irq);
}
static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
if (mbox->ops->ack_irq)
mbox->ops->ack_irq(mbox, irq);
}
static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
return mbox->ops->is_irq(mbox, irq);
}
#endif /* __ARCH_ARM_PLAT_MAILBOX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment