From: Olof Johansson Date: Fri, 14 Jun 2013 21:11:35 +0000 (-0700) Subject: Revert "Merge branch 'next/mailbox' into for-next" X-Git-Tag: next-20130617~16^2~29 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=b5c8518665039e18601eac306084ffa61177dc5f;p=karo-tx-linux.git Revert "Merge branch 'next/mailbox' into for-next" This reverts commit 51b5f8934223ec0a5a29b1cb0cdb7e97c8f42ba0, reversing changes made to c7788792a5e7b0d5d7f96d0766b4cb6112d47d75. --- diff --git a/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt b/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt deleted file mode 100644 index df0f59428074..000000000000 --- a/Documentation/devicetree/bindings/mailbox/dbx500-mailbox.txt +++ /dev/null @@ -1,27 +0,0 @@ -ST-Ericsson DBx500 PRCM Mailbox Driver - -Required properties: -- compatible : Should be - "stericsson,db8500-mailbox" for db8500 and db9500 - "stericsson,db9540-mailbox" for db9540 -- reg : Physical base address and length of mailbox's - registers and shared memory -- reg-names : Should contain the reg names "prcm-reg" and - "prcmu-tcdm" -- interrupts : contains the IRQ line for the PRCM mailbox -- interrupt-names : Should contain the interrupt name "irq" -- legacy-offset : Memory offset in shared mem for legacy mailboxes - -Optional properties: -- upap-offset : Memory offset in shared mem for upap mailboxes - -Examples: - -mailbox { - compatible = "stericsson,db8500-mailbox"; - reg = <0x80157000 0x1000>, <0x801B8000 0x2000>; - reg-names = "prcm-reg", "prcmu-tcdm"; - interrupts = <0 47 0x4>; - interrupt-names = "irq"; - legacy-offset = <0xdd4>; -}; diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig index d74edbad18fc..9940f7b4e438 100644 --- a/arch/arm/configs/omap1_defconfig +++ b/arch/arm/configs/omap1_defconfig @@ -26,8 +26,7 @@ CONFIG_ARCH_OMAP=y CONFIG_ARCH_OMAP1=y CONFIG_OMAP_RESET_CLOCKS=y # CONFIG_OMAP_MUX is not set -CONFIG_MAILBOX=y -CONFIG_OMAP1_MBOX=y +CONFIG_OMAP_MBOX_FWK=y CONFIG_OMAP_32K_TIMER=y CONFIG_OMAP_DM_TIMER=y CONFIG_ARCH_OMAP730=y diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 3889b6cd211e..222d58c0ae76 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -19,6 +19,10 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # Power Management obj-$(CONFIG_PM) += pm.o sleep.o +# DSP +obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o +mailbox_mach-objs := mailbox.o + i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) diff --git a/drivers/mailbox/mailbox-omap1.c b/arch/arm/mach-omap1/mailbox.c similarity index 64% rename from drivers/mailbox/mailbox-omap1.c rename to arch/arm/mach-omap1/mailbox.c index 44418726d23d..efc8f207f6fc 100644 --- a/drivers/mailbox/mailbox-omap1.c +++ b/arch/arm/mach-omap1/mailbox.c @@ -13,9 +13,7 @@ #include #include #include -#include - -#include "mailbox_internal.h" +#include #define MAILBOX_ARM2DSP1 0x00 #define MAILBOX_ARM2DSP1b 0x04 @@ -38,8 +36,6 @@ struct omap_mbox1_fifo { struct omap_mbox1_priv { struct omap_mbox1_fifo tx_fifo; struct omap_mbox1_fifo rx_fifo; - u32 data; - bool empty_flag; }; static inline int mbox_read_reg(size_t ofs) @@ -53,40 +49,34 @@ static inline void mbox_write_reg(u32 val, size_t ofs) } /* msg */ -static void omap1_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg) +static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) { - struct omap_mbox1_priv *priv = mbox->priv; - struct omap_mbox1_fifo *fifo = &priv->rx_fifo; + struct omap_mbox1_fifo *fifo = + &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; + mbox_msg_t msg; - priv->data = mbox_read_reg(fifo->data); - priv->data |= ((u32) mbox_read_reg(fifo->cmd)) << 16; - MAILBOX_FILL_MSG((*msg), 0, priv->data, 0); - priv->empty_flag = false; + msg = mbox_read_reg(fifo->data); + msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; + + return msg; } -static int -omap1_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg) +static void +omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) { struct omap_mbox1_fifo *fifo = &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; - u32 data = (u32)msg->pdata; - - mbox_write_reg(data & 0xffff, fifo->data); - mbox_write_reg(data >> 16, fifo->cmd); - return 0; + mbox_write_reg(msg & 0xffff, fifo->data); + mbox_write_reg(msg >> 16, fifo->cmd); } -static int omap1_mbox_fifo_empty(struct mailbox *mbox) +static int omap1_mbox_fifo_empty(struct omap_mbox *mbox) { - struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv; - if (priv->empty_flag) - return 0; - else - return 1; + return 0; } -static int omap1_mbox_fifo_full(struct mailbox *mbox) +static int omap1_mbox_fifo_full(struct omap_mbox *mbox) { struct omap_mbox1_fifo *fifo = &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; @@ -94,52 +84,35 @@ static int omap1_mbox_fifo_full(struct mailbox *mbox) return mbox_read_reg(fifo->flag); } -static int omap1_mbox_poll_for_space(struct mailbox *mbox) -{ - int ret = 0, i = 1000; - - while (omap1_mbox_fifo_full(mbox)) { - if (--i == 0) - return -1; - udelay(1); - } - return ret; -} - /* irq */ static void -omap1_mbox_enable_irq(struct mailbox *mbox, mailbox_type_t irq) +omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) { if (irq == IRQ_RX) enable_irq(mbox->irq); } static void -omap1_mbox_disable_irq(struct mailbox *mbox, mailbox_type_t irq) +omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) { if (irq == IRQ_RX) disable_irq(mbox->irq); } static int -omap1_mbox_is_irq(struct mailbox *mbox, mailbox_type_t irq) +omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) { - struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv; - if (irq == IRQ_TX) return 0; - if (irq == IRQ_RX) - priv->empty_flag = true; - return 1; } -static struct mailbox_ops omap1_mbox_ops = { - .type = MBOX_HW_FIFO1_TYPE, - .read = omap1_mbox_fifo_read, - .write = omap1_mbox_fifo_write, - .empty = omap1_mbox_fifo_empty, - .poll_for_space = omap1_mbox_poll_for_space, +static struct omap_mbox_ops omap1_mbox_ops = { + .type = OMAP_MBOX_TYPE1, + .fifo_read = omap1_mbox_fifo_read, + .fifo_write = omap1_mbox_fifo_write, + .fifo_empty = omap1_mbox_fifo_empty, + .fifo_full = omap1_mbox_fifo_full, .enable_irq = omap1_mbox_enable_irq, .disable_irq = omap1_mbox_disable_irq, .is_irq = omap1_mbox_is_irq, @@ -161,32 +134,29 @@ static struct omap_mbox1_priv omap1_mbox_dsp_priv = { }, }; -static struct mailbox mbox_dsp_info = { +static struct omap_mbox mbox_dsp_info = { .name = "dsp", .ops = &omap1_mbox_ops, .priv = &omap1_mbox_dsp_priv, }; -static struct mailbox *omap1_mboxes[] = { &mbox_dsp_info, NULL }; +static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL }; static int omap1_mbox_probe(struct platform_device *pdev) { struct resource *mem; int ret; - struct mailbox **list; + struct omap_mbox **list; list = omap1_mboxes; list[0]->irq = platform_get_irq_byname(pdev, "dsp"); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -ENOMEM; - mbox_base = ioremap(mem->start, resource_size(mem)); if (!mbox_base) return -ENOMEM; - ret = mailbox_register(&pdev->dev, list); + ret = omap_mbox_register(&pdev->dev, list); if (ret) { iounmap(mbox_base); return ret; @@ -197,7 +167,7 @@ static int omap1_mbox_probe(struct platform_device *pdev) static int omap1_mbox_remove(struct platform_device *pdev) { - mailbox_unregister(); + omap_mbox_unregister(); iounmap(mbox_base); return 0; } diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f2d19af051eb..55a9d6777683 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -203,6 +203,9 @@ obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o +obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o +mailbox_mach-objs := mailbox.o + iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o obj-y += $(iommu-m) $(iommu-y) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 60d4dcedee16..daa0ff65f599 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -328,31 +327,25 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data return 0; } -#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE) +#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE) static inline void __init omap_init_mbox(void) { struct omap_hwmod *oh; struct platform_device *pdev; - struct omap_mbox_pdata *pdata; oh = omap_hwmod_lookup("mailbox"); if (!oh) { pr_err("%s: unable to find hwmod\n", __func__); return; } - if (!oh->dev_attr) { - pr_err("%s: hwmod doesn't have valid attrs\n", __func__); - return; - } - pdata = (struct omap_mbox_pdata *)oh->dev_attr; - pdev = omap_device_build("omap-mailbox", -1, oh, pdata, sizeof(*pdata)); + pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n", __func__, PTR_ERR(pdev)); } #else static inline void omap_init_mbox(void) { } -#endif /* CONFIG_OMAP2PLUS_MBOX */ +#endif /* CONFIG_OMAP_MBOX_FWK */ static inline void omap_init_sti(void) {} diff --git a/drivers/mailbox/mailbox-omap2.c b/arch/arm/mach-omap2/mailbox.c similarity index 50% rename from drivers/mailbox/mailbox-omap2.c rename to arch/arm/mach-omap2/mailbox.c index eed5a3d6910f..0b080267b7f6 100644 --- a/drivers/mailbox/mailbox-omap2.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -11,15 +11,15 @@ */ #include -#include #include #include #include #include #include -#include -#include "mailbox_internal.h" +#include + +#include "soc.h" #define MAILBOX_REVISION 0x000 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) @@ -59,12 +59,10 @@ struct omap_mbox2_priv { u32 notfull_bit; u32 ctx[OMAP4_MBOX_NR_REGS]; unsigned long irqdisable; - u32 intr_type; - u32 data; }; -static void omap2_mbox_enable_irq(struct mailbox *mbox, - mailbox_type_t irq); +static void omap2_mbox_enable_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq); static inline unsigned int mbox_read_reg(size_t ofs) { @@ -77,7 +75,7 @@ static inline void mbox_write_reg(u32 val, size_t ofs) } /* Mailbox H/W preparations */ -static int omap2_mbox_startup(struct mailbox *mbox) +static int omap2_mbox_startup(struct omap_mbox *mbox) { u32 l; @@ -90,56 +88,44 @@ static int omap2_mbox_startup(struct mailbox *mbox) return 0; } -static void omap2_mbox_shutdown(struct mailbox *mbox) +static void omap2_mbox_shutdown(struct omap_mbox *mbox) { pm_runtime_put_sync(mbox->dev->parent); pm_runtime_disable(mbox->dev->parent); } /* Mailbox FIFO handle functions */ -static void omap2_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg) +static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) { - struct omap_mbox2_priv *priv = mbox->priv; - struct omap_mbox2_fifo *fifo = &priv->rx_fifo; - priv->data = mbox_read_reg(fifo->msg); - MAILBOX_FILL_MSG((*msg), 0, priv->data, 0); + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; + return (mbox_msg_t) mbox_read_reg(fifo->msg); } -static int omap2_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg) +static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) { struct omap_mbox2_fifo *fifo = &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; - - mbox_write_reg((u32)msg->pdata, fifo->msg); - - return 0; + mbox_write_reg(msg, fifo->msg); } -static int omap2_mbox_fifo_empty(struct mailbox *mbox) +static int omap2_mbox_fifo_empty(struct omap_mbox *mbox) { struct omap_mbox2_fifo *fifo = &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; return (mbox_read_reg(fifo->msg_stat) == 0); } -static int omap2_mbox_fifo_full(struct mailbox *mbox) +static int omap2_mbox_fifo_full(struct omap_mbox *mbox) { struct omap_mbox2_fifo *fifo = &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; return mbox_read_reg(fifo->fifo_stat); } -static int omap2_mbox_poll_for_space(struct mailbox *mbox) -{ - if (omap2_mbox_fifo_full(mbox)) - return -1; - - return 0; -} - /* Mailbox IRQ handle functions */ -static void omap2_mbox_enable_irq(struct mailbox *mbox, - mailbox_type_t irq) +static void omap2_mbox_enable_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -149,20 +135,20 @@ static void omap2_mbox_enable_irq(struct mailbox *mbox, mbox_write_reg(l, p->irqenable); } -static void omap2_mbox_disable_irq(struct mailbox *mbox, - mailbox_type_t irq) +static void omap2_mbox_disable_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - if (!p->intr_type) + if (!cpu_is_omap44xx()) bit = mbox_read_reg(p->irqdisable) & ~bit; mbox_write_reg(bit, p->irqdisable); } -static void omap2_mbox_ack_irq(struct mailbox *mbox, - mailbox_type_t irq) +static void omap2_mbox_ack_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -173,8 +159,8 @@ static void omap2_mbox_ack_irq(struct mailbox *mbox, mbox_read_reg(p->irqstatus); } -static int omap2_mbox_is_irq(struct mailbox *mbox, - mailbox_type_t irq) +static int omap2_mbox_is_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -184,13 +170,12 @@ static int omap2_mbox_is_irq(struct mailbox *mbox, return (int)(enable & status & bit); } -static void omap2_mbox_save_ctx(struct mailbox *mbox) +static void omap2_mbox_save_ctx(struct omap_mbox *mbox) { int i; struct omap_mbox2_priv *p = mbox->priv; int nr_regs; - - if (p->intr_type) + if (cpu_is_omap44xx()) nr_regs = OMAP4_MBOX_NR_REGS; else nr_regs = MBOX_NR_REGS; @@ -198,17 +183,16 @@ static void omap2_mbox_save_ctx(struct mailbox *mbox) p->ctx[i] = mbox_read_reg(i * sizeof(u32)); dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, - i, p->ctx[i]); + i, p->ctx[i]); } } -static void omap2_mbox_restore_ctx(struct mailbox *mbox) +static void omap2_mbox_restore_ctx(struct omap_mbox *mbox) { int i; struct omap_mbox2_priv *p = mbox->priv; int nr_regs; - - if (p->intr_type) + if (cpu_is_omap44xx()) nr_regs = OMAP4_MBOX_NR_REGS; else nr_regs = MBOX_NR_REGS; @@ -216,18 +200,18 @@ static void omap2_mbox_restore_ctx(struct mailbox *mbox) mbox_write_reg(p->ctx[i], i * sizeof(u32)); dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, - i, p->ctx[i]); + i, p->ctx[i]); } } -static struct mailbox_ops omap2_mbox_ops = { - .type = MBOX_HW_FIFO2_TYPE, +static struct omap_mbox_ops omap2_mbox_ops = { + .type = OMAP_MBOX_TYPE2, .startup = omap2_mbox_startup, .shutdown = omap2_mbox_shutdown, - .read = omap2_mbox_fifo_read, - .write = omap2_mbox_fifo_write, - .empty = omap2_mbox_fifo_empty, - .poll_for_space = omap2_mbox_poll_for_space, + .fifo_read = omap2_mbox_fifo_read, + .fifo_write = omap2_mbox_fifo_write, + .fifo_empty = omap2_mbox_fifo_empty, + .fifo_full = omap2_mbox_fifo_full, .enable_irq = omap2_mbox_enable_irq, .disable_irq = omap2_mbox_disable_irq, .ack_irq = omap2_mbox_ack_irq, @@ -236,116 +220,192 @@ static struct mailbox_ops omap2_mbox_ops = { .restore_ctx = omap2_mbox_restore_ctx, }; +/* + * MAILBOX 0: ARM -> DSP, + * MAILBOX 1: ARM <- DSP. + * MAILBOX 2: ARM -> IVA, + * MAILBOX 3: ARM <- IVA. + */ + +/* FIXME: the following structs should be filled automatically by the user id */ + +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2) +/* DSP */ +static struct omap_mbox2_priv omap2_mbox_dsp_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE(0), + .fifo_stat = MAILBOX_FIFOSTATUS(0), + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE(1), + .msg_stat = MAILBOX_MSGSTATUS(1), + }, + .irqenable = MAILBOX_IRQENABLE(0), + .irqstatus = MAILBOX_IRQSTATUS(0), + .notfull_bit = MAILBOX_IRQ_NOTFULL(0), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), + .irqdisable = MAILBOX_IRQENABLE(0), +}; + +struct omap_mbox mbox_dsp_info = { + .name = "dsp", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_dsp_priv, +}; +#endif + +#if defined(CONFIG_ARCH_OMAP3) +struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL }; +#endif + +#if defined(CONFIG_SOC_OMAP2420) +/* IVA */ +static struct omap_mbox2_priv omap2_mbox_iva_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE(2), + .fifo_stat = MAILBOX_FIFOSTATUS(2), + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE(3), + .msg_stat = MAILBOX_MSGSTATUS(3), + }, + .irqenable = MAILBOX_IRQENABLE(3), + .irqstatus = MAILBOX_IRQSTATUS(3), + .notfull_bit = MAILBOX_IRQ_NOTFULL(2), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), + .irqdisable = MAILBOX_IRQENABLE(3), +}; + +static struct omap_mbox mbox_iva_info = { + .name = "iva", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_iva_priv, +}; +#endif + +#ifdef CONFIG_ARCH_OMAP2 +struct omap_mbox *omap2_mboxes[] = { + &mbox_dsp_info, +#ifdef CONFIG_SOC_OMAP2420 + &mbox_iva_info, +#endif + NULL +}; +#endif + +#if defined(CONFIG_ARCH_OMAP4) +/* OMAP4 */ +static struct omap_mbox2_priv omap2_mbox_1_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE(0), + .fifo_stat = MAILBOX_FIFOSTATUS(0), + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE(1), + .msg_stat = MAILBOX_MSGSTATUS(1), + }, + .irqenable = OMAP4_MAILBOX_IRQENABLE(0), + .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0), + .notfull_bit = MAILBOX_IRQ_NOTFULL(0), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), + .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0), +}; + +struct omap_mbox mbox_1_info = { + .name = "mailbox-1", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_1_priv, +}; + +static struct omap_mbox2_priv omap2_mbox_2_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE(3), + .fifo_stat = MAILBOX_FIFOSTATUS(3), + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE(2), + .msg_stat = MAILBOX_MSGSTATUS(2), + }, + .irqenable = OMAP4_MAILBOX_IRQENABLE(0), + .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0), + .notfull_bit = MAILBOX_IRQ_NOTFULL(3), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(2), + .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0), +}; + +struct omap_mbox mbox_2_info = { + .name = "mailbox-2", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_2_priv, +}; + +struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL }; +#endif + static int omap2_mbox_probe(struct platform_device *pdev) { struct resource *mem; int ret; - struct mailbox **list, *mbox, *mboxblk; - struct omap_mbox2_priv *priv, *privblk; - struct omap_mbox_pdata *pdata = pdev->dev.platform_data; - struct omap_mbox_dev_info *info; - int i; + struct omap_mbox **list; - if (!pdata || !pdata->info_cnt || !pdata->info) { - pr_err("%s: platform not supported\n", __func__); - return -ENODEV; + if (false) + ; +#if defined(CONFIG_ARCH_OMAP3) + else if (cpu_is_omap34xx()) { + list = omap3_mboxes; + + list[0]->irq = platform_get_irq(pdev, 0); } +#endif +#if defined(CONFIG_ARCH_OMAP2) + else if (cpu_is_omap2430()) { + list = omap2_mboxes; - /* allocate one extra for marking end of list */ - list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL); - if (!list) - return -ENOMEM; + list[0]->irq = platform_get_irq(pdev, 0); + } else if (cpu_is_omap2420()) { + list = omap2_mboxes; - mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL); - if (!mboxblk) { - ret = -ENOMEM; - goto free_list; + list[0]->irq = platform_get_irq_byname(pdev, "dsp"); + list[1]->irq = platform_get_irq_byname(pdev, "iva"); } +#endif +#if defined(CONFIG_ARCH_OMAP4) + else if (cpu_is_omap44xx()) { + list = omap4_mboxes; - privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL); - if (!privblk) { - ret = -ENOMEM; - goto free_mboxblk; + list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0); } - - info = pdata->info; - for (i = 0; i < pdata->info_cnt; i++, info++, priv++) { - priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id); - priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); - priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id); - priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id); - priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); - priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); - if (pdata->intr_type) { - priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id); - priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id); - priv->irqdisable = - OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id); - } else { - priv->irqenable = MAILBOX_IRQENABLE(info->usr_id); - priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id); - priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id); - } - priv->intr_type = pdata->intr_type; - - mbox->priv = priv; - mbox->name = info->name; - mbox->ops = &omap2_mbox_ops; - mbox->irq = platform_get_irq(pdev, info->irq_id); - list[i] = mbox++; +#endif + else { + pr_err("%s: platform not supported\n", __func__); + return -ENODEV; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - ret = -ENOMEM; - goto free_privblk; - } - mbox_base = ioremap(mem->start, resource_size(mem)); - if (!mbox_base) { - ret = -ENOMEM; - goto free_privblk; - } + if (!mbox_base) + return -ENOMEM; - ret = mailbox_register(&pdev->dev, list); - if (ret) - goto unmap_mbox; - platform_set_drvdata(pdev, list); + ret = omap_mbox_register(&pdev->dev, list); + if (ret) { + iounmap(mbox_base); + return ret; + } return 0; - -unmap_mbox: - iounmap(mbox_base); -free_privblk: - kfree(privblk); -free_mboxblk: - kfree(mboxblk); -free_list: - kfree(list); - return ret; } static int omap2_mbox_remove(struct platform_device *pdev) { - struct omap_mbox2_priv *privblk; - struct mailbox **list = platform_get_drvdata(pdev); - struct mailbox *mboxblk = list[0]; - - privblk = mboxblk->priv; - mailbox_unregister(); + omap_mbox_unregister(); iounmap(mbox_base); - kfree(privblk); - kfree(mboxblk); - kfree(list); - platform_set_drvdata(pdev, NULL); - return 0; } static struct platform_driver omap2_mbox_driver = { - .probe = omap2_mbox_probe, - .remove = omap2_mbox_remove, - .driver = { + .probe = omap2_mbox_probe, + .remove = omap2_mbox_remove, + .driver = { .name = "omap-mailbox", }, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index dbcb928eea50..5137cc84b504 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "omap_hwmod.h" @@ -167,16 +166,6 @@ static struct omap_hwmod omap2420_dma_system_hwmod = { }; /* mailbox */ -static struct omap_mbox_dev_info omap2420_mailbox_info[] = { - { .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 }, - { .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 }, -}; - -static struct omap_mbox_pdata omap2420_mailbox_attrs = { - .info_cnt = ARRAY_SIZE(omap2420_mailbox_info), - .info = omap2420_mailbox_info, -}; - static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = { { .name = "dsp", .irq = 26 + OMAP_INTC_START, }, { .name = "iva", .irq = 34 + OMAP_INTC_START, }, @@ -197,7 +186,6 @@ static struct omap_hwmod omap2420_mailbox_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT, }, }, - .dev_attr = &omap2420_mailbox_attrs, }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index df2f8742fe41..4ce999ee3ee9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "omap_hwmod.h" @@ -171,15 +170,6 @@ static struct omap_hwmod omap2430_dma_system_hwmod = { }; /* mailbox */ -static struct omap_mbox_dev_info omap2430_mailbox_info[] = { - { .name = "dsp", .tx_id = 0, .rx_id = 1 }, -}; - -static struct omap_mbox_pdata omap2430_mailbox_attrs = { - .info_cnt = ARRAY_SIZE(omap2430_mailbox_info), - .info = omap2430_mailbox_info, -}; - static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = { { .irq = 26 + OMAP_INTC_START, }, { .irq = -1 }, @@ -199,7 +189,6 @@ static struct omap_hwmod omap2430_mailbox_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT, }, }, - .dev_attr = &omap2430_mailbox_attrs, }; /* mcspi3 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 9ac5122396d8..31c7126eb3bb 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "am35xx.h" @@ -1506,15 +1505,6 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = { .sysc = &omap3xxx_mailbox_sysc, }; -static struct omap_mbox_dev_info omap3xxx_mailbox_info[] = { - { .name = "dsp", .tx_id = 0, .rx_id = 1 }, -}; - -static struct omap_mbox_pdata omap3xxx_mailbox_attrs = { - .info_cnt = ARRAY_SIZE(omap3xxx_mailbox_info), - .info = omap3xxx_mailbox_info, -}; - static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = { { .irq = 26 + OMAP_INTC_START, }, { .irq = -1 }, @@ -1534,7 +1524,6 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = { .idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT, }, }, - .dev_attr = &omap3xxx_mailbox_attrs, }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 4065962fe04d..848b6dc67590 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "omap_hwmod.h" @@ -1862,17 +1861,6 @@ static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = { }; /* mailbox */ -static struct omap_mbox_dev_info omap44xx_mailbox_info[] = { - { .name = "mbox-ipu", .tx_id = 0, .rx_id = 1 }, - { .name = "mbox-dsp", .tx_id = 3, .rx_id = 2 }, -}; - -static struct omap_mbox_pdata omap44xx_mailbox_attrs = { - .intr_type = MBOX_INTR_CFG_TYPE2, - .info_cnt = ARRAY_SIZE(omap44xx_mailbox_info), - .info = omap44xx_mailbox_info, -}; - static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = { { .irq = 26 + OMAP44XX_IRQ_GIC_START }, { .irq = -1 } @@ -1889,7 +1877,6 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = { .context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET, }, }, - .dev_attr = &omap44xx_mailbox_attrs, }; /* diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index f82bae2171eb..ce66eb9be481 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -86,6 +86,22 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. +config OMAP_MBOX_FWK + tristate "Mailbox framework support" + depends on ARCH_OMAP && !ARCH_MULTIPLATFORM + help + Say Y here if you want to use OMAP Mailbox framework support for + DSP, IVA1.0 and IVA2 in OMAP1/2/3. + +config OMAP_MBOX_KFIFO_SIZE + int "Mailbox kfifo default buffer size (bytes)" + depends on OMAP_MBOX_FWK + default 256 + help + Specify the default size of mailbox's kfifo buffers (bytes). + This can also be changed at runtime (via the mbox_kfifo_size + module parameter). + config OMAP_IOMMU_IVA2 bool diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 0b01b68fd033..31199417b56a 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -17,3 +17,6 @@ obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) +# OMAP mailbox framework +obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o + diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h new file mode 100644 index 000000000000..cc3921e9059c --- /dev/null +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -0,0 +1,105 @@ +/* mailbox.h */ + +#ifndef MAILBOX_H +#define MAILBOX_H + +#include +#include +#include +#include +#include + +typedef u32 mbox_msg_t; +struct omap_mbox; + +typedef int __bitwise omap_mbox_irq_t; +#define IRQ_TX ((__force omap_mbox_irq_t) 1) +#define IRQ_RX ((__force omap_mbox_irq_t) 2) + +typedef int __bitwise omap_mbox_type_t; +#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1) +#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2) + +struct omap_mbox_ops { + omap_mbox_type_t type; + int (*startup)(struct omap_mbox *mbox); + void (*shutdown)(struct omap_mbox *mbox); + /* fifo */ + mbox_msg_t (*fifo_read)(struct omap_mbox *mbox); + void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg); + int (*fifo_empty)(struct omap_mbox *mbox); + int (*fifo_full)(struct omap_mbox *mbox); + /* irq */ + void (*enable_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); + 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 { + spinlock_t lock; + struct kfifo fifo; + struct work_struct work; + struct tasklet_struct tasklet; + struct omap_mbox *mbox; + bool full; +}; + +struct omap_mbox { + char *name; + unsigned int irq; + struct omap_mbox_queue *txq, *rxq; + struct omap_mbox_ops *ops; + struct device *dev; + void *priv; + int use_count; + struct blocking_notifier_head notifier; +}; + +int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); +void omap_mbox_init_seq(struct omap_mbox *); + +struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); + +int omap_mbox_register(struct device *parent, struct omap_mbox **); +int omap_mbox_unregister(void); + +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); +} + +static inline void omap_mbox_enable_irq(struct omap_mbox *mbox, + omap_mbox_irq_t irq) +{ + mbox->ops->enable_irq(mbox, irq); +} + +static inline void omap_mbox_disable_irq(struct omap_mbox *mbox, + omap_mbox_irq_t irq) +{ + mbox->ops->disable_irq(mbox, irq); +} + +#endif /* MAILBOX_H */ diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c new file mode 100644 index 000000000000..42377ef9ea3d --- /dev/null +++ b/arch/arm/plat-omap/mailbox.c @@ -0,0 +1,435 @@ +/* + * OMAP mailbox driver + * + * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. + * + * Contact: Hiroshi DOYU + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct omap_mbox **mboxes; + +static int mbox_configured; +static DEFINE_MUTEX(mbox_configured_lock); + +static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; +module_param(mbox_kfifo_size, uint, S_IRUGO); +MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); + +/* 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 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); +} + +/* + * message sender + */ +static int __mbox_poll_for_space(struct omap_mbox *mbox) +{ + int ret = 0, i = 1000; + + while (mbox_fifo_full(mbox)) { + if (mbox->ops->type == OMAP_MBOX_TYPE2) + return -1; + if (--i == 0) + return -1; + udelay(1); + } + return ret; +} + +int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) +{ + struct omap_mbox_queue *mq = mbox->txq; + int ret = 0, len; + + spin_lock_bh(&mq->lock); + + if (kfifo_avail(&mq->fifo) < sizeof(msg)) { + ret = -ENOMEM; + goto out; + } + + if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) { + mbox_fifo_write(mbox, msg); + goto out; + } + + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); + + tasklet_schedule(&mbox->txq->tasklet); + +out: + spin_unlock_bh(&mq->lock); + return ret; +} +EXPORT_SYMBOL(omap_mbox_msg_send); + +static void mbox_tx_tasklet(unsigned long tx_data) +{ + struct omap_mbox *mbox = (struct omap_mbox *)tx_data; + struct omap_mbox_queue *mq = mbox->txq; + mbox_msg_t msg; + int ret; + + while (kfifo_len(&mq->fifo)) { + if (__mbox_poll_for_space(mbox)) { + omap_mbox_enable_irq(mbox, IRQ_TX); + break; + } + + ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, + sizeof(msg)); + WARN_ON(ret != sizeof(msg)); + + mbox_fifo_write(mbox, msg); + } +} + +/* + * Message receiver(workqueue) + */ +static void mbox_rx_work(struct work_struct *work) +{ + struct omap_mbox_queue *mq = + container_of(work, struct omap_mbox_queue, work); + mbox_msg_t msg; + int len; + + while (kfifo_len(&mq->fifo) >= sizeof(msg)) { + len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); + + blocking_notifier_call_chain(&mq->mbox->notifier, len, + (void *)msg); + spin_lock_irq(&mq->lock); + if (mq->full) { + mq->full = false; + omap_mbox_enable_irq(mq->mbox, IRQ_RX); + } + spin_unlock_irq(&mq->lock); + } +} + +/* + * Mailbox interrupt handler + */ +static void __mbox_tx_interrupt(struct omap_mbox *mbox) +{ + omap_mbox_disable_irq(mbox, IRQ_TX); + ack_mbox_irq(mbox, IRQ_TX); + tasklet_schedule(&mbox->txq->tasklet); +} + +static void __mbox_rx_interrupt(struct omap_mbox *mbox) +{ + struct omap_mbox_queue *mq = mbox->rxq; + mbox_msg_t msg; + int len; + + while (!mbox_fifo_empty(mbox)) { + if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { + omap_mbox_disable_irq(mbox, IRQ_RX); + mq->full = true; + goto nomem; + } + + msg = mbox_fifo_read(mbox); + + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); + + if (mbox->ops->type == OMAP_MBOX_TYPE1) + break; + } + + /* no more messages in the fifo. clear IRQ source. */ + ack_mbox_irq(mbox, IRQ_RX); +nomem: + schedule_work(&mbox->rxq->work); +} + +static irqreturn_t mbox_interrupt(int irq, void *p) +{ + struct omap_mbox *mbox = p; + + if (is_mbox_irq(mbox, IRQ_TX)) + __mbox_tx_interrupt(mbox); + + if (is_mbox_irq(mbox, IRQ_RX)) + __mbox_rx_interrupt(mbox); + + return IRQ_HANDLED; +} + +static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, + void (*work) (struct work_struct *), + void (*tasklet)(unsigned long)) +{ + struct omap_mbox_queue *mq; + + mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); + if (!mq) + return NULL; + + spin_lock_init(&mq->lock); + + if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) + goto error; + + if (work) + INIT_WORK(&mq->work, work); + + if (tasklet) + tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox); + return mq; +error: + kfree(mq); + return NULL; +} + +static void mbox_queue_free(struct omap_mbox_queue *q) +{ + kfifo_free(&q->fifo); + kfree(q); +} + +static int omap_mbox_startup(struct omap_mbox *mbox) +{ + int ret = 0; + struct omap_mbox_queue *mq; + + mutex_lock(&mbox_configured_lock); + if (!mbox_configured++) { + if (likely(mbox->ops->startup)) { + ret = mbox->ops->startup(mbox); + if (unlikely(ret)) + goto fail_startup; + } else + goto fail_startup; + } + + if (!mbox->use_count++) { + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + pr_err("failed to register mailbox interrupt:%d\n", + ret); + goto fail_request_irq; + } + mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_txq; + } + mbox->txq = mq; + + mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_rxq; + } + mbox->rxq = mq; + mq->mbox = mbox; + + omap_mbox_enable_irq(mbox, IRQ_RX); + } + mutex_unlock(&mbox_configured_lock); + return 0; + +fail_alloc_rxq: + mbox_queue_free(mbox->txq); +fail_alloc_txq: + free_irq(mbox->irq, mbox); +fail_request_irq: + if (mbox->ops->shutdown) + mbox->ops->shutdown(mbox); + mbox->use_count--; +fail_startup: + mbox_configured--; + mutex_unlock(&mbox_configured_lock); + return ret; +} + +static void omap_mbox_fini(struct omap_mbox *mbox) +{ + mutex_lock(&mbox_configured_lock); + + if (!--mbox->use_count) { + omap_mbox_disable_irq(mbox, IRQ_RX); + free_irq(mbox->irq, mbox); + tasklet_kill(&mbox->txq->tasklet); + flush_work(&mbox->rxq->work); + mbox_queue_free(mbox->txq); + mbox_queue_free(mbox->rxq); + } + + if (likely(mbox->ops->shutdown)) { + if (!--mbox_configured) + mbox->ops->shutdown(mbox); + } + + mutex_unlock(&mbox_configured_lock); +} + +struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) +{ + struct omap_mbox *_mbox, *mbox = NULL; + int i, ret; + + if (!mboxes) + return ERR_PTR(-EINVAL); + + for (i = 0; (_mbox = mboxes[i]); i++) { + if (!strcmp(_mbox->name, name)) { + mbox = _mbox; + break; + } + } + + if (!mbox) + return ERR_PTR(-ENOENT); + + if (nb) + blocking_notifier_chain_register(&mbox->notifier, nb); + + ret = omap_mbox_startup(mbox); + if (ret) { + blocking_notifier_chain_unregister(&mbox->notifier, nb); + return ERR_PTR(-ENODEV); + } + + return mbox; +} +EXPORT_SYMBOL(omap_mbox_get); + +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&mbox->notifier, nb); + omap_mbox_fini(mbox); +} +EXPORT_SYMBOL(omap_mbox_put); + +static struct class omap_mbox_class = { .name = "mbox", }; + +int omap_mbox_register(struct device *parent, struct omap_mbox **list) +{ + int ret; + int i; + + mboxes = list; + if (!mboxes) + return -EINVAL; + + for (i = 0; mboxes[i]; i++) { + struct omap_mbox *mbox = mboxes[i]; + mbox->dev = device_create(&omap_mbox_class, + parent, 0, mbox, "%s", mbox->name); + if (IS_ERR(mbox->dev)) { + ret = PTR_ERR(mbox->dev); + goto err_out; + } + + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); + } + return 0; + +err_out: + while (i--) + device_unregister(mboxes[i]->dev); + return ret; +} +EXPORT_SYMBOL(omap_mbox_register); + +int omap_mbox_unregister(void) +{ + int i; + + if (!mboxes) + return -EINVAL; + + for (i = 0; mboxes[i]; i++) + device_unregister(mboxes[i]->dev); + mboxes = NULL; + return 0; +} +EXPORT_SYMBOL(omap_mbox_unregister); + +static int __init omap_mbox_init(void) +{ + int err; + + err = class_register(&omap_mbox_class); + if (err) + return err; + + /* kfifo size sanity check: alignment and minimal size */ + mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, + sizeof(mbox_msg_t)); + + return 0; +} +subsys_initcall(omap_mbox_init); + +static void __exit omap_mbox_exit(void) +{ + class_unregister(&omap_mbox_class); +} +module_exit(omap_mbox_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); +MODULE_AUTHOR("Toshihiro Kobayashi"); +MODULE_AUTHOR("Hiroshi DOYU"); diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 3118b87a37bc..b61b5a3fad64 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #define HB_CPUFREQ_CHANGE_NOTE 0x80000001 diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 438ea213dd99..9545c9f03809 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -16,45 +16,4 @@ config PL320_MBOX Management Engine, primarily for cpufreq. Say Y here if you want to use the PL320 IPCM support. -config OMAP1_MBOX - tristate "OMAP1 Mailbox framework support" - depends on ARCH_OMAP1 - help - Mailbox implementation for OMAP chips with hardware for - interprocessor communication involving DSP in OMAP1. Say Y here - if you want to use OMAP1 Mailbox framework support. - -config OMAP2PLUS_MBOX - tristate "OMAP2+ Mailbox framework support" - depends on ARCH_OMAP2PLUS - help - Mailbox implementation for OMAP family chips with hardware for - interprocessor communication involving DSP, IVA1.0 and IVA2 in - OMAP2/3; or IPU, IVA HD and DSP in OMAP4. Say Y here if you want - to use OMAP2+ Mailbox framework support. - -config DBX500_MBOX - tristate "DBx500 Mailbox driver support" - depends on ARCH_U8500 - help - Say Y here if you want to use DBx500 Mailbox driver support for - power coprocessor access on Ux500 and Ux540 families - -config MBOX_KFIFO_SIZE - int "Mailbox kfifo default buffer size (bytes)" - default 256 - help - Specify the default size of mailbox's kfifo buffers (bytes). - This can also be changed at runtime (via the mbox_kfifo_size - module parameter). - -config MBOX_DATA_SIZE - int "Mailbox associated data max size (bytes)" - default 64 if DBX500_MBOX - default 4 - help - Specify the default size of mailbox's associated data buffer - (bytes) - This can also be changed at runtime (via the mbox_kfifo_size - module parameter). endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index ee5fb1e46452..543ad6a79505 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -1,6 +1 @@ obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o - -obj-$(CONFIG_MAILBOX) += mailbox.o -obj-$(CONFIG_OMAP1_MBOX) += mailbox-omap1.o -obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox-omap2.o -obj-$(CONFIG_DBX500_MBOX) += mailbox-dbx500.o diff --git a/drivers/mailbox/mailbox-dbx500.c b/drivers/mailbox/mailbox-dbx500.c deleted file mode 100644 index e9d2b0a9b3b4..000000000000 --- a/drivers/mailbox/mailbox-dbx500.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2012 - * - * License Terms: GNU General Public License v2 - * Author: Loic Pallardy for ST-Ericsson - * DBX500 PRCM Mailbox driver - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mailbox_internal.h" - -#define MAILBOX_LEGACY 0 -#define MAILBOX_UPAP 1 - -enum { - MAILBOX_BLOCKING, - MAILBOX_ATOMIC, -}; - -/* CPU mailbox registers */ -#define PRCM_MBOX_CPU_VAL 0x0fc -#define PRCM_MBOX_CPU_SET 0x100 -#define PRCM_MBOX_CPU_CLR 0x104 - -#define PRCM_ARM_IT1_CLR 0x48C -#define PRCM_ARM_IT1_VAL 0x494 - -#define NUM_MB 8 -#define MBOX_BIT BIT -#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1) - -/* CPU mailbox shared memory */ -#define PRCM_MBOX_LEGACY_SIZE 0x220 -#define _PRCM_MBOX_HEADER 0x214 /* 16 bytes */ -#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0) -#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1) -#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2) -#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3) -#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4) -#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5) -#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8) - -/* Req Mailboxes */ -#define PRCM_REQ_MB0 0x208 /* 12 bytes */ -#define PRCM_REQ_MB1 0x1FC /* 12 bytes */ -#define PRCM_REQ_MB2 0x1EC /* 16 bytes */ -#define PRCM_REQ_MB3 0x78 /* 372 bytes */ -#define PRCM_REQ_MB4 0x74 /* 4 bytes */ -#define PRCM_REQ_MB5 0x70 /* 4 bytes */ -#define PRCM_REQ_PASR 0x30 /* 4 bytes */ - -/* Ack Mailboxes */ -#define PRCM_ACK_MB0 0x34 /* 52 bytes */ -#define PRCM_ACK_MB1 0x30 /* 4 bytes */ -#define PRCM_ACK_MB2 0x2C /* 4 bytes */ -#define PRCM_ACK_MB3 0x28 /* 4 bytes */ -#define PRCM_ACK_MB4 0x24 /* 4 bytes */ -#define PRCM_ACK_MB5 0x20 /* 4 bytes */ - -/* Ack Mailboxe sizes */ -#define PRCM_ACK_MB0_SIZE 0x24 /* 52 bytes */ -#define PRCM_ACK_MB1_SIZE 0x4 /* 4 bytes */ -#define PRCM_ACK_MB2_SIZE 0x1 /* 1 bytes */ -#define PRCM_ACK_MB3_SIZE 0x2 /* 2 bytes */ -#define PRCM_ACK_MB4_SIZE 0x0 /* 0 bytes */ -#define PRCM_ACK_MB5_SIZE 0x4 /* 4 bytes */ - -static void __iomem *mbox_base; -static void __iomem *tcdm_mem_base; - -static u8 prcm_mbox_irq_mask; /* masked by default */ -static DEFINE_SPINLOCK(prcm_mbox_irqs_lock); - -struct dbx500_mbox_priv { - int access_mode; - int type; - int header_size; - unsigned int tx_header_offset; - unsigned int rx_header_offset; - unsigned int tx_offset; - unsigned int rx_offset; - unsigned int rx_size; - unsigned int sw_irq; - bool empty_flag; -}; - -static inline unsigned int mbox_read_reg(size_t ofs) -{ - return __raw_readl(mbox_base + ofs); -} - -static inline void mbox_write_reg(u32 val, size_t ofs) -{ - __raw_writel(val, mbox_base + ofs); -} - -/* Mailbox H/W preparations */ -static struct irq_chip dbx500_mbox_irq_chip; -static struct irq_domain *dbx500_mbox_irq_domain; - -static int dbx500_mbox_startup(struct mailbox *mbox) -{ - /* Nothing to do */ - return 0; -} - -/* Mailbox IRQ handle functions */ - -static void dbx500_mbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - unsigned long flags; - - spin_lock_irqsave(&prcm_mbox_irqs_lock, flags); - - prcm_mbox_irq_mask |= MBOX_BIT(mbox->id); - - spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags); - -} - -static void dbx500_mbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - unsigned long flags; - - spin_lock_irqsave(&prcm_mbox_irqs_lock, flags); - - prcm_mbox_irq_mask &= ~MBOX_BIT(mbox->id); - - spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags); - -} - -static void dbx500_mbox_ack_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - if (irq == IRQ_RX) - mbox_write_reg(MBOX_BIT(mbox->id), PRCM_ARM_IT1_CLR); -} - -static int dbx500_mbox_is_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv; - - if (irq == IRQ_RX) { - if (mbox_read_reg(PRCM_ARM_IT1_VAL) & MBOX_BIT(mbox->id)) { - priv->empty_flag = true; - return 1; - } else { - return 0; - } - } else { - return 0; - } -} - -/* message management */ - -static int dbx500_mbox_is_ready(struct mailbox *mbox) -{ - return mbox_read_reg(PRCM_MBOX_CPU_VAL) & MBOX_BIT(mbox->id); -} - -static int dbx500_mbox_write(struct mailbox *mbox, - struct mailbox_msg *msg) -{ - int j; - struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv; - - if (msg->size && !msg->pdata) - return -EINVAL; - - while (dbx500_mbox_is_ready(mbox)) - cpu_relax(); - - /* write header */ - if (priv->header_size) - writeb(msg->header, tcdm_mem_base + priv->tx_header_offset); - - /* write data */ - for (j = 0; j < msg->size; j++) - writeb(((unsigned char *)msg->pdata)[j], - tcdm_mem_base + priv->tx_offset + j); - - /* send event */ - mbox_write_reg(MBOX_BIT(mbox->id), PRCM_MBOX_CPU_SET); - - return 0; -} - -static void dbx500_mbox_read(struct mailbox *mbox, struct mailbox_msg *msg) -{ - struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv; - - msg->header = readb(tcdm_mem_base + priv->rx_header_offset); - msg->pdata = (unsigned char *)(tcdm_mem_base + priv->rx_offset); - - msg->size = priv->rx_size; - priv->empty_flag = false; -} - -static int dbx500_mbox_empty(struct mailbox *mbox) -{ - struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv; - if (priv->empty_flag) - return 0; - else - return 1; -} - -static int dbx500_mbox_poll_for_space(struct mailbox *mbox) -{ - return 0; -} -/* interrupt management */ - -/* mask/unmask must be managed by SW */ - -static void mbox_irq_mask(struct irq_data *d) -{ - unsigned long flags; - - spin_lock_irqsave(&prcm_mbox_irqs_lock, flags); - - prcm_mbox_irq_mask &= ~MBOX_BIT(d->hwirq); - - spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags); -} - -static void mbox_irq_unmask(struct irq_data *d) -{ - unsigned long flags; - - spin_lock_irqsave(&prcm_mbox_irqs_lock, flags); - - prcm_mbox_irq_mask |= MBOX_BIT(d->hwirq); - - spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags); -} - -static void mbox_irq_ack(struct irq_data *d) -{ - mbox_write_reg(MBOX_BIT(d->hwirq), PRCM_ARM_IT1_CLR); -} - -static struct irq_chip dbx500_mbox_irq_chip = { - .name = "dbx500_mbox", - .irq_disable = mbox_irq_unmask, - .irq_ack = mbox_irq_ack, - .irq_mask = mbox_irq_mask, - .irq_unmask = mbox_irq_unmask, -}; - -static int dbx500_mbox_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - irq_set_chip_and_handler(irq, &dbx500_mbox_irq_chip, - handle_simple_irq); - set_irq_flags(irq, IRQF_VALID); - - return 0; -} - -static struct irq_domain_ops dbx500_mbox_irq_ops = { - .map = dbx500_mbox_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -static irqreturn_t dbx500_mbox_irq_handler(int irq, void *data) -{ - u32 bits; - u8 n; - - bits = (mbox_read_reg(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); - if (unlikely(!bits)) - return IRQ_NONE; - - bits &= prcm_mbox_irq_mask; - - for (n = 0; bits; n++) { - if (bits & MBOX_BIT(n)) { - bits -= MBOX_BIT(n); - generic_handle_irq( - irq_find_mapping(dbx500_mbox_irq_domain, n)); - } - } - return IRQ_HANDLED; -} - -/* 5 mailboxes AP <--> PRCMU */ -static struct mailbox_ops dbx500_mbox_ops = { - .type = MBOX_SHARED_MEM_TYPE, - .startup = dbx500_mbox_startup, - .enable_irq = dbx500_mbox_enable_irq, - .disable_irq = dbx500_mbox_disable_irq, - .ack_irq = dbx500_mbox_ack_irq, - .is_irq = dbx500_mbox_is_irq, - .read = dbx500_mbox_read, - .write = dbx500_mbox_write, - .empty = dbx500_mbox_empty, - .poll_for_space = dbx500_mbox_poll_for_space, -}; - -struct dbx500_mbox_priv mbox0_priv = { - .access_mode = MAILBOX_ATOMIC, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB0, - .header_size = 1, - .tx_offset = PRCM_REQ_MB0, - .rx_header_offset = PRCM_MBOX_HEADER_ACK_MB0, - .rx_offset = PRCM_ACK_MB0, - .rx_size = PRCM_ACK_MB0_SIZE, -}; - -struct mailbox mbox0_info = { - .name = "mbox0", - .id = 0, - .ops = &dbx500_mbox_ops, - .priv = &mbox0_priv, -}; - -struct dbx500_mbox_priv mbox1_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB1, - .header_size = 1, - .tx_offset = PRCM_REQ_MB1, - .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB1, - .rx_offset = PRCM_ACK_MB1, - .rx_size = PRCM_ACK_MB1_SIZE, -}; - -struct mailbox mbox1_info = { - .name = "mbox1", - .id = 1, - .ops = &dbx500_mbox_ops, - .priv = &mbox1_priv, -}; - -struct dbx500_mbox_priv mbox2_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB2, - .header_size = 1, - .tx_offset = PRCM_REQ_MB2, - .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB2, - .rx_offset = PRCM_ACK_MB2, - .rx_size = PRCM_ACK_MB2_SIZE, -}; - -struct mailbox mbox2_info = { - .name = "mbox2", - .id = 2, - .ops = &dbx500_mbox_ops, - .priv = &mbox2_priv, -}; - -struct dbx500_mbox_priv mbox3_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB3, - .header_size = 1, - .tx_offset = PRCM_REQ_MB3, - .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB3, - .rx_offset = PRCM_ACK_MB3, - .rx_size = PRCM_ACK_MB3_SIZE, -}; - -struct mailbox mbox3_info = { - .name = "mbox3", - .id = 3, - .ops = &dbx500_mbox_ops, - .priv = &mbox3_priv, -}; - -struct dbx500_mbox_priv mbox4_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB4, - .header_size = 1, - .tx_offset = PRCM_REQ_MB4, - .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB4, - .rx_offset = PRCM_ACK_MB4, - .rx_size = PRCM_ACK_MB4_SIZE, -}; - -struct mailbox mbox4_info = { - .name = "mbox4", - .id = 4, - .ops = &dbx500_mbox_ops, - .priv = &mbox4_priv, -}; - -struct dbx500_mbox_priv mbox5_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_LEGACY, - .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB5, - .header_size = 1, - .tx_offset = PRCM_REQ_MB5, - .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB5, - .rx_offset = PRCM_ACK_MB5, - .rx_size = PRCM_ACK_MB5_SIZE, -}; - -struct mailbox mbox5_info = { - .name = "mbox5", - .id = 5, - .ops = &dbx500_mbox_ops, - .priv = &mbox5_priv, -}; - -struct mailbox mbox6_info = { - .name = "mbox6", - .id = 6, - .ops = &dbx500_mbox_ops, -}; - -struct mailbox mbox7_info = { - .name = "mbox7", - .id = 7, - .ops = &dbx500_mbox_ops, -}; - -/* x540 mailbox definition */ -struct dbx500_mbox_priv mbox1_upap_priv = { - .access_mode = MAILBOX_BLOCKING, - .type = MAILBOX_UPAP, - .tx_header_offset = 0, - .header_size = 0, - .tx_offset = 0, - .rx_offset = 0, /* TODO to be replaced by dynamic detection */ - .rx_size = 0x40, -}; - -struct mailbox mbox1_upap_info = { - .name = "mbox1_upap", - .id = 1, - .ops = &dbx500_mbox_ops, - .priv = &mbox1_upap_priv, -}; - -struct mailbox *db8500_mboxes[] = { &mbox0_info, &mbox1_info, &mbox2_info, - &mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info, - NULL }; - -struct mailbox *dbx540_mboxes[] = { &mbox0_info, &mbox2_info, - &mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info, - &mbox1_upap_info, NULL }; - -static const struct of_device_id dbx500_mailbox_match[] = { - { .compatible = "stericsson,db8500-mailbox", - .data = (void *)db8500_mboxes, - }, - { .compatible = "stericsson,db9540-mailbox", - .data = (void *)dbx540_mboxes, - }, - { /* sentinel */} -}; - -static int dbx500_mbox_probe(struct platform_device *pdev) -{ - const struct platform_device_id *platid = platform_get_device_id(pdev); - struct resource *mem; - int ret, i, irq; - u32 legacy_offset = 0; - u32 upap_offset = 0, upap_size = PRCM_MBOX_LEGACY_SIZE; - struct mailbox **list; - struct dbx500_plat_data *pdata = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; - bool upap_used = false; - - if (!pdata) { - if (np) { - if (of_property_read_u32(np, "legacy-offset", - &legacy_offset)) { - /* missing legacy-offset */ - dev_err(&pdev->dev, "No legacy offset found\n"); - return -ENODEV; - } - if (of_property_read_u32(np, "upap-offset", - &upap_offset)) { - dev_dbg(&pdev->dev, "No upap offset found\n"); - upap_offset = -1; - } - list = (struct mailbox **)of_match_device( - dbx500_mailbox_match, &pdev->dev)->data; - if (!list) { - /* No mailbox configuration */ - dev_err(&pdev->dev, "No configuration found\n"); - return -ENODEV; - } - } else { - /* No mailbox configuration */ - dev_err(&pdev->dev, "No configuration found\n"); - return -ENODEV; - } - } else { - list = (struct mailbox **)platid->driver_data; - legacy_offset = pdata->legacy_offset; - upap_offset = pdata->upap_offset; - } - - mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcm-reg"); - mbox_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (!mbox_base) { - ret = -ENOMEM; - goto out; - } - - mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); - tcdm_mem_base = devm_ioremap(&pdev->dev, mem->start, - resource_size(mem)); - if (!tcdm_mem_base) { - ret = -ENOMEM; - goto out; - } - - /* check mailbox offset values */ - if (legacy_offset >= (resource_size(mem) - PRCM_MBOX_LEGACY_SIZE)) { - dev_err(&pdev->dev, "Incorrect legacy offset value\n"); - ret = -EINVAL; - goto out; - } - - for (i = 0; list[i]; i++) { - struct mailbox *mbox = list[i]; - struct dbx500_mbox_priv *priv = - (struct dbx500_mbox_priv *)mbox->priv; - if (!priv) - continue; - if (priv->type == MAILBOX_UPAP) { - upap_used = true; - upap_size += priv->rx_size; - break; - } - } - - if (upap_used && (upap_offset >= (resource_size(mem) - upap_size))) { - dev_err(&pdev->dev, "Incorrect upap offset value\n"); - ret = -EINVAL; - goto out; - } - - irq = platform_get_irq(pdev, 0); - /* clean all mailboxes */ - mbox_write_reg(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); - ret = request_irq(irq, dbx500_mbox_irq_handler, - IRQF_NO_SUSPEND, "db8500_mbox", NULL); - if (ret) { - ret = -EINVAL; - goto out; - } - - dbx500_mbox_irq_domain = irq_domain_add_linear( - np, NUM_MB, &dbx500_mbox_irq_ops, NULL); - - if (!dbx500_mbox_irq_domain) { - dev_err(&pdev->dev, "Failed to create irqdomain\n"); - ret = -ENOSYS; - goto irq_free; - } - - /* - * Update mailbox shared memory buffer offset according to mailbox - * type - */ - for (i = 0; list[i]; i++) { - struct mailbox *mbox = list[i]; - struct dbx500_mbox_priv *priv = - (struct dbx500_mbox_priv *)mbox->priv; - if (!priv) - continue; - mbox->irq = irq_create_mapping(dbx500_mbox_irq_domain, - mbox->id); - if (priv->type == MAILBOX_LEGACY) { - priv->rx_offset += legacy_offset; - priv->rx_header_offset += legacy_offset; - priv->tx_offset += legacy_offset; - priv->tx_header_offset += legacy_offset; - } else if (priv->type == MAILBOX_UPAP) { - priv->tx_offset += upap_offset; - priv->rx_offset += upap_offset; - } - } - - ret = mailbox_register(&pdev->dev, list); -irq_free: - if (ret) - free_irq(irq, NULL); - -out: - return ret; -} - -static int dbx500_mbox_remove(struct platform_device *pdev) -{ - mailbox_unregister(); - iounmap(mbox_base); - return 0; -} - -static const struct platform_device_id dbx500_mbox_id[] = { - { - .name = "db8500-mailbox", - .driver_data = (unsigned long) db8500_mboxes, - }, { - .name = "db9540-mailbox", - .driver_data = (unsigned long) dbx540_mboxes, - }, { - /* sentinel */ - } -}; - -static struct platform_driver dbx500_mbox_driver = { - .probe = dbx500_mbox_probe, - .remove = dbx500_mbox_remove, - .driver = { - .name = "dbx500-mailbox", - .of_match_table = dbx500_mailbox_match, - }, - .id_table = dbx500_mbox_id, -}; - -static int __init dbx500_mbox_init(void) -{ - return platform_driver_register(&dbx500_mbox_driver); -} - -static void __exit dbx500_mbox_exit(void) -{ - platform_driver_unregister(&dbx500_mbox_driver); -} - -postcore_initcall(dbx500_mbox_init); -module_exit(dbx500_mbox_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("ST-Ericsson mailbox: dbx500 architecture specific functions"); -MODULE_AUTHOR("Loic Pallardy "); -MODULE_ALIAS("platform:dbx500-mailbox"); diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c deleted file mode 100644 index 78e52c064270..000000000000 --- a/drivers/mailbox/mailbox.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Mailbox framework - * - * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. - * - * Contact: Hiroshi DOYU - * Author: Loic Pallardy for ST-Ericsson - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mailbox_internal.h" - -static struct mailbox **mboxes; - -static int mbox_configured; -static DEFINE_MUTEX(mbox_configured_lock); - -static unsigned int mbox_kfifo_size = CONFIG_MBOX_KFIFO_SIZE; -module_param(mbox_kfifo_size, uint, S_IRUGO); -MODULE_PARM_DESC(mbox_kfifo_size, "Size of mailbox kfifo (bytes)"); - -/* Mailbox FIFO handle functions */ -static inline void mbox_read(struct mailbox *mbox, struct mailbox_msg *msg) -{ - mbox->ops->read(mbox, msg); -} -static inline int mbox_write(struct mailbox *mbox, struct mailbox_msg *msg) -{ - return mbox->ops->write(mbox, msg); -} -static inline int mbox_empty(struct mailbox *mbox) -{ - return mbox->ops->empty(mbox); -} - -/* Mailbox IRQ handle functions */ -static inline void ack_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - if (mbox->ops->ack_irq) - mbox->ops->ack_irq(mbox, irq); -} -static inline int is_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - return mbox->ops->is_irq(mbox, irq); -} - -/* - * message sender - */ -static int __mbox_poll_for_space(struct mailbox *mbox) -{ - return mbox->ops->poll_for_space(mbox); -} - -int mailbox_msg_send(struct mailbox *mbox, struct mailbox_msg *msg) -{ - struct mailbox_queue *mq = mbox->txq; - int ret = 0, len; - - mutex_lock(&mq->mlock); - - if (kfifo_avail(&mq->fifo) < (sizeof(*msg) + msg->size)) { - ret = -ENOMEM; - goto out; - } - - if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) { - ret = mbox_write(mbox, msg); - goto out; - } - - len = kfifo_in(&mq->fifo, (unsigned char *)msg, sizeof(*msg)); - WARN_ON(len != sizeof(*msg)); - - if (msg->size && msg->pdata) { - len = kfifo_in(&mq->fifo, (unsigned char *)msg->pdata, - msg->size); - WARN_ON(len != msg->size); - } - - tasklet_schedule(&mbox->txq->tasklet); - -out: - mutex_unlock(&mq->mlock); - return ret; -} -EXPORT_SYMBOL(mailbox_msg_send); - -#define TRANSFER_TIMEOUT 30000 /* Becomes ~3s timeout */ - -static struct mailbox_msg no_irq_msg_res; - -struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *mbox, - struct mailbox_msg *msg) -{ - int ret = 0; - int count = 0; - - BUG_ON(!irqs_disabled()); - - if (likely(mbox->ops->write && mbox->ops->read)) { - if (__mbox_poll_for_space(mbox)) { - ret = -EBUSY; - goto out; - } - mbox->ops->write(mbox, msg); - while (!is_mbox_irq(mbox, IRQ_RX)) { - udelay(100); - cpu_relax(); - count++; - if (count > TRANSFER_TIMEOUT) { - pr_err("%s: Error: transfer timed out\n", - __func__); - ret = -EINVAL; - goto out; - } - } - mbox->ops->read(mbox, &no_irq_msg_res); - ack_mbox_irq(mbox, IRQ_RX); - } else { - ret = -EINVAL; - } - -out: - BUG_ON(ret < 0); - - return &no_irq_msg_res; -} -EXPORT_SYMBOL(mailbox_msg_send_receive_no_irq); - -int mailbox_msg_send_no_irq(struct mailbox *mbox, - struct mailbox_msg *msg) -{ - int ret = 0; - - BUG_ON(!irqs_disabled()); - - if (likely(mbox->ops->write)) { - if (__mbox_poll_for_space(mbox)) { - ret = -EBUSY; - goto out; - } - mbox->ops->write(mbox, msg); - } else { - ret = -EINVAL; - } - -out: - WARN_ON(ret < 0); - - return ret; -} -EXPORT_SYMBOL(mailbox_msg_send_no_irq); - -void mailbox_save_ctx(struct mailbox *mbox) -{ - if (!mbox->ops->save_ctx) { - dev_err(mbox->dev, "%s:\tno save\n", __func__); - return; - } - - mbox->ops->save_ctx(mbox); -} -EXPORT_SYMBOL(mailbox_save_ctx); - -void mailbox_restore_ctx(struct mailbox *mbox) -{ - if (!mbox->ops->restore_ctx) { - dev_err(mbox->dev, "%s:\tno restore\n", __func__); - return; - } - - mbox->ops->restore_ctx(mbox); -} -EXPORT_SYMBOL(mailbox_restore_ctx); - -void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - mbox->ops->enable_irq(mbox, irq); -} -EXPORT_SYMBOL(mailbox_enable_irq); - -void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq) -{ - mbox->ops->disable_irq(mbox, irq); -} -EXPORT_SYMBOL(mailbox_disable_irq); - -static void mbox_tx_tasklet(unsigned long tx_data) -{ - struct mailbox *mbox = (struct mailbox *)tx_data; - struct mailbox_queue *mq = mbox->txq; - struct mailbox_msg msg; - int ret; - unsigned char tx_data_buf[CONFIG_MBOX_DATA_SIZE]; - - while (kfifo_len(&mq->fifo)) { - if (__mbox_poll_for_space(mbox)) { - mailbox_enable_irq(mbox, IRQ_TX); - break; - } - - ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); - WARN_ON(ret != sizeof(msg)); - - if (msg.size) { - ret = kfifo_out(&mq->fifo, tx_data_buf, - sizeof(msg.size)); - WARN_ON(ret != msg.size); - msg.pdata = tx_data_buf; - } - - ret = mbox_write(mbox, &msg); - WARN_ON(ret); - } -} - -/* - * Message receiver(workqueue) - */ -static unsigned char rx_work_data[CONFIG_MBOX_DATA_SIZE]; - -static void mbox_rx_work(struct work_struct *work) -{ - struct mailbox_queue *mq = - container_of(work, struct mailbox_queue, work); - int len; - struct mailbox *mbox = mq->mbox; - struct mailbox_msg msg; - - while (kfifo_len(&mq->fifo) >= sizeof(msg)) { - len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); - WARN_ON(len != sizeof(msg)); - - if (msg.size) { - len = kfifo_out(&mq->fifo, rx_work_data, msg.size); - WARN_ON(len != msg.size); - msg.pdata = rx_work_data; - } - - blocking_notifier_call_chain(&mbox->notifier, len, - (void *)&msg); - spin_lock_irq(&mq->lock); - if (mq->full) { - mq->full = false; - mailbox_enable_irq(mbox, IRQ_RX); - } - spin_unlock_irq(&mq->lock); - } -} - -/* - * Mailbox interrupt handler - */ -static void __mbox_tx_interrupt(struct mailbox *mbox) -{ - mailbox_disable_irq(mbox, IRQ_TX); - ack_mbox_irq(mbox, IRQ_TX); - tasklet_schedule(&mbox->txq->tasklet); -} - -static void __mbox_rx_interrupt(struct mailbox *mbox) -{ - struct mailbox_queue *mq = mbox->rxq; - struct mailbox_msg msg; - int len; - - while (!mbox_empty(mbox)) { - if (unlikely(kfifo_avail(&mq->fifo) < - (sizeof(msg) + CONFIG_MBOX_DATA_SIZE))) { - mailbox_disable_irq(mbox, IRQ_RX); - mq->full = true; - goto nomem; - } - - mbox_read(mbox, &msg); - - len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); - WARN_ON(len != sizeof(msg)); - - if (msg.pdata && msg.size) { - len = kfifo_in(&mq->fifo, (unsigned char *)msg.pdata, - msg.size); - WARN_ON(len != msg.size); - } - } - - /* no more messages in the fifo. clear IRQ source. */ - ack_mbox_irq(mbox, IRQ_RX); -nomem: - schedule_work(&mbox->rxq->work); -} - -static irqreturn_t mbox_interrupt(int irq, void *p) -{ - struct mailbox *mbox = p; - - if (is_mbox_irq(mbox, IRQ_TX)) - __mbox_tx_interrupt(mbox); - - if (is_mbox_irq(mbox, IRQ_RX)) - __mbox_rx_interrupt(mbox); - - return IRQ_HANDLED; -} - -static struct mailbox_queue *mbox_queue_alloc(struct mailbox *mbox, - void (*work) (struct work_struct *), - void (*tasklet)(unsigned long)) -{ - struct mailbox_queue *mq; - - mq = kzalloc(sizeof(struct mailbox_queue), GFP_KERNEL); - if (!mq) - return NULL; - - spin_lock_init(&mq->lock); - mutex_init(&mq->mlock); - - if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) - goto error; - - if (work) - INIT_WORK(&mq->work, work); - - if (tasklet) - tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox); - return mq; -error: - kfree(mq); - return NULL; -} - -static void mbox_queue_free(struct mailbox_queue *q) -{ - kfifo_free(&q->fifo); - kfree(q); -} - -static int mailbox_startup(struct mailbox *mbox) -{ - int ret = 0; - struct mailbox_queue *mq; - - mutex_lock(&mbox_configured_lock); - if (!mbox_configured++) { - if (likely(mbox->ops->startup)) { - ret = mbox->ops->startup(mbox); - if (unlikely(ret)) - goto fail_startup; - } else - goto fail_startup; - } - - if (!mbox->use_count++) { - mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_txq; - } - mbox->txq = mq; - - mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_rxq; - } - mbox->rxq = mq; - mq->mbox = mbox; - ret = request_irq(mbox->irq, mbox_interrupt, - IRQF_SHARED | IRQF_NO_SUSPEND, - mbox->name, mbox); - if (unlikely(ret)) { - pr_err("failed to register mailbox interrupt:%d\n", - ret); - goto fail_request_irq; - } - - mailbox_enable_irq(mbox, IRQ_RX); - } - mutex_unlock(&mbox_configured_lock); - return 0; - -fail_request_irq: - mbox_queue_free(mbox->rxq); -fail_alloc_rxq: - mbox_queue_free(mbox->txq); -fail_alloc_txq: - if (mbox->ops->shutdown) - mbox->ops->shutdown(mbox); - mbox->use_count--; -fail_startup: - mbox_configured--; - mutex_unlock(&mbox_configured_lock); - return ret; -} - -static void mailbox_fini(struct mailbox *mbox) -{ - mutex_lock(&mbox_configured_lock); - - if (!--mbox->use_count) { - mailbox_disable_irq(mbox, IRQ_RX); - free_irq(mbox->irq, mbox); - tasklet_kill(&mbox->txq->tasklet); - flush_work(&mbox->rxq->work); - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); - } - - if (likely(mbox->ops->shutdown)) { - if (!--mbox_configured) - mbox->ops->shutdown(mbox); - } - - mutex_unlock(&mbox_configured_lock); -} - -struct mailbox *mailbox_get(const char *name, struct notifier_block *nb) -{ - struct mailbox *_mbox, *mbox = NULL; - int i, ret; - - if (!mboxes) - return ERR_PTR(-EINVAL); - - for (i = 0; (_mbox = mboxes[i]); i++) { - if (!strcmp(_mbox->name, name)) { - mbox = _mbox; - break; - } - } - - if (!mbox) - return ERR_PTR(-ENOENT); - - if (nb) - blocking_notifier_chain_register(&mbox->notifier, nb); - - ret = mailbox_startup(mbox); - if (ret) { - blocking_notifier_chain_unregister(&mbox->notifier, nb); - return ERR_PTR(-ENODEV); - } - - return mbox; -} -EXPORT_SYMBOL(mailbox_get); - -void mailbox_put(struct mailbox *mbox, struct notifier_block *nb) -{ - if (nb) - blocking_notifier_chain_unregister(&mbox->notifier, nb); - mailbox_fini(mbox); -} -EXPORT_SYMBOL(mailbox_put); - -static struct class mailbox_class = { .name = "mbox", }; - -int mailbox_register(struct device *parent, struct mailbox **list) -{ - int ret; - int i; - - mboxes = list; - if (!mboxes) - return -EINVAL; - - for (i = 0; mboxes[i]; i++) { - struct mailbox *mbox = mboxes[i]; - mbox->dev = device_create(&mailbox_class, - parent, 0, mbox, "%s", mbox->name); - if (IS_ERR(mbox->dev)) { - ret = PTR_ERR(mbox->dev); - goto err_out; - } - - BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); - } - return 0; - -err_out: - while (i--) - device_unregister(mboxes[i]->dev); - return ret; -} -EXPORT_SYMBOL(mailbox_register); - -int mailbox_unregister(void) -{ - int i; - - if (!mboxes) - return -EINVAL; - - for (i = 0; mboxes[i]; i++) - device_unregister(mboxes[i]->dev); - mboxes = NULL; - return 0; -} -EXPORT_SYMBOL(mailbox_unregister); - -static int __init mailbox_init(void) -{ - int err; - - err = class_register(&mailbox_class); - if (err) - return err; - - /* kfifo size sanity check: alignment and minimal size */ - mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(struct mailbox_msg)); - mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, - sizeof(struct mailbox_msg) + CONFIG_MBOX_DATA_SIZE); - return 0; -} -subsys_initcall(mailbox_init); - -static void __exit mailbox_exit(void) -{ - class_unregister(&mailbox_class); -} -module_exit(mailbox_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("mailbox framework: interrupt driven messaging"); -MODULE_AUTHOR("Toshihiro Kobayashi"); -MODULE_AUTHOR("Hiroshi DOYU"); diff --git a/drivers/mailbox/mailbox_internal.h b/drivers/mailbox/mailbox_internal.h deleted file mode 100644 index 8aded9584dc0..000000000000 --- a/drivers/mailbox/mailbox_internal.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * mailbox: interprocessor communication module - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef MAILBOX_INTERNAL_H -#define MAILBOX_INTERNAL_H - -#include -#include -#include -#include -#include -#include - -typedef int __bitwise mailbox_type_t; -#define MBOX_HW_FIFO1_TYPE ((__force mailbox_type_t) 1) -#define MBOX_HW_FIFO2_TYPE ((__force mailbox_type_t) 2) -#define MBOX_SHARED_MEM_TYPE ((__force mailbox_type_t) 3) - -struct mailbox_ops { - mailbox_type_t type; - int (*startup)(struct mailbox *mbox); - void (*shutdown)(struct mailbox *mbox); - /* mailbox access */ - void (*read)(struct mailbox *mbox, struct mailbox_msg *msg); - int (*write)(struct mailbox *mbox, struct mailbox_msg *msg); - int (*empty)(struct mailbox *mbox); - int (*poll_for_space)(struct mailbox *mbox); - /* irq */ - void (*enable_irq)(struct mailbox *mbox, mailbox_irq_t irq); - void (*disable_irq)(struct mailbox *mbox, mailbox_irq_t irq); - void (*ack_irq)(struct mailbox *mbox, mailbox_irq_t irq); - int (*is_irq)(struct mailbox *mbox, mailbox_irq_t irq); - /* ctx */ - void (*save_ctx)(struct mailbox *mbox); - void (*restore_ctx)(struct mailbox *mbox); -}; - -struct mailbox_queue { - spinlock_t lock; - struct mutex mlock; - struct kfifo fifo; - struct work_struct work; - struct tasklet_struct tasklet; - struct mailbox *mbox; - bool full; -}; - -struct mailbox { - const char *name; - unsigned int id; - unsigned int irq; - struct mailbox_queue *txq, *rxq; - struct mailbox_ops *ops; - struct device *dev; - void *priv; - int use_count; - struct blocking_notifier_head notifier; -}; - -void mailbox_init_seq(struct mailbox *); - -int mailbox_register(struct device *parent, struct mailbox **); -int mailbox_unregister(void); - -#endif /* MAILBOX_INTERNAL_H */ diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c index f3755e0aa935..d873cbae2fbb 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320-ipc.c @@ -26,7 +26,7 @@ #include #include -#include +#include #define IPCMxSOURCE(m) ((m) * 0x40) #define IPCMxDSET(m) (((m) * 0x40) + 0x004) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index ce1743d0b679..d4d377c40ec9 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -14,9 +14,8 @@ config OMAP_REMOTEPROC depends on HAS_DMA depends on ARCH_OMAP4 || SOC_OMAP5 depends on OMAP_IOMMU + depends on OMAP_MBOX_FWK select REMOTEPROC - select MAILBOX - select OMAP2PLUS_MBOX select RPMSG help Say y here to support OMAP's remote processors (dual M3 diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index b90beef04083..0e396c155b3b 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -27,8 +27,8 @@ #include #include #include -#include +#include #include #include "omap_remoteproc.h" @@ -41,7 +41,7 @@ * @rproc: rproc handle */ struct omap_rproc { - struct mailbox *mbox; + struct omap_mbox *mbox; struct notifier_block nb; struct rproc *rproc; }; @@ -64,15 +64,14 @@ struct omap_rproc { static int omap_rproc_mbox_callback(struct notifier_block *this, unsigned long index, void *data) { + mbox_msg_t msg = (mbox_msg_t) data; struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); struct device *dev = oproc->rproc->dev.parent; - struct mailbox_msg *msg = data; const char *name = oproc->rproc->name; - u32 msg_data = (u32)msg->pdata; - dev_dbg(dev, "mbox msg: 0x%x\n", msg_data); + dev_dbg(dev, "mbox msg: 0x%x\n", msg); - switch (msg_data) { + switch (msg) { case RP_MBOX_CRASH: /* just log this for now. later, we'll also do recovery */ dev_err(dev, "omap rproc %s crashed\n", name); @@ -82,9 +81,8 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, break; default: /* msg contains the index of the triggered vring */ - if (rproc_vq_interrupt(oproc->rproc, msg_data) == IRQ_NONE) - dev_dbg(dev, "no message was found in vqid %d\n", - msg_data); + if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) + dev_dbg(dev, "no message was found in vqid %d\n", msg); } return NOTIFY_DONE; @@ -95,14 +93,12 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) { struct omap_rproc *oproc = rproc->priv; struct device *dev = rproc->dev.parent; - struct mailbox_msg msg; int ret; /* send the index of the triggered virtqueue in the mailbox payload */ - MAILBOX_FILL_MSG(msg, 0, vqid, 0); - ret = mailbox_msg_send(oproc->mbox, &msg); + ret = omap_mbox_msg_send(oproc->mbox, vqid); if (ret) - dev_err(dev, "mailbox_msg_send failed: %d\n", ret); + dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret); } /* @@ -118,7 +114,6 @@ static int omap_rproc_start(struct rproc *rproc) struct device *dev = rproc->dev.parent; struct platform_device *pdev = to_platform_device(dev); struct omap_rproc_pdata *pdata = pdev->dev.platform_data; - struct mailbox_msg msg; int ret; if (pdata->set_bootaddr) @@ -127,10 +122,10 @@ static int omap_rproc_start(struct rproc *rproc) oproc->nb.notifier_call = omap_rproc_mbox_callback; /* every omap rproc is assigned a mailbox instance for messaging */ - oproc->mbox = mailbox_get(pdata->mbox_name, &oproc->nb); + oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); if (IS_ERR(oproc->mbox)) { ret = PTR_ERR(oproc->mbox); - dev_err(dev, "mailbox_get failed: %d\n", ret); + dev_err(dev, "omap_mbox_get failed: %d\n", ret); return ret; } @@ -141,10 +136,9 @@ static int omap_rproc_start(struct rproc *rproc) * Note that the reply will _not_ arrive immediately: this message * will wait in the mailbox fifo until the remote processor is booted. */ - MAILBOX_FILL_MSG(msg, 0, RP_MBOX_ECHO_REQUEST, 0); - ret = mailbox_msg_send(oproc->mbox, &msg); + ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); if (ret) { - dev_err(dev, "mailbox_get failed: %d\n", ret); + dev_err(dev, "omap_mbox_get failed: %d\n", ret); goto put_mbox; } @@ -157,7 +151,7 @@ static int omap_rproc_start(struct rproc *rproc) return 0; put_mbox: - mailbox_put(oproc->mbox, &oproc->nb); + omap_mbox_put(oproc->mbox, &oproc->nb); return ret; } @@ -174,7 +168,7 @@ static int omap_rproc_stop(struct rproc *rproc) if (ret) return ret; - mailbox_put(oproc->mbox, &oproc->nb); + omap_mbox_put(oproc->mbox, &oproc->nb); return 0; } diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig index 165b918b8171..60848f198b48 100644 --- a/drivers/staging/tidspbridge/Kconfig +++ b/drivers/staging/tidspbridge/Kconfig @@ -5,8 +5,7 @@ menuconfig TIDSPBRIDGE tristate "DSP Bridge driver" depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM - select MAILBOX - select OMAP2PLUS_MBOX + select OMAP_MBOX_FWK help DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more attached DSPs. The GPP is considered the master or diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h index f71a89de1882..b783bfa59b1c 100644 --- a/drivers/staging/tidspbridge/core/_tiomap.h +++ b/drivers/staging/tidspbridge/core/_tiomap.h @@ -338,7 +338,7 @@ struct bridge_dev_context { u32 dsp_start_add; /* API Boot vector */ u32 internal_size; /* Internal memory size */ - struct mailbox *mbox; /* Mail box handle */ + struct omap_mbox *mbox; /* Mail box handle */ struct cfg_hostres *resources; /* Host Resources */ diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c index 1cae172df02e..16fa3462fbbe 100644 --- a/drivers/staging/tidspbridge/core/chnl_sm.c +++ b/drivers/staging/tidspbridge/core/chnl_sm.c @@ -155,7 +155,7 @@ func_cont: * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */ chnl_mgr_obj = pchnl->chnl_mgr_obj; spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock); - mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX); + omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX); if (pchnl->chnl_type == CHNL_PCPY) { /* This is a processor-copy channel. */ if (CHNL_IS_OUTPUT(pchnl->chnl_mode)) { @@ -210,7 +210,7 @@ func_cont: IO_OUTPUT), &mb_val); sched_dpc = true; out: - mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX); + omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX); spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock); if (mb_val != 0) sm_interrupt_dsp(dev_ctxt, mb_val); @@ -570,7 +570,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout, } /* See comment in AddIOReq */ spin_lock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock); - mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX); + omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX); if (dequeue_ioc) { /* Dequeue IOC and set chan_ioc; */ chnl_packet_obj = list_first_entry(&pchnl->io_completions, @@ -616,7 +616,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout, /* else, if list is empty, ensure event is reset. */ sync_reset_event(pchnl->sync_event); } - mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX); + omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX); spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock); if (dequeue_ioc && (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)) { diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index 495ef98d548c..e322fb7aebe1 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -908,11 +908,10 @@ func_end: * Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then * schedules a DPC to dispatch I/O. */ -int io_mbox_msg(struct notifier_block *self, unsigned long len, void *data) +int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg) { struct io_mgr *pio_mgr; struct dev_object *dev_obj; - u32 msg = (u32)((struct mailbox_msg *)data)->pdata; unsigned long flags; dev_obj = dev_get_first(); @@ -921,7 +920,7 @@ int io_mbox_msg(struct notifier_block *self, unsigned long len, void *data) if (!pio_mgr) return NOTIFY_BAD; - pio_mgr->intr_val = (u16)(msg); + pio_mgr->intr_val = (u16)((u32)msg); if (pio_mgr->intr_val & MBX_PM_CLASS) io_dispatch_pm(pio_mgr); diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index c637299970c7..b770b2281ce8 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -542,7 +542,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, * Enable Mailbox events and also drain any pending * stale messages. */ - dev_context->mbox = mailbox_get("dsp", &dsp_mbox_notifier); + dev_context->mbox = omap_mbox_get("dsp", &dsp_mbox_notifier); if (IS_ERR(dev_context->mbox)) { dev_context->mbox = NULL; pr_err("%s: Failed to get dsp mailbox handle\n", @@ -677,8 +677,8 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt) } /* Disable the mailbox interrupts */ if (dev_context->mbox) { - mailbox_disable_irq(dev_context->mbox, IRQ_RX); - mailbox_put(dev_context->mbox, &dsp_mbox_notifier); + omap_mbox_disable_irq(dev_context->mbox, IRQ_RX); + omap_mbox_put(dev_context->mbox, &dsp_mbox_notifier); dev_context->mbox = NULL; } /* Reset IVA2 clocks*/ diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c index e50f404ccac1..dafa6d9b2948 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c +++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c @@ -108,7 +108,7 @@ int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context) } else { /* Save mailbox settings */ - mailbox_save_ctx(dev_context->mbox); + omap_mbox_save_ctx(dev_context->mbox); /* Turn off DSP Peripheral clocks and DSP Load monitor timer */ status = dsp_clock_disable_all(dev_context->dsp_per_clks); @@ -165,7 +165,7 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd, switch (dev_context->brd_state) { case BRD_RUNNING: - mailbox_save_ctx(dev_context->mbox); + omap_mbox_save_ctx(dev_context->mbox); if (dsp_test_sleepstate == PWRDM_POWER_OFF) { sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE); dev_dbg(bridge, "PM: %s - sent hibernate cmd to DSP\n", @@ -177,7 +177,7 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd, } break; case BRD_RETENTION: - mailbox_save_ctx(dev_context->mbox); + omap_mbox_save_ctx(dev_context->mbox); if (dsp_test_sleepstate == PWRDM_POWER_OFF) { sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE); target_pwr_state = PWRDM_POWER_OFF; diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c index 5bd57dd2e15f..f53ed98d18c1 100644 --- a/drivers/staging/tidspbridge/core/tiomap_io.c +++ b/drivers/staging/tidspbridge/core/tiomap_io.c @@ -374,7 +374,6 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val) struct omap_dsp_platform_data *pdata = omap_dspbridge_dev->dev.platform_data; struct cfg_hostres *resources = dev_context->resources; - struct mailbox_msg msg; int status = 0; u32 temp; @@ -417,7 +416,7 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val) OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL); /* Restore mailbox settings */ - mailbox_restore_ctx(dev_context->mbox); + omap_mbox_restore_ctx(dev_context->mbox); /* Access MMU SYS CONFIG register to generate a short wakeup */ temp = readl(resources->dmmu_base + 0x10); @@ -428,12 +427,10 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val) dsp_clock_enable_all(dev_context->dsp_per_clks); } - temp = mb_val; - MAILBOX_FILL_MSG(msg, 0, temp, 0); - status = mailbox_msg_send(dev_context->mbox, &msg); + status = omap_mbox_msg_send(dev_context->mbox, mb_val); if (status) { - pr_err("mailbox_msg_send Fail and status = %d\n", status); + pr_err("omap_mbox_msg_send Fail and status = %d\n", status); status = -EPERM; } diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h index 27f6bd6114bc..7f3a1db31619 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h +++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/linux/mailbox.h b/include/linux/mailbox.h index a41b67d78431..5161f63ec1c8 100644 --- a/include/linux/mailbox.h +++ b/include/linux/mailbox.h @@ -1,43 +1,17 @@ /* - * mailbox: interprocessor communication module + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ -#ifndef MAILBOX_H -#define MAILBOX_H - -struct mailbox; - -typedef int __bitwise mailbox_irq_t; -#define IRQ_TX ((__force mailbox_irq_t) 1) -#define IRQ_RX ((__force mailbox_irq_t) 2) - -struct mailbox_msg { - int size; - u32 header; - void *pdata; -}; - -#define MAILBOX_FILL_MSG(_msg, _header, _pdata, _size) { \ - _msg.header = _header; \ - _msg.pdata = (void *)_pdata; \ - _msg.size = _size; \ -} - -int mailbox_msg_send(struct mailbox *, struct mailbox_msg *msg); -struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *, - struct mailbox_msg *msg); -int mailbox_msg_send_no_irq(struct mailbox *, struct mailbox_msg *msg); - -struct mailbox *mailbox_get(const char *, struct notifier_block *nb); -void mailbox_put(struct mailbox *mbox, struct notifier_block *nb); - -void mailbox_save_ctx(struct mailbox *mbox); -void mailbox_restore_ctx(struct mailbox *mbox); -void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq); -void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq); - -#endif /* MAILBOX_H */ +int pl320_ipc_transmit(u32 *data); +int pl320_ipc_register_notifier(struct notifier_block *nb); +int pl320_ipc_unregister_notifier(struct notifier_block *nb); diff --git a/include/linux/pl320-ipc.h b/include/linux/pl320-ipc.h deleted file mode 100644 index 5161f63ec1c8..000000000000 --- a/include/linux/pl320-ipc.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -int pl320_ipc_transmit(u32 *data); -int pl320_ipc_register_notifier(struct notifier_block *nb); -int pl320_ipc_unregister_notifier(struct notifier_block *nb); diff --git a/include/linux/platform_data/mailbox-dbx500.h b/include/linux/platform_data/mailbox-dbx500.h deleted file mode 100644 index d5aebd952447..000000000000 --- a/include/linux/platform_data/mailbox-dbx500.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * mailbox-dbx500.h - * - * Copyright (C) ST-Ericsson SA 2012 - * Author: for ST-Ericsson. - * License terms: GNU General Public License (GPL), version 2 - */ - -struct dbx500_plat_data { - unsigned int legacy_offset; - unsigned int upap_offset; -}; diff --git a/include/linux/platform_data/mailbox-omap.h b/include/linux/platform_data/mailbox-omap.h deleted file mode 100644 index 676cd642bb3f..000000000000 --- a/include/linux/platform_data/mailbox-omap.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * mailbox-omap.h - * - * Copyright (C) 2013 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _PLAT_MAILBOX_H -#define _PLAT_MAILBOX_H - -/* Interrupt register configuration types */ -#define MBOX_INTR_CFG_TYPE1 (0) -#define MBOX_INTR_CFG_TYPE2 (1) - -/** - * struct omap_mbox_dev_info - OMAP mailbox device attribute info - * @name: name of the mailbox device - * @tx_id: mailbox queue id used for transmitting messages - * @rx_id: mailbox queue id on which messages are received - * @irq_id: irq identifier number to use from the hwmod data - * @usr_id: mailbox user id for identifying the interrupt into - * the MPU interrupt controller. - */ -struct omap_mbox_dev_info { - const char *name; - u32 tx_id; - u32 rx_id; - u32 irq_id; - u32 usr_id; -}; - -/** - * struct omap_mbox_pdata - OMAP mailbox platform data - * @intr_type: type of interrupt configuration registers used - while programming mailbox queue interrupts - * @info_cnt: number of mailbox devices for the platform - * @info: array of mailbox device attributes - */ -struct omap_mbox_pdata { - u32 intr_type; - u32 info_cnt; - struct omap_mbox_dev_info *info; -}; - -#endif /* _PLAT_MAILBOX_H */