From patchwork Wed Jun 25 00:43:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suman Anna X-Patchwork-Id: 4415491 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 693ABBEEAA for ; Wed, 25 Jun 2014 00:45:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 31412201EF for ; Wed, 25 Jun 2014 00:45:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C68402037B for ; Wed, 25 Jun 2014 00:45:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753219AbaFYApL (ORCPT ); Tue, 24 Jun 2014 20:45:11 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:33864 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752978AbaFYApK (ORCPT ); Tue, 24 Jun 2014 20:45:10 -0400 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id s5P0ipkR009148; Tue, 24 Jun 2014 19:44:51 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id s5P0ip4w001086; Tue, 24 Jun 2014 19:44:51 -0500 Received: from dlep32.itg.ti.com (157.170.170.100) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.174.1; Tue, 24 Jun 2014 19:44:51 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id s5P0ipKd018448; Tue, 24 Jun 2014 19:44:51 -0500 Received: from localhost (irmo.am.dhcp.ti.com [128.247.71.175]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id s5P0ipt21974; Tue, 24 Jun 2014 19:44:51 -0500 (CDT) From: Suman Anna To: Tony Lindgren CC: Dave Gerlach , Jassi Brar , , , Suman Anna Subject: [PATCH 7/7] mailbox/omap: add a parent structure for every IP instance Date: Tue, 24 Jun 2014 19:43:43 -0500 Message-ID: <1403657023-53897-8-git-send-email-s-anna@ti.com> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1403657023-53897-1-git-send-email-s-anna@ti.com> References: <1403657023-53897-1-git-send-email-s-anna@ti.com> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A new structure, omap_mbox_device, is added to contain the global variables pertinent to a mailbox h/w IP block. This enables the support for having multiple instances of the same h/w IP block in the SoC. This is in preparation to support the DRA7 SoC, which is the first SoC in the OMAP family to have multiple mailbox IP instances. The changes include enhancements to the sub-mailbox registration logic and mbox startup sequencing, removing the usage of single global configuration variables for all h/w instances, and storing the registered sub-mailboxes with the parent mailbox device structure. Signed-off-by: Suman Anna --- drivers/mailbox/omap-mailbox.c | 173 +++++++++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 58 deletions(-) diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c index d9a5039..a27e00e 100644 --- a/drivers/mailbox/omap-mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -84,11 +84,22 @@ struct omap_mbox_queue { bool full; }; +struct omap_mbox_device { + struct device *dev; + struct mutex cfg_lock; + void __iomem *mbox_base; + u32 num_users; + u32 num_fifos; + struct omap_mbox **mboxes; + struct list_head elem; +}; + struct omap_mbox { const char *name; int irq; struct omap_mbox_queue *txq, *rxq; struct device *dev; + struct omap_mbox_device *parent; struct omap_mbox_fifo tx_fifo; struct omap_mbox_fifo rx_fifo; u32 ctx[OMAP4_MBOX_NR_REGS]; @@ -97,48 +108,49 @@ struct omap_mbox { struct blocking_notifier_head notifier; }; -static void __iomem *mbox_base; -static struct omap_mbox **mboxes; - -static DEFINE_MUTEX(mbox_configured_lock); +/* global variables for the mailbox devices */ +static DEFINE_MUTEX(omap_mbox_devices_lock); +static LIST_HEAD(omap_mbox_devices); 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)"); -static inline unsigned int mbox_read_reg(size_t ofs) +static inline +unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs) { - return __raw_readl(mbox_base + ofs); + return __raw_readl(mdev->mbox_base + ofs); } -static inline void mbox_write_reg(u32 val, size_t ofs) +static inline +void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs) { - __raw_writel(val, mbox_base + ofs); + __raw_writel(val, mdev->mbox_base + ofs); } /* Mailbox FIFO handle functions */ static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->rx_fifo; - return (mbox_msg_t) mbox_read_reg(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) { struct omap_mbox_fifo *fifo = &mbox->tx_fifo; - mbox_write_reg(msg, fifo->msg); + mbox_write_reg(mbox->parent, msg, fifo->msg); } static int mbox_fifo_empty(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->rx_fifo; - return (mbox_read_reg(fifo->msg_stat) == 0); + return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0); } static int mbox_fifo_full(struct omap_mbox *mbox) { struct omap_mbox_fifo *fifo = &mbox->tx_fifo; - return mbox_read_reg(fifo->fifo_stat); + return mbox_read_reg(mbox->parent, fifo->fifo_stat); } /* Mailbox IRQ handle functions */ @@ -149,10 +161,10 @@ static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) u32 bit = fifo->intr_bit; u32 irqstatus = fifo->irqstatus; - mbox_write_reg(bit, irqstatus); + mbox_write_reg(mbox->parent, bit, irqstatus); /* Flush posted write for irq status to avoid spurious interrupts */ - mbox_read_reg(irqstatus); + mbox_read_reg(mbox->parent, irqstatus); } static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) @@ -163,8 +175,8 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) u32 irqenable = fifo->irqenable; u32 irqstatus = fifo->irqstatus; - u32 enable = mbox_read_reg(irqenable); - u32 status = mbox_read_reg(irqstatus); + u32 enable = mbox_read_reg(mbox->parent, irqenable); + u32 status = mbox_read_reg(mbox->parent, irqstatus); return (int)(enable & status & bit); } @@ -210,7 +222,7 @@ void omap_mbox_save_ctx(struct omap_mbox *mbox) else nr_regs = MBOX_NR_REGS; for (i = 0; i < nr_regs; i++) { - mbox->ctx[i] = mbox_read_reg(i * sizeof(u32)); + mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32)); dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, i, mbox->ctx[i]); @@ -228,7 +240,7 @@ void omap_mbox_restore_ctx(struct omap_mbox *mbox) else nr_regs = MBOX_NR_REGS; for (i = 0; i < nr_regs; i++) { - mbox_write_reg(mbox->ctx[i], i * sizeof(u32)); + mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32)); dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, i, mbox->ctx[i]); @@ -244,9 +256,9 @@ void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) u32 bit = fifo->intr_bit; u32 irqenable = fifo->irqenable; - l = mbox_read_reg(irqenable); + l = mbox_read_reg(mbox->parent, irqenable); l |= bit; - mbox_write_reg(l, irqenable); + mbox_write_reg(mbox->parent, l, irqenable); } EXPORT_SYMBOL(omap_mbox_enable_irq); @@ -262,9 +274,9 @@ void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) * OMAP4 and later SoCs have a dedicated interrupt disabling register. */ if (!mbox->intr_type) - bit = mbox_read_reg(irqdisable) & ~bit; + bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit; - mbox_write_reg(bit, irqdisable); + mbox_write_reg(mbox->parent, bit, irqdisable); } EXPORT_SYMBOL(omap_mbox_disable_irq); @@ -398,9 +410,10 @@ static int omap_mbox_startup(struct omap_mbox *mbox) { int ret = 0; struct omap_mbox_queue *mq; + struct omap_mbox_device *mdev = mbox->parent; - mutex_lock(&mbox_configured_lock); - ret = pm_runtime_get_sync(mbox->dev->parent); + mutex_lock(&mdev->cfg_lock); + ret = pm_runtime_get_sync(mdev->dev); if (unlikely(ret < 0)) goto fail_startup; @@ -429,7 +442,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox) omap_mbox_enable_irq(mbox, IRQ_RX); } - mutex_unlock(&mbox_configured_lock); + mutex_unlock(&mdev->cfg_lock); return 0; fail_request_irq: @@ -437,16 +450,18 @@ fail_request_irq: fail_alloc_rxq: mbox_queue_free(mbox->txq); fail_alloc_txq: - pm_runtime_put_sync(mbox->dev->parent); + pm_runtime_put_sync(mdev->dev); mbox->use_count--; fail_startup: - mutex_unlock(&mbox_configured_lock); + mutex_unlock(&mdev->cfg_lock); return ret; } static void omap_mbox_fini(struct omap_mbox *mbox) { - mutex_lock(&mbox_configured_lock); + struct omap_mbox_device *mdev = mbox->parent; + + mutex_lock(&mdev->cfg_lock); if (!--mbox->use_count) { omap_mbox_disable_irq(mbox, IRQ_RX); @@ -457,25 +472,43 @@ static void omap_mbox_fini(struct omap_mbox *mbox) mbox_queue_free(mbox->rxq); } - pm_runtime_put_sync(mbox->dev->parent); + pm_runtime_put_sync(mdev->dev); - mutex_unlock(&mbox_configured_lock); + mutex_unlock(&mdev->cfg_lock); } -struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) +static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev, + const char *mbox_name) { struct omap_mbox *_mbox, *mbox = NULL; - int i, ret; + struct omap_mbox **mboxes = mdev->mboxes; + int i; if (!mboxes) - return ERR_PTR(-EINVAL); + return NULL; for (i = 0; (_mbox = mboxes[i]); i++) { - if (!strcmp(_mbox->name, name)) { + if (!strcmp(_mbox->name, mbox_name)) { mbox = _mbox; break; } } + return mbox; +} + +struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) +{ + struct omap_mbox *mbox = NULL; + struct omap_mbox_device *mdev; + int ret; + + mutex_lock(&omap_mbox_devices_lock); + list_for_each_entry(mdev, &omap_mbox_devices, elem) { + mbox = omap_mbox_device_find(mdev, name); + if (mbox) + break; + } + mutex_unlock(&omap_mbox_devices_lock); if (!mbox) return ERR_PTR(-ENOENT); @@ -502,19 +535,20 @@ EXPORT_SYMBOL(omap_mbox_put); static struct class omap_mbox_class = { .name = "mbox", }; -static int omap_mbox_register(struct device *parent, struct omap_mbox **list) +static int omap_mbox_register(struct omap_mbox_device *mdev) { int ret; int i; + struct omap_mbox **mboxes; - mboxes = list; - if (!mboxes) + if (!mdev || !mdev->mboxes) return -EINVAL; + mboxes = mdev->mboxes; 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); + mdev->dev, 0, mbox, "%s", mbox->name); if (IS_ERR(mbox->dev)) { ret = PTR_ERR(mbox->dev); goto err_out; @@ -522,6 +556,11 @@ static int omap_mbox_register(struct device *parent, struct omap_mbox **list) BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); } + + mutex_lock(&omap_mbox_devices_lock); + list_add(&mdev->elem, &omap_mbox_devices); + mutex_unlock(&omap_mbox_devices_lock); + return 0; err_out: @@ -530,16 +569,21 @@ err_out: return ret; } -static int omap_mbox_unregister(void) +static int omap_mbox_unregister(struct omap_mbox_device *mdev) { int i; + struct omap_mbox **mboxes; - if (!mboxes) + if (!mdev || !mdev->mboxes) return -EINVAL; + mutex_lock(&omap_mbox_devices_lock); + list_del(&mdev->elem); + mutex_unlock(&omap_mbox_devices_lock); + + mboxes = mdev->mboxes; for (i = 0; mboxes[i]; i++) device_unregister(mboxes[i]->dev); - mboxes = NULL; return 0; } @@ -550,6 +594,7 @@ static int omap_mbox_probe(struct platform_device *pdev) struct omap_mbox **list, *mbox, *mboxblk; struct omap_mbox_pdata *pdata = pdev->dev.platform_data; struct omap_mbox_dev_info *info; + struct omap_mbox_device *mdev; struct omap_mbox_fifo *fifo; u32 intr_type; u32 l; @@ -560,6 +605,15 @@ static int omap_mbox_probe(struct platform_device *pdev) return -ENODEV; } + mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(mdev->mbox_base)) + return PTR_ERR(mdev->mbox_base); + /* allocate one extra for marking end of list */ list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL); @@ -593,6 +647,7 @@ static int omap_mbox_probe(struct platform_device *pdev) mbox->intr_type = intr_type; + mbox->parent = mdev; mbox->name = info->name; mbox->irq = platform_get_irq(pdev, info->irq_id); if (mbox->irq < 0) @@ -600,21 +655,21 @@ static int omap_mbox_probe(struct platform_device *pdev) list[i] = mbox++; } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mbox_base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(mbox_base)) - return PTR_ERR(mbox_base); - - ret = omap_mbox_register(&pdev->dev, list); + mutex_init(&mdev->cfg_lock); + mdev->dev = &pdev->dev; + mdev->num_users = pdata->num_users; + mdev->num_fifos = pdata->num_fifos; + mdev->mboxes = list; + ret = omap_mbox_register(mdev); if (ret) return ret; - platform_set_drvdata(pdev, list); - pm_runtime_enable(&pdev->dev); + platform_set_drvdata(pdev, mdev); + pm_runtime_enable(mdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(mdev->dev); if (ret < 0) { - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_put_noidle(mdev->dev); goto unregister; } @@ -622,25 +677,27 @@ static int omap_mbox_probe(struct platform_device *pdev) * just print the raw revision register, the format is not * uniform across all SoCs */ - l = mbox_read_reg(MAILBOX_REVISION); - dev_info(&pdev->dev, "omap mailbox rev 0x%x\n", l); + l = mbox_read_reg(mdev, MAILBOX_REVISION); + dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l); - ret = pm_runtime_put_sync(&pdev->dev); + ret = pm_runtime_put_sync(mdev->dev); if (ret < 0) goto unregister; return 0; unregister: - pm_runtime_disable(&pdev->dev); - omap_mbox_unregister(); + pm_runtime_disable(mdev->dev); + omap_mbox_unregister(mdev); return ret; } static int omap_mbox_remove(struct platform_device *pdev) { - pm_runtime_disable(&pdev->dev); - omap_mbox_unregister(); + struct omap_mbox_device *mdev = platform_get_drvdata(pdev); + + pm_runtime_disable(mdev->dev); + omap_mbox_unregister(mdev); return 0; }