Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f64a3c89 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'omap-for-v3.17/mailbox-cleanup' of...

Merge tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers

Merge "late omap mailbox clean-up, driver parts" from Tony Lindgren:

Driver specific omap mailbox cleanup. Mostly to remove
broken legacy code for omap1 and move things towards
device tree.

These patches were posted a while back, but I did not
realize I was supposed to merge the driver related
parts too. So apologies for a late pull request on
these changes.

* tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap

:
  mailbox/omap: add a parent structure for every IP instance
  mailbox/omap: remove the private mailbox structure
  mailbox/omap: consolidate OMAP mailbox driver
  mailbox/omap: simplify the fifo assignment by using macros
  mailbox/omap: remove omap_mbox_type_t from mailbox ops
  mailbox/omap: remove OMAP1 mailbox driver
  mailbox/omap: use devm_* interfaces

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 537994aa 72c1c817
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -26,8 +26,6 @@ CONFIG_ARCH_OMAP=y
CONFIG_ARCH_OMAP1=y
CONFIG_ARCH_OMAP1=y
CONFIG_OMAP_RESET_CLOCKS=y
CONFIG_OMAP_RESET_CLOCKS=y
# CONFIG_OMAP_MUX is not set
# CONFIG_OMAP_MUX is not set
CONFIG_MAILBOX=y
CONFIG_OMAP1_MBOX=y
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_DM_TIMER=y
CONFIG_OMAP_DM_TIMER=y
CONFIG_ARCH_OMAP730=y
CONFIG_ARCH_OMAP730=y
+1 −18
Original line number Original line Diff line number Diff line
@@ -16,26 +16,9 @@ config PL320_MBOX
	  Management Engine, primarily for cpufreq. Say Y here if you want
	  Management Engine, primarily for cpufreq. Say Y here if you want
	  to use the PL320 IPCM support.
	  to use the PL320 IPCM support.


config OMAP_MBOX
	tristate
	help
	  This option is selected by any OMAP architecture specific mailbox
	  driver such as CONFIG_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This
	  enables the common OMAP mailbox framework code.

config OMAP1_MBOX
	tristate "OMAP1 Mailbox framework support"
	depends on ARCH_OMAP1
	select OMAP_MBOX
	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
config OMAP2PLUS_MBOX
	tristate "OMAP2+ Mailbox framework support"
	tristate "OMAP2+ Mailbox framework support"
	depends on ARCH_OMAP2PLUS
	depends on ARCH_OMAP2PLUS
	select OMAP_MBOX
	help
	help
	  Mailbox implementation for OMAP family chips with hardware for
	  Mailbox implementation for OMAP family chips with hardware for
	  interprocessor communication involving DSP, IVA1.0 and IVA2 in
	  interprocessor communication involving DSP, IVA1.0 and IVA2 in
@@ -44,7 +27,7 @@ config OMAP2PLUS_MBOX


config OMAP_MBOX_KFIFO_SIZE
config OMAP_MBOX_KFIFO_SIZE
	int "Mailbox kfifo default buffer size (bytes)"
	int "Mailbox kfifo default buffer size (bytes)"
	depends on OMAP2PLUS_MBOX || OMAP1_MBOX
	depends on OMAP2PLUS_MBOX
	default 256
	default 256
	help
	help
	  Specify the default size of mailbox's kfifo buffers (bytes).
	  Specify the default size of mailbox's kfifo buffers (bytes).
+1 −5
Original line number Original line Diff line number Diff line
obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o


obj-$(CONFIG_OMAP_MBOX)		+= omap-mailbox.o
obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
obj-$(CONFIG_OMAP1_MBOX)	+= mailbox_omap1.o
mailbox_omap1-objs		:= mailbox-omap1.o
obj-$(CONFIG_OMAP2PLUS_MBOX)	+= mailbox_omap2.o
mailbox_omap2-objs		:= mailbox-omap2.o

drivers/mailbox/mailbox-omap1.c

deleted100644 → 0
+0 −203
Original line number Original line Diff line number Diff line
/*
 * Mailbox reservation modules for OMAP1
 *
 * Copyright (C) 2006-2009 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.
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>

#include "omap-mbox.h"

#define MAILBOX_ARM2DSP1		0x00
#define MAILBOX_ARM2DSP1b		0x04
#define MAILBOX_DSP2ARM1		0x08
#define MAILBOX_DSP2ARM1b		0x0c
#define MAILBOX_DSP2ARM2		0x10
#define MAILBOX_DSP2ARM2b		0x14
#define MAILBOX_ARM2DSP1_Flag		0x18
#define MAILBOX_DSP2ARM1_Flag		0x1c
#define MAILBOX_DSP2ARM2_Flag		0x20

static void __iomem *mbox_base;

struct omap_mbox1_fifo {
	unsigned long cmd;
	unsigned long data;
	unsigned long flag;
};

struct omap_mbox1_priv {
	struct omap_mbox1_fifo tx_fifo;
	struct omap_mbox1_fifo rx_fifo;
};

static inline int mbox_read_reg(size_t ofs)
{
	return __raw_readw(mbox_base + ofs);
}

static inline void mbox_write_reg(u32 val, size_t ofs)
{
	__raw_writew(val, mbox_base + ofs);
}

/* msg */
static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
{
	struct omap_mbox1_fifo *fifo =
		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
	mbox_msg_t msg;

	msg = mbox_read_reg(fifo->data);
	msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;

	return 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;

	mbox_write_reg(msg & 0xffff, fifo->data);
	mbox_write_reg(msg >> 16, fifo->cmd);
}

static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
{
	return 0;
}

static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
{
	struct omap_mbox1_fifo *fifo =
		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;

	return mbox_read_reg(fifo->flag);
}

/* irq */
static void
omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	if (irq == IRQ_RX)
		enable_irq(mbox->irq);
}

static void
omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	if (irq == IRQ_RX)
		disable_irq(mbox->irq);
}

static int
omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	if (irq == IRQ_TX)
		return 0;
	return 1;
}

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,
};

/* FIXME: the following struct should be created automatically by the user id */

/* DSP */
static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
	.tx_fifo = {
		.cmd	= MAILBOX_ARM2DSP1b,
		.data	= MAILBOX_ARM2DSP1,
		.flag	= MAILBOX_ARM2DSP1_Flag,
	},
	.rx_fifo = {
		.cmd	= MAILBOX_DSP2ARM1b,
		.data	= MAILBOX_DSP2ARM1,
		.flag	= MAILBOX_DSP2ARM1_Flag,
	},
};

static struct omap_mbox mbox_dsp_info = {
	.name	= "dsp",
	.ops	= &omap1_mbox_ops,
	.priv	= &omap1_mbox_dsp_priv,
};

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 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 -ENOENT;

	mbox_base = ioremap(mem->start, resource_size(mem));
	if (!mbox_base)
		return -ENOMEM;

	ret = omap_mbox_register(&pdev->dev, list);
	if (ret) {
		iounmap(mbox_base);
		return ret;
	}

	return 0;
}

static int omap1_mbox_remove(struct platform_device *pdev)
{
	omap_mbox_unregister();
	iounmap(mbox_base);
	return 0;
}

static struct platform_driver omap1_mbox_driver = {
	.probe	= omap1_mbox_probe,
	.remove	= omap1_mbox_remove,
	.driver	= {
		.name	= "omap-mailbox",
	},
};

static int __init omap1_mbox_init(void)
{
	return platform_driver_register(&omap1_mbox_driver);
}

static void __exit omap1_mbox_exit(void)
{
	platform_driver_unregister(&omap1_mbox_driver);
}

module_init(omap1_mbox_init);
module_exit(omap1_mbox_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
MODULE_ALIAS("platform:omap1-mailbox");

drivers/mailbox/mailbox-omap2.c

deleted100644 → 0
+0 −357
Original line number Original line Diff line number Diff line
/*
 * Mailbox reservation modules for OMAP2/3
 *
 * Copyright (C) 2006-2009 Nokia Corporation
 * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 *        and  Paul Mundt
 *
 * 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.
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/platform_data/mailbox-omap.h>

#include "omap-mbox.h"

#define MAILBOX_REVISION		0x000
#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
#define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
#define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))

#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))

#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))

#define MBOX_REG_SIZE			0x120

#define OMAP4_MBOX_REG_SIZE		0x130

#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))

static void __iomem *mbox_base;

struct omap_mbox2_fifo {
	unsigned long msg;
	unsigned long fifo_stat;
	unsigned long msg_stat;
};

struct omap_mbox2_priv {
	struct omap_mbox2_fifo tx_fifo;
	struct omap_mbox2_fifo rx_fifo;
	unsigned long irqenable;
	unsigned long irqstatus;
	u32 newmsg_bit;
	u32 notfull_bit;
	u32 ctx[OMAP4_MBOX_NR_REGS];
	unsigned long irqdisable;
	u32 intr_type;
};

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 int omap2_mbox_startup(struct omap_mbox *mbox)
{
	u32 l;

	pm_runtime_enable(mbox->dev->parent);
	pm_runtime_get_sync(mbox->dev->parent);

	l = mbox_read_reg(MAILBOX_REVISION);
	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));

	return 0;
}

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 mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
	return (mbox_msg_t) mbox_read_reg(fifo->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(msg, fifo->msg);
}

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 omap_mbox *mbox)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
	return mbox_read_reg(fifo->fifo_stat);
}

/* Mailbox IRQ handle functions */
static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	struct omap_mbox2_priv *p = mbox->priv;
	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	l = mbox_read_reg(p->irqenable);
	l |= bit;
	mbox_write_reg(l, p->irqenable);
}

static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	struct omap_mbox2_priv *p = mbox->priv;
	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	/*
	 * Read and update the interrupt configuration register for pre-OMAP4.
	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
	 */
	if (!p->intr_type)
		bit = mbox_read_reg(p->irqdisable) & ~bit;

	mbox_write_reg(bit, p->irqdisable);
}

static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	struct omap_mbox2_priv *p = mbox->priv;
	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	mbox_write_reg(bit, p->irqstatus);

	/* Flush posted write for irq status to avoid spurious interrupts */
	mbox_read_reg(p->irqstatus);
}

static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
	struct omap_mbox2_priv *p = mbox->priv;
	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
	u32 enable = mbox_read_reg(p->irqenable);
	u32 status = mbox_read_reg(p->irqstatus);

	return (int)(enable & status & bit);
}

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)
		nr_regs = OMAP4_MBOX_NR_REGS;
	else
		nr_regs = MBOX_NR_REGS;
	for (i = 0; i < nr_regs; i++) {
		p->ctx[i] = mbox_read_reg(i * sizeof(u32));

		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
			i, p->ctx[i]);
	}
}

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)
		nr_regs = OMAP4_MBOX_NR_REGS;
	else
		nr_regs = MBOX_NR_REGS;
	for (i = 0; i < nr_regs; i++) {
		mbox_write_reg(p->ctx[i], i * sizeof(u32));

		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
			i, p->ctx[i]);
	}
}

static struct omap_mbox_ops omap2_mbox_ops = {
	.type		= OMAP_MBOX_TYPE2,
	.startup	= omap2_mbox_startup,
	.shutdown	= omap2_mbox_shutdown,
	.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,
	.is_irq		= omap2_mbox_is_irq,
	.save_ctx	= omap2_mbox_save_ctx,
	.restore_ctx	= omap2_mbox_restore_ctx,
};

static int omap2_mbox_probe(struct platform_device *pdev)
{
	struct resource *mem;
	int ret;
	struct omap_mbox **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;

	if (!pdata || !pdata->info_cnt || !pdata->info) {
		pr_err("%s: platform not supported\n", __func__);
		return -ENODEV;
	}

	/* allocate one extra for marking end of list */
	list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
	if (!list)
		return -ENOMEM;

	mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
	if (!mboxblk) {
		ret = -ENOMEM;
		goto free_list;
	}

	privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
	if (!privblk) {
		ret = -ENOMEM;
		goto free_mboxblk;
	}

	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);
		if (mbox->irq < 0) {
			ret = mbox->irq;
			goto free_privblk;
		}
		list[i] = mbox++;
	}

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem) {
		ret = -ENOENT;
		goto free_privblk;
	}

	mbox_base = ioremap(mem->start, resource_size(mem));
	if (!mbox_base) {
		ret = -ENOMEM;
		goto free_privblk;
	}

	ret = omap_mbox_register(&pdev->dev, list);
	if (ret)
		goto unmap_mbox;
	platform_set_drvdata(pdev, list);

	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 omap_mbox **list = platform_get_drvdata(pdev);
	struct omap_mbox *mboxblk = list[0];

	privblk = mboxblk->priv;
	omap_mbox_unregister();
	iounmap(mbox_base);
	kfree(privblk);
	kfree(mboxblk);
	kfree(list);

	return 0;
}

static struct platform_driver omap2_mbox_driver = {
	.probe	= omap2_mbox_probe,
	.remove	= omap2_mbox_remove,
	.driver	= {
		.name = "omap-mailbox",
	},
};

static int __init omap2_mbox_init(void)
{
	return platform_driver_register(&omap2_mbox_driver);
}

static void __exit omap2_mbox_exit(void)
{
	platform_driver_unregister(&omap2_mbox_driver);
}

module_init(omap2_mbox_init);
module_exit(omap2_mbox_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
MODULE_AUTHOR("Paul Mundt");
MODULE_ALIAS("platform:omap2-mailbox");
Loading