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

Commit 10cd7158 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull mailbox updates from Jassi Brar:
 "OMAP:
   - Remove non-DT support from mailbox driver
   - Move PM from client calls to native driver suspend/resume
   - Trivial cleanups to make checkpatch happy

  STI:
   - Check return from devm_ioremap_resource as ERR_PTR, not NULL"

* 'mailbox-for-next' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
  mailbox: Fix devm_ioremap_resource error detection code
  mailbox/omap: kill omap_mbox_{save/restore}_ctx() functions
  mailbox/omap: check for any unread messages during suspend
  mailbox/omap: add support for suspend/resume
  mailbox/omap: store mailbox interrupt type in omap_mbox_device
  mailbox/omap: add blank lines after declarations
  mailbox/omap: remove FSF mailing address paragraph
  mailbox/omap: use variable name for sizeof() operator
  mailbox/omap: drop legacy platform device support
parents 51e68d05 c430cf37
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -430,8 +430,8 @@ static int sti_mbox_probe(struct platform_device *pdev)


	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	mdev->base = devm_ioremap_resource(&pdev->dev, res);
	mdev->base = devm_ioremap_resource(&pdev->dev, res);
	if (!mdev->base)
	if (IS_ERR(mdev->base))
		return -ENOMEM;
		return PTR_ERR(mdev->base);


	ret = of_property_read_string(np, "mbox-name", &mdev->name);
	ret = of_property_read_string(np, "mbox-name", &mdev->name);
	if (ret)
	if (ret)
+102 −118
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
 * OMAP mailbox driver
 * OMAP mailbox driver
 *
 *
 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
 * Copyright (C) 2013-2014 Texas Instruments Inc.
 * Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com
 *
 *
 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 *          Suman Anna <s-anna@ti.com>
 *          Suman Anna <s-anna@ti.com>
@@ -15,12 +15,6 @@
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 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 <linux/interrupt.h>
#include <linux/interrupt.h>
@@ -33,7 +27,6 @@
#include <linux/of_device.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_runtime.h>
#include <linux/platform_data/mailbox-omap.h>
#include <linux/omap-mailbox.h>
#include <linux/omap-mailbox.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox_client.h>
@@ -62,12 +55,9 @@
#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))


#define MBOX_REG_SIZE			0x120
/* Interrupt register configuration types */

#define MBOX_INTR_CFG_TYPE1		0
#define OMAP4_MBOX_REG_SIZE		0x130
#define MBOX_INTR_CFG_TYPE2		1

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


struct omap_mbox_fifo {
struct omap_mbox_fifo {
	unsigned long msg;
	unsigned long msg;
@@ -91,8 +81,10 @@ struct omap_mbox_device {
	struct device *dev;
	struct device *dev;
	struct mutex cfg_lock;
	struct mutex cfg_lock;
	void __iomem *mbox_base;
	void __iomem *mbox_base;
	u32 *irq_ctx;
	u32 num_users;
	u32 num_users;
	u32 num_fifos;
	u32 num_fifos;
	u32 intr_type;
	struct omap_mbox **mboxes;
	struct omap_mbox **mboxes;
	struct mbox_controller controller;
	struct mbox_controller controller;
	struct list_head elem;
	struct list_head elem;
@@ -119,7 +111,6 @@ struct omap_mbox {
	struct omap_mbox_device *parent;
	struct omap_mbox_device *parent;
	struct omap_mbox_fifo	tx_fifo;
	struct omap_mbox_fifo	tx_fifo;
	struct omap_mbox_fifo	rx_fifo;
	struct omap_mbox_fifo	rx_fifo;
	u32			ctx[OMAP4_MBOX_NR_REGS];
	u32			intr_type;
	u32			intr_type;
	struct mbox_chan	*chan;
	struct mbox_chan	*chan;
	bool			send_no_irq;
	bool			send_no_irq;
@@ -157,24 +148,28 @@ void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{
{
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;

	return (mbox_msg_t)mbox_read_reg(mbox->parent, fifo->msg);
	return (mbox_msg_t)mbox_read_reg(mbox->parent, fifo->msg);
}
}


static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
{
	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;

	mbox_write_reg(mbox->parent, msg, fifo->msg);
	mbox_write_reg(mbox->parent, msg, fifo->msg);
}
}


static int mbox_fifo_empty(struct omap_mbox *mbox)
static int mbox_fifo_empty(struct omap_mbox *mbox)
{
{
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
	struct omap_mbox_fifo *fifo = &mbox->rx_fifo;

	return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
	return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
}
}


static int mbox_fifo_full(struct omap_mbox *mbox)
static int mbox_fifo_full(struct omap_mbox *mbox)
{
{
	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
	struct omap_mbox_fifo *fifo = &mbox->tx_fifo;

	return mbox_read_reg(mbox->parent, fifo->fifo_stat);
	return mbox_read_reg(mbox->parent, fifo->fifo_stat);
}
}


@@ -206,49 +201,6 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
	return (int)(enable & status & bit);
	return (int)(enable & status & bit);
}
}


void omap_mbox_save_ctx(struct mbox_chan *chan)
{
	int i;
	int nr_regs;
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);

	if (WARN_ON(!mbox))
		return;

	if (mbox->intr_type)
		nr_regs = OMAP4_MBOX_NR_REGS;
	else
		nr_regs = MBOX_NR_REGS;
	for (i = 0; i < nr_regs; i++) {
		mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));

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

void omap_mbox_restore_ctx(struct mbox_chan *chan)
{
	int i;
	int nr_regs;
	struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);

	if (WARN_ON(!mbox))
		return;

	if (mbox->intr_type)
		nr_regs = OMAP4_MBOX_NR_REGS;
	else
		nr_regs = MBOX_NR_REGS;
	for (i = 0; i < nr_regs; i++) {
		mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
			i, mbox->ctx[i]);
	}
}
EXPORT_SYMBOL(omap_mbox_restore_ctx);

static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
{
	u32 l;
	u32 l;
@@ -381,7 +333,7 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
	if (!work)
	if (!work)
		return NULL;
		return NULL;


	mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
	mq = kzalloc(sizeof(*mq), GFP_KERNEL);
	if (!mq)
	if (!mq)
		return NULL;
		return NULL;


@@ -525,6 +477,7 @@ static int omap_mbox_register(struct omap_mbox_device *mdev)
	mboxes = mdev->mboxes;
	mboxes = mdev->mboxes;
	for (i = 0; mboxes[i]; i++) {
	for (i = 0; mboxes[i]; i++) {
		struct omap_mbox *mbox = mboxes[i];
		struct omap_mbox *mbox = mboxes[i];

		mbox->dev = device_create(&omap_mbox_class, mdev->dev,
		mbox->dev = device_create(&omap_mbox_class, mdev->dev,
					0, mbox, "%s", mbox->name);
					0, mbox, "%s", mbox->name);
		if (IS_ERR(mbox->dev)) {
		if (IS_ERR(mbox->dev)) {
@@ -647,6 +600,52 @@ static const struct mbox_chan_ops omap_mbox_chan_ops = {
	.shutdown       = omap_mbox_chan_shutdown,
	.shutdown       = omap_mbox_chan_shutdown,
};
};


#ifdef CONFIG_PM_SLEEP
static int omap_mbox_suspend(struct device *dev)
{
	struct omap_mbox_device *mdev = dev_get_drvdata(dev);
	u32 usr, fifo, reg;

	if (pm_runtime_status_suspended(dev))
		return 0;

	for (fifo = 0; fifo < mdev->num_fifos; fifo++) {
		if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) {
			dev_err(mdev->dev, "fifo %d has unexpected unread messages\n",
				fifo);
			return -EBUSY;
		}
	}

	for (usr = 0; usr < mdev->num_users; usr++) {
		reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
		mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg);
	}

	return 0;
}

static int omap_mbox_resume(struct device *dev)
{
	struct omap_mbox_device *mdev = dev_get_drvdata(dev);
	u32 usr, reg;

	if (pm_runtime_status_suspended(dev))
		return 0;

	for (usr = 0; usr < mdev->num_users; usr++) {
		reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
		mbox_write_reg(mdev, mdev->irq_ctx[usr], reg);
	}

	return 0;
}
#endif

static const struct dev_pm_ops omap_mbox_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume)
};

static const struct of_device_id omap_mailbox_of_match[] = {
static const struct of_device_id omap_mailbox_of_match[] = {
	{
	{
		.compatible	= "ti,omap2-mailbox",
		.compatible	= "ti,omap2-mailbox",
@@ -696,8 +695,6 @@ static int omap_mbox_probe(struct platform_device *pdev)
	int ret;
	int ret;
	struct mbox_chan *chnls;
	struct mbox_chan *chnls;
	struct omap_mbox **list, *mbox, *mboxblk;
	struct omap_mbox **list, *mbox, *mboxblk;
	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
	struct omap_mbox_dev_info *info = NULL;
	struct omap_mbox_fifo_info *finfo, *finfoblk;
	struct omap_mbox_fifo_info *finfo, *finfoblk;
	struct omap_mbox_device *mdev;
	struct omap_mbox_device *mdev;
	struct omap_mbox_fifo *fifo;
	struct omap_mbox_fifo *fifo;
@@ -710,23 +707,20 @@ static int omap_mbox_probe(struct platform_device *pdev)
	u32 l;
	u32 l;
	int i;
	int i;


	if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) {
	if (!node) {
		pr_err("%s: platform not supported\n", __func__);
		pr_err("%s: only DT-based devices are supported\n", __func__);
		return -ENODEV;
		return -ENODEV;
	}
	}


	if (node) {
	match = of_match_device(omap_mailbox_of_match, &pdev->dev);
	match = of_match_device(omap_mailbox_of_match, &pdev->dev);
	if (!match)
	if (!match)
		return -ENODEV;
		return -ENODEV;
	intr_type = (u32)match->data;
	intr_type = (u32)match->data;


		if (of_property_read_u32(node, "ti,mbox-num-users",
	if (of_property_read_u32(node, "ti,mbox-num-users", &num_users))
					 &num_users))
		return -ENODEV;
		return -ENODEV;


		if (of_property_read_u32(node, "ti,mbox-num-fifos",
	if (of_property_read_u32(node, "ti,mbox-num-fifos", &num_fifos))
					 &num_fifos))
		return -ENODEV;
		return -ENODEV;


	info_count = of_get_available_child_count(node);
	info_count = of_get_available_child_count(node);
@@ -734,13 +728,6 @@ static int omap_mbox_probe(struct platform_device *pdev)
		dev_err(&pdev->dev, "no available mbox devices found\n");
		dev_err(&pdev->dev, "no available mbox devices found\n");
		return -ENODEV;
		return -ENODEV;
	}
	}
	} else { /* non-DT device creation */
		info_count = pdata->info_cnt;
		info = pdata->info;
		intr_type = pdata->intr_type;
		num_users = pdata->num_users;
		num_fifos = pdata->num_fifos;
	}


	finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk),
	finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk),
				GFP_KERNEL);
				GFP_KERNEL);
@@ -750,18 +737,17 @@ static int omap_mbox_probe(struct platform_device *pdev)
	finfo = finfoblk;
	finfo = finfoblk;
	child = NULL;
	child = NULL;
	for (i = 0; i < info_count; i++, finfo++) {
	for (i = 0; i < info_count; i++, finfo++) {
		if (node) {
		child = of_get_next_available_child(node, child);
		child = of_get_next_available_child(node, child);
			ret = of_property_read_u32_array(child, "ti,mbox-tx",
		ret = of_property_read_u32_array(child, "ti,mbox-tx", tmp,
							 tmp, ARRAY_SIZE(tmp));
						 ARRAY_SIZE(tmp));
		if (ret)
		if (ret)
			return ret;
			return ret;
		finfo->tx_id = tmp[0];
		finfo->tx_id = tmp[0];
		finfo->tx_irq = tmp[1];
		finfo->tx_irq = tmp[1];
		finfo->tx_usr = tmp[2];
		finfo->tx_usr = tmp[2];


			ret = of_property_read_u32_array(child, "ti,mbox-rx",
		ret = of_property_read_u32_array(child, "ti,mbox-rx", tmp,
							 tmp, ARRAY_SIZE(tmp));
						 ARRAY_SIZE(tmp));
		if (ret)
		if (ret)
			return ret;
			return ret;
		finfo->rx_id = tmp[0];
		finfo->rx_id = tmp[0];
@@ -772,16 +758,7 @@ static int omap_mbox_probe(struct platform_device *pdev)


		if (of_find_property(child, "ti,mbox-send-noirq", NULL))
		if (of_find_property(child, "ti,mbox-send-noirq", NULL))
			finfo->send_no_irq = true;
			finfo->send_no_irq = true;
		} else {

			finfo->tx_id = info->tx_id;
			finfo->rx_id = info->rx_id;
			finfo->tx_usr = info->usr_id;
			finfo->tx_irq = info->irq_id;
			finfo->rx_usr = info->usr_id;
			finfo->rx_irq = info->irq_id;
			finfo->name = info->name;
			info++;
		}
		if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos ||
		if (finfo->tx_id >= num_fifos || finfo->rx_id >= num_fifos ||
		    finfo->tx_usr >= num_users || finfo->rx_usr >= num_users)
		    finfo->tx_usr >= num_users || finfo->rx_usr >= num_users)
			return -EINVAL;
			return -EINVAL;
@@ -796,6 +773,11 @@ static int omap_mbox_probe(struct platform_device *pdev)
	if (IS_ERR(mdev->mbox_base))
	if (IS_ERR(mdev->mbox_base))
		return PTR_ERR(mdev->mbox_base);
		return PTR_ERR(mdev->mbox_base);


	mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32),
				     GFP_KERNEL);
	if (!mdev->irq_ctx)
		return -ENOMEM;

	/* allocate one extra for marking end of list */
	/* allocate one extra for marking end of list */
	list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
	list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
			    GFP_KERNEL);
			    GFP_KERNEL);
@@ -848,6 +830,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
	mdev->dev = &pdev->dev;
	mdev->dev = &pdev->dev;
	mdev->num_users = num_users;
	mdev->num_users = num_users;
	mdev->num_fifos = num_fifos;
	mdev->num_fifos = num_fifos;
	mdev->intr_type = intr_type;
	mdev->mboxes = list;
	mdev->mboxes = list;


	/* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
	/* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
@@ -905,6 +888,7 @@ static struct platform_driver omap_mbox_driver = {
	.remove	= omap_mbox_remove,
	.remove	= omap_mbox_remove,
	.driver	= {
	.driver	= {
		.name = "omap-mailbox",
		.name = "omap-mailbox",
		.pm = &omap_mbox_pm_ops,
		.of_match_table = of_match_ptr(omap_mailbox_of_match),
		.of_match_table = of_match_ptr(omap_mailbox_of_match),
	},
	},
};
};
+0 −2
Original line number Original line Diff line number Diff line
@@ -21,8 +21,6 @@ struct mbox_client;
struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
					    const char *chan_name);
					    const char *chan_name);


void omap_mbox_save_ctx(struct mbox_chan *chan);
void omap_mbox_restore_ctx(struct mbox_chan *chan);
void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);


+0 −58
Original line number Original line Diff line number Diff line
/*
 * 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
 * @num_users:	number of users (processor devices) that the mailbox
 *			h/w block can interrupt
 * @num_fifos:	number of h/w fifos within the mailbox h/w block
 * @info_cnt:	number of mailbox devices for the platform
 * @info:	array of mailbox device attributes
 */
struct omap_mbox_pdata {
	u32 intr_type;
	u32 num_users;
	u32 num_fifos;
	u32 info_cnt;
	struct omap_mbox_dev_info *info;
};

#endif /* _PLAT_MAILBOX_H */