Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mailbox/omap: consolidate OMAP mailbox driver

There is no need for a separate common OMAP mailbox module
now that the OMAP1 mailbox driver has been removed. So,
consolidate the two individual OMAP mailbox modules into a
single driver. This streamlines the driver for converting
to mailbox framework.

The following are the main changes:
- collapse mailbox-omap2.c into omap-mailbox.c
- remove omap_mbox_ops and replace the ops calls with
the equivalent functionality.
- simplify the sub-mailbox startup/shutdown functionality,
the one-time operations are moved into probe, and the
pm_runtime_get_sync and pm_runtime_put_sync can be invoked
without using a configuration counter.
- move all definitions from private omap_mbox.h into the
source code, and eliminate this internal header.
- rename some variables that used the omap2_mbox prefix with
a generic omap_mbox prefix.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

authored by

Suman Anna and committed by
Tony Lindgren
5040f534 ef45eae6

+281 -453
-8
drivers/mailbox/Kconfig
··· 16 16 Management Engine, primarily for cpufreq. Say Y here if you want 17 17 to use the PL320 IPCM support. 18 18 19 - config OMAP_MBOX 20 - tristate 21 - help 22 - This option is selected by any OMAP architecture specific mailbox 23 - driver such as CONFIG_OMAP2PLUS_MBOX. This enables the common OMAP 24 - mailbox framework code. 25 - 26 19 config OMAP2PLUS_MBOX 27 20 tristate "OMAP2+ Mailbox framework support" 28 21 depends on ARCH_OMAP2PLUS 29 - select OMAP_MBOX 30 22 help 31 23 Mailbox implementation for OMAP family chips with hardware for 32 24 interprocessor communication involving DSP, IVA1.0 and IVA2 in
+1 -3
drivers/mailbox/Makefile
··· 1 1 obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o 2 2 3 - obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o 4 - obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox_omap2.o 5 - mailbox_omap2-objs := mailbox-omap2.o 3 + obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
-333
drivers/mailbox/mailbox-omap2.c
··· 1 - /* 2 - * Mailbox reservation modules for OMAP2/3 3 - * 4 - * Copyright (C) 2006-2009 Nokia Corporation 5 - * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> 6 - * and Paul Mundt 7 - * 8 - * This file is subject to the terms and conditions of the GNU General Public 9 - * License. See the file "COPYING" in the main directory of this archive 10 - * for more details. 11 - */ 12 - 13 - #include <linux/module.h> 14 - #include <linux/slab.h> 15 - #include <linux/clk.h> 16 - #include <linux/err.h> 17 - #include <linux/platform_device.h> 18 - #include <linux/io.h> 19 - #include <linux/pm_runtime.h> 20 - #include <linux/platform_data/mailbox-omap.h> 21 - 22 - #include "omap-mbox.h" 23 - 24 - #define MAILBOX_REVISION 0x000 25 - #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) 26 - #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m)) 27 - #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m)) 28 - 29 - #define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) 30 - #define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) 31 - 32 - #define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u)) 33 - #define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u)) 34 - #define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u)) 35 - 36 - #define MAILBOX_IRQSTATUS(type, u) (type ? OMAP4_MAILBOX_IRQSTATUS(u) : \ 37 - OMAP2_MAILBOX_IRQSTATUS(u)) 38 - #define MAILBOX_IRQENABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE(u) : \ 39 - OMAP2_MAILBOX_IRQENABLE(u)) 40 - #define MAILBOX_IRQDISABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \ 41 - : OMAP2_MAILBOX_IRQENABLE(u)) 42 - 43 - #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) 44 - #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) 45 - 46 - #define MBOX_REG_SIZE 0x120 47 - 48 - #define OMAP4_MBOX_REG_SIZE 0x130 49 - 50 - #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) 51 - #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) 52 - 53 - static void __iomem *mbox_base; 54 - 55 - struct omap_mbox2_fifo { 56 - unsigned long msg; 57 - unsigned long fifo_stat; 58 - unsigned long msg_stat; 59 - }; 60 - 61 - struct omap_mbox2_priv { 62 - struct omap_mbox2_fifo tx_fifo; 63 - struct omap_mbox2_fifo rx_fifo; 64 - unsigned long irqenable; 65 - unsigned long irqstatus; 66 - u32 newmsg_bit; 67 - u32 notfull_bit; 68 - u32 ctx[OMAP4_MBOX_NR_REGS]; 69 - unsigned long irqdisable; 70 - u32 intr_type; 71 - }; 72 - 73 - static inline unsigned int mbox_read_reg(size_t ofs) 74 - { 75 - return __raw_readl(mbox_base + ofs); 76 - } 77 - 78 - static inline void mbox_write_reg(u32 val, size_t ofs) 79 - { 80 - __raw_writel(val, mbox_base + ofs); 81 - } 82 - 83 - /* Mailbox H/W preparations */ 84 - static int omap2_mbox_startup(struct omap_mbox *mbox) 85 - { 86 - u32 l; 87 - 88 - pm_runtime_enable(mbox->dev->parent); 89 - pm_runtime_get_sync(mbox->dev->parent); 90 - 91 - l = mbox_read_reg(MAILBOX_REVISION); 92 - pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); 93 - 94 - return 0; 95 - } 96 - 97 - static void omap2_mbox_shutdown(struct omap_mbox *mbox) 98 - { 99 - pm_runtime_put_sync(mbox->dev->parent); 100 - pm_runtime_disable(mbox->dev->parent); 101 - } 102 - 103 - /* Mailbox FIFO handle functions */ 104 - static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) 105 - { 106 - struct omap_mbox2_fifo *fifo = 107 - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; 108 - return (mbox_msg_t) mbox_read_reg(fifo->msg); 109 - } 110 - 111 - static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 112 - { 113 - struct omap_mbox2_fifo *fifo = 114 - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; 115 - mbox_write_reg(msg, fifo->msg); 116 - } 117 - 118 - static int omap2_mbox_fifo_empty(struct omap_mbox *mbox) 119 - { 120 - struct omap_mbox2_fifo *fifo = 121 - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; 122 - return (mbox_read_reg(fifo->msg_stat) == 0); 123 - } 124 - 125 - static int omap2_mbox_fifo_full(struct omap_mbox *mbox) 126 - { 127 - struct omap_mbox2_fifo *fifo = 128 - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; 129 - return mbox_read_reg(fifo->fifo_stat); 130 - } 131 - 132 - /* Mailbox IRQ handle functions */ 133 - static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 134 - { 135 - struct omap_mbox2_priv *p = mbox->priv; 136 - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 137 - 138 - l = mbox_read_reg(p->irqenable); 139 - l |= bit; 140 - mbox_write_reg(l, p->irqenable); 141 - } 142 - 143 - static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 144 - { 145 - struct omap_mbox2_priv *p = mbox->priv; 146 - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 147 - 148 - /* 149 - * Read and update the interrupt configuration register for pre-OMAP4. 150 - * OMAP4 and later SoCs have a dedicated interrupt disabling register. 151 - */ 152 - if (!p->intr_type) 153 - bit = mbox_read_reg(p->irqdisable) & ~bit; 154 - 155 - mbox_write_reg(bit, p->irqdisable); 156 - } 157 - 158 - static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 159 - { 160 - struct omap_mbox2_priv *p = mbox->priv; 161 - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 162 - 163 - mbox_write_reg(bit, p->irqstatus); 164 - 165 - /* Flush posted write for irq status to avoid spurious interrupts */ 166 - mbox_read_reg(p->irqstatus); 167 - } 168 - 169 - static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 170 - { 171 - struct omap_mbox2_priv *p = mbox->priv; 172 - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 173 - u32 enable = mbox_read_reg(p->irqenable); 174 - u32 status = mbox_read_reg(p->irqstatus); 175 - 176 - return (int)(enable & status & bit); 177 - } 178 - 179 - static void omap2_mbox_save_ctx(struct omap_mbox *mbox) 180 - { 181 - int i; 182 - struct omap_mbox2_priv *p = mbox->priv; 183 - int nr_regs; 184 - 185 - if (p->intr_type) 186 - nr_regs = OMAP4_MBOX_NR_REGS; 187 - else 188 - nr_regs = MBOX_NR_REGS; 189 - for (i = 0; i < nr_regs; i++) { 190 - p->ctx[i] = mbox_read_reg(i * sizeof(u32)); 191 - 192 - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 193 - i, p->ctx[i]); 194 - } 195 - } 196 - 197 - static void omap2_mbox_restore_ctx(struct omap_mbox *mbox) 198 - { 199 - int i; 200 - struct omap_mbox2_priv *p = mbox->priv; 201 - int nr_regs; 202 - 203 - if (p->intr_type) 204 - nr_regs = OMAP4_MBOX_NR_REGS; 205 - else 206 - nr_regs = MBOX_NR_REGS; 207 - for (i = 0; i < nr_regs; i++) { 208 - mbox_write_reg(p->ctx[i], i * sizeof(u32)); 209 - 210 - dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 211 - i, p->ctx[i]); 212 - } 213 - } 214 - 215 - static struct omap_mbox_ops omap2_mbox_ops = { 216 - .startup = omap2_mbox_startup, 217 - .shutdown = omap2_mbox_shutdown, 218 - .fifo_read = omap2_mbox_fifo_read, 219 - .fifo_write = omap2_mbox_fifo_write, 220 - .fifo_empty = omap2_mbox_fifo_empty, 221 - .fifo_full = omap2_mbox_fifo_full, 222 - .enable_irq = omap2_mbox_enable_irq, 223 - .disable_irq = omap2_mbox_disable_irq, 224 - .ack_irq = omap2_mbox_ack_irq, 225 - .is_irq = omap2_mbox_is_irq, 226 - .save_ctx = omap2_mbox_save_ctx, 227 - .restore_ctx = omap2_mbox_restore_ctx, 228 - }; 229 - 230 - static int omap2_mbox_probe(struct platform_device *pdev) 231 - { 232 - struct resource *mem; 233 - int ret; 234 - struct omap_mbox **list, *mbox, *mboxblk; 235 - struct omap_mbox2_priv *priv, *privblk; 236 - struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 237 - struct omap_mbox_dev_info *info; 238 - u32 intr_type; 239 - int i; 240 - 241 - if (!pdata || !pdata->info_cnt || !pdata->info) { 242 - pr_err("%s: platform not supported\n", __func__); 243 - return -ENODEV; 244 - } 245 - 246 - /* allocate one extra for marking end of list */ 247 - list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list), 248 - GFP_KERNEL); 249 - if (!list) 250 - return -ENOMEM; 251 - 252 - mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox), 253 - GFP_KERNEL); 254 - if (!mboxblk) 255 - return -ENOMEM; 256 - 257 - privblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*priv), 258 - GFP_KERNEL); 259 - if (!privblk) 260 - return -ENOMEM; 261 - 262 - info = pdata->info; 263 - intr_type = pdata->intr_type; 264 - mbox = mboxblk; 265 - priv = privblk; 266 - for (i = 0; i < pdata->info_cnt; i++, info++, priv++) { 267 - priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id); 268 - priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); 269 - priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id); 270 - priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id); 271 - priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); 272 - priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); 273 - priv->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id); 274 - priv->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id); 275 - priv->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id); 276 - priv->intr_type = intr_type; 277 - 278 - mbox->priv = priv; 279 - mbox->name = info->name; 280 - mbox->ops = &omap2_mbox_ops; 281 - mbox->irq = platform_get_irq(pdev, info->irq_id); 282 - if (mbox->irq < 0) 283 - return mbox->irq; 284 - list[i] = mbox++; 285 - } 286 - 287 - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 288 - mbox_base = devm_ioremap_resource(&pdev->dev, mem); 289 - if (IS_ERR(mbox_base)) 290 - return PTR_ERR(mbox_base); 291 - 292 - ret = omap_mbox_register(&pdev->dev, list); 293 - if (ret) 294 - return ret; 295 - 296 - platform_set_drvdata(pdev, list); 297 - 298 - return 0; 299 - } 300 - 301 - static int omap2_mbox_remove(struct platform_device *pdev) 302 - { 303 - omap_mbox_unregister(); 304 - 305 - return 0; 306 - } 307 - 308 - static struct platform_driver omap2_mbox_driver = { 309 - .probe = omap2_mbox_probe, 310 - .remove = omap2_mbox_remove, 311 - .driver = { 312 - .name = "omap-mailbox", 313 - }, 314 - }; 315 - 316 - static int __init omap2_mbox_init(void) 317 - { 318 - return platform_driver_register(&omap2_mbox_driver); 319 - } 320 - 321 - static void __exit omap2_mbox_exit(void) 322 - { 323 - platform_driver_unregister(&omap2_mbox_driver); 324 - } 325 - 326 - module_init(omap2_mbox_init); 327 - module_exit(omap2_mbox_exit); 328 - 329 - MODULE_LICENSE("GPL v2"); 330 - MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions"); 331 - MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>"); 332 - MODULE_AUTHOR("Paul Mundt"); 333 - MODULE_ALIAS("platform:omap2-mailbox");
+280 -47
drivers/mailbox/omap-mailbox.c
··· 2 2 * OMAP mailbox driver 3 3 * 4 4 * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved. 5 + * Copyright (C) 2013-2014 Texas Instruments Inc. 5 6 * 6 7 * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> 8 + * Suman Anna <s-anna@ti.com> 7 9 * 8 10 * This program is free software; you can redistribute it and/or 9 11 * modify it under the terms of the GNU General Public License ··· 31 29 #include <linux/err.h> 32 30 #include <linux/notifier.h> 33 31 #include <linux/module.h> 32 + #include <linux/platform_device.h> 33 + #include <linux/pm_runtime.h> 34 + #include <linux/platform_data/mailbox-omap.h> 35 + #include <linux/omap-mailbox.h> 34 36 35 - #include "omap-mbox.h" 37 + #define MAILBOX_REVISION 0x000 38 + #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) 39 + #define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m)) 40 + #define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m)) 36 41 42 + #define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u)) 43 + #define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u)) 44 + 45 + #define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u)) 46 + #define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u)) 47 + #define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u)) 48 + 49 + #define MAILBOX_IRQSTATUS(type, u) (type ? OMAP4_MAILBOX_IRQSTATUS(u) : \ 50 + OMAP2_MAILBOX_IRQSTATUS(u)) 51 + #define MAILBOX_IRQENABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE(u) : \ 52 + OMAP2_MAILBOX_IRQENABLE(u)) 53 + #define MAILBOX_IRQDISABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \ 54 + : OMAP2_MAILBOX_IRQENABLE(u)) 55 + 56 + #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) 57 + #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) 58 + 59 + #define MBOX_REG_SIZE 0x120 60 + 61 + #define OMAP4_MBOX_REG_SIZE 0x130 62 + 63 + #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) 64 + #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) 65 + 66 + struct omap_mbox_fifo { 67 + unsigned long msg; 68 + unsigned long fifo_stat; 69 + unsigned long msg_stat; 70 + }; 71 + 72 + struct omap_mbox_priv { 73 + struct omap_mbox_fifo tx_fifo; 74 + struct omap_mbox_fifo rx_fifo; 75 + unsigned long irqenable; 76 + unsigned long irqstatus; 77 + u32 newmsg_bit; 78 + u32 notfull_bit; 79 + u32 ctx[OMAP4_MBOX_NR_REGS]; 80 + unsigned long irqdisable; 81 + u32 intr_type; 82 + }; 83 + 84 + struct omap_mbox_queue { 85 + spinlock_t lock; 86 + struct kfifo fifo; 87 + struct work_struct work; 88 + struct tasklet_struct tasklet; 89 + struct omap_mbox *mbox; 90 + bool full; 91 + }; 92 + 93 + struct omap_mbox { 94 + const char *name; 95 + int irq; 96 + struct omap_mbox_queue *txq, *rxq; 97 + struct device *dev; 98 + void *priv; 99 + int use_count; 100 + struct blocking_notifier_head notifier; 101 + }; 102 + 103 + static void __iomem *mbox_base; 37 104 static struct omap_mbox **mboxes; 38 105 39 - static int mbox_configured; 40 106 static DEFINE_MUTEX(mbox_configured_lock); 41 107 42 108 static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; 43 109 module_param(mbox_kfifo_size, uint, S_IRUGO); 44 110 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 45 111 112 + static inline unsigned int mbox_read_reg(size_t ofs) 113 + { 114 + return __raw_readl(mbox_base + ofs); 115 + } 116 + 117 + static inline void mbox_write_reg(u32 val, size_t ofs) 118 + { 119 + __raw_writel(val, mbox_base + ofs); 120 + } 121 + 46 122 /* Mailbox FIFO handle functions */ 47 - static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 123 + static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) 48 124 { 49 - return mbox->ops->fifo_read(mbox); 125 + struct omap_mbox_fifo *fifo = 126 + &((struct omap_mbox_priv *)mbox->priv)->rx_fifo; 127 + return (mbox_msg_t) mbox_read_reg(fifo->msg); 50 128 } 51 - static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 129 + 130 + static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) 52 131 { 53 - mbox->ops->fifo_write(mbox, msg); 132 + struct omap_mbox_fifo *fifo = 133 + &((struct omap_mbox_priv *)mbox->priv)->tx_fifo; 134 + mbox_write_reg(msg, fifo->msg); 54 135 } 55 - static inline int mbox_fifo_empty(struct omap_mbox *mbox) 136 + 137 + static int mbox_fifo_empty(struct omap_mbox *mbox) 56 138 { 57 - return mbox->ops->fifo_empty(mbox); 139 + struct omap_mbox_fifo *fifo = 140 + &((struct omap_mbox_priv *)mbox->priv)->rx_fifo; 141 + return (mbox_read_reg(fifo->msg_stat) == 0); 58 142 } 59 - static inline int mbox_fifo_full(struct omap_mbox *mbox) 143 + 144 + static int mbox_fifo_full(struct omap_mbox *mbox) 60 145 { 61 - return mbox->ops->fifo_full(mbox); 146 + struct omap_mbox_fifo *fifo = 147 + &((struct omap_mbox_priv *)mbox->priv)->tx_fifo; 148 + return mbox_read_reg(fifo->fifo_stat); 62 149 } 63 150 64 151 /* Mailbox IRQ handle functions */ 65 - static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 152 + static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 66 153 { 67 - if (mbox->ops->ack_irq) 68 - mbox->ops->ack_irq(mbox, irq); 154 + struct omap_mbox_priv *p = mbox->priv; 155 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 156 + 157 + mbox_write_reg(bit, p->irqstatus); 158 + 159 + /* Flush posted write for irq status to avoid spurious interrupts */ 160 + mbox_read_reg(p->irqstatus); 69 161 } 70 - static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 162 + 163 + static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 71 164 { 72 - return mbox->ops->is_irq(mbox, irq); 165 + struct omap_mbox_priv *p = mbox->priv; 166 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 167 + u32 enable = mbox_read_reg(p->irqenable); 168 + u32 status = mbox_read_reg(p->irqstatus); 169 + 170 + return (int)(enable & status & bit); 73 171 } 74 172 75 173 /* ··· 205 103 206 104 void omap_mbox_save_ctx(struct omap_mbox *mbox) 207 105 { 208 - if (!mbox->ops->save_ctx) { 209 - dev_err(mbox->dev, "%s:\tno save\n", __func__); 210 - return; 211 - } 106 + int i; 107 + struct omap_mbox_priv *p = mbox->priv; 108 + int nr_regs; 212 109 213 - mbox->ops->save_ctx(mbox); 110 + if (p->intr_type) 111 + nr_regs = OMAP4_MBOX_NR_REGS; 112 + else 113 + nr_regs = MBOX_NR_REGS; 114 + for (i = 0; i < nr_regs; i++) { 115 + p->ctx[i] = mbox_read_reg(i * sizeof(u32)); 116 + 117 + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 118 + i, p->ctx[i]); 119 + } 214 120 } 215 121 EXPORT_SYMBOL(omap_mbox_save_ctx); 216 122 217 123 void omap_mbox_restore_ctx(struct omap_mbox *mbox) 218 124 { 219 - if (!mbox->ops->restore_ctx) { 220 - dev_err(mbox->dev, "%s:\tno restore\n", __func__); 221 - return; 222 - } 125 + int i; 126 + struct omap_mbox_priv *p = mbox->priv; 127 + int nr_regs; 223 128 224 - mbox->ops->restore_ctx(mbox); 129 + if (p->intr_type) 130 + nr_regs = OMAP4_MBOX_NR_REGS; 131 + else 132 + nr_regs = MBOX_NR_REGS; 133 + for (i = 0; i < nr_regs; i++) { 134 + mbox_write_reg(p->ctx[i], i * sizeof(u32)); 135 + 136 + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 137 + i, p->ctx[i]); 138 + } 225 139 } 226 140 EXPORT_SYMBOL(omap_mbox_restore_ctx); 227 141 228 142 void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 229 143 { 230 - mbox->ops->enable_irq(mbox, irq); 144 + struct omap_mbox_priv *p = mbox->priv; 145 + u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 146 + 147 + l = mbox_read_reg(p->irqenable); 148 + l |= bit; 149 + mbox_write_reg(l, p->irqenable); 231 150 } 232 151 EXPORT_SYMBOL(omap_mbox_enable_irq); 233 152 234 153 void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 235 154 { 236 - mbox->ops->disable_irq(mbox, irq); 155 + struct omap_mbox_priv *p = mbox->priv; 156 + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; 157 + 158 + /* 159 + * Read and update the interrupt configuration register for pre-OMAP4. 160 + * OMAP4 and later SoCs have a dedicated interrupt disabling register. 161 + */ 162 + if (!p->intr_type) 163 + bit = mbox_read_reg(p->irqdisable) & ~bit; 164 + 165 + mbox_write_reg(bit, p->irqdisable); 237 166 } 238 167 EXPORT_SYMBOL(omap_mbox_disable_irq); 239 168 ··· 400 267 struct omap_mbox_queue *mq; 401 268 402 269 mutex_lock(&mbox_configured_lock); 403 - if (!mbox_configured++) { 404 - if (likely(mbox->ops->startup)) { 405 - ret = mbox->ops->startup(mbox); 406 - if (unlikely(ret)) 407 - goto fail_startup; 408 - } else 409 - goto fail_startup; 410 - } 270 + ret = pm_runtime_get_sync(mbox->dev->parent); 271 + if (unlikely(ret < 0)) 272 + goto fail_startup; 411 273 412 274 if (!mbox->use_count++) { 413 275 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); ··· 437 309 fail_alloc_rxq: 438 310 mbox_queue_free(mbox->txq); 439 311 fail_alloc_txq: 440 - if (mbox->ops->shutdown) 441 - mbox->ops->shutdown(mbox); 312 + pm_runtime_put_sync(mbox->dev->parent); 442 313 mbox->use_count--; 443 314 fail_startup: 444 - mbox_configured--; 445 315 mutex_unlock(&mbox_configured_lock); 446 316 return ret; 447 317 } ··· 457 331 mbox_queue_free(mbox->rxq); 458 332 } 459 333 460 - if (likely(mbox->ops->shutdown)) { 461 - if (!--mbox_configured) 462 - mbox->ops->shutdown(mbox); 463 - } 334 + pm_runtime_put_sync(mbox->dev->parent); 464 335 465 336 mutex_unlock(&mbox_configured_lock); 466 337 } ··· 502 379 503 380 static struct class omap_mbox_class = { .name = "mbox", }; 504 381 505 - int omap_mbox_register(struct device *parent, struct omap_mbox **list) 382 + static int omap_mbox_register(struct device *parent, struct omap_mbox **list) 506 383 { 507 384 int ret; 508 385 int i; ··· 529 406 device_unregister(mboxes[i]->dev); 530 407 return ret; 531 408 } 532 - EXPORT_SYMBOL(omap_mbox_register); 533 409 534 - int omap_mbox_unregister(void) 410 + static int omap_mbox_unregister(void) 535 411 { 536 412 int i; 537 413 ··· 542 420 mboxes = NULL; 543 421 return 0; 544 422 } 545 - EXPORT_SYMBOL(omap_mbox_unregister); 423 + 424 + static int omap_mbox_probe(struct platform_device *pdev) 425 + { 426 + struct resource *mem; 427 + int ret; 428 + struct omap_mbox **list, *mbox, *mboxblk; 429 + struct omap_mbox_priv *priv, *privblk; 430 + struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 431 + struct omap_mbox_dev_info *info; 432 + u32 intr_type; 433 + u32 l; 434 + int i; 435 + 436 + if (!pdata || !pdata->info_cnt || !pdata->info) { 437 + pr_err("%s: platform not supported\n", __func__); 438 + return -ENODEV; 439 + } 440 + 441 + /* allocate one extra for marking end of list */ 442 + list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list), 443 + GFP_KERNEL); 444 + if (!list) 445 + return -ENOMEM; 446 + 447 + mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox), 448 + GFP_KERNEL); 449 + if (!mboxblk) 450 + return -ENOMEM; 451 + 452 + privblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*priv), 453 + GFP_KERNEL); 454 + if (!privblk) 455 + return -ENOMEM; 456 + 457 + info = pdata->info; 458 + intr_type = pdata->intr_type; 459 + mbox = mboxblk; 460 + priv = privblk; 461 + for (i = 0; i < pdata->info_cnt; i++, info++, priv++) { 462 + priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id); 463 + priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); 464 + priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id); 465 + priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id); 466 + priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); 467 + priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); 468 + priv->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id); 469 + priv->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id); 470 + priv->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id); 471 + priv->intr_type = intr_type; 472 + 473 + mbox->priv = priv; 474 + mbox->name = info->name; 475 + mbox->irq = platform_get_irq(pdev, info->irq_id); 476 + if (mbox->irq < 0) 477 + return mbox->irq; 478 + list[i] = mbox++; 479 + } 480 + 481 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 482 + mbox_base = devm_ioremap_resource(&pdev->dev, mem); 483 + if (IS_ERR(mbox_base)) 484 + return PTR_ERR(mbox_base); 485 + 486 + ret = omap_mbox_register(&pdev->dev, list); 487 + if (ret) 488 + return ret; 489 + 490 + platform_set_drvdata(pdev, list); 491 + pm_runtime_enable(&pdev->dev); 492 + 493 + ret = pm_runtime_get_sync(&pdev->dev); 494 + if (ret < 0) { 495 + pm_runtime_put_noidle(&pdev->dev); 496 + goto unregister; 497 + } 498 + 499 + /* 500 + * just print the raw revision register, the format is not 501 + * uniform across all SoCs 502 + */ 503 + l = mbox_read_reg(MAILBOX_REVISION); 504 + dev_info(&pdev->dev, "omap mailbox rev 0x%x\n", l); 505 + 506 + ret = pm_runtime_put_sync(&pdev->dev); 507 + if (ret < 0) 508 + goto unregister; 509 + 510 + return 0; 511 + 512 + unregister: 513 + pm_runtime_disable(&pdev->dev); 514 + omap_mbox_unregister(); 515 + return ret; 516 + } 517 + 518 + static int omap_mbox_remove(struct platform_device *pdev) 519 + { 520 + pm_runtime_disable(&pdev->dev); 521 + omap_mbox_unregister(); 522 + 523 + return 0; 524 + } 525 + 526 + static struct platform_driver omap_mbox_driver = { 527 + .probe = omap_mbox_probe, 528 + .remove = omap_mbox_remove, 529 + .driver = { 530 + .name = "omap-mailbox", 531 + .owner = THIS_MODULE, 532 + }, 533 + }; 546 534 547 535 static int __init omap_mbox_init(void) 548 536 { ··· 667 435 mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, 668 436 sizeof(mbox_msg_t)); 669 437 670 - return 0; 438 + return platform_driver_register(&omap_mbox_driver); 671 439 } 672 440 subsys_initcall(omap_mbox_init); 673 441 674 442 static void __exit omap_mbox_exit(void) 675 443 { 444 + platform_driver_unregister(&omap_mbox_driver); 676 445 class_unregister(&omap_mbox_class); 677 446 } 678 447 module_exit(omap_mbox_exit);
-62
drivers/mailbox/omap-mbox.h
··· 1 - /* 2 - * omap-mbox.h: OMAP mailbox internal definitions 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - 9 - #ifndef OMAP_MBOX_H 10 - #define OMAP_MBOX_H 11 - 12 - #include <linux/device.h> 13 - #include <linux/interrupt.h> 14 - #include <linux/kfifo.h> 15 - #include <linux/spinlock.h> 16 - #include <linux/workqueue.h> 17 - #include <linux/omap-mailbox.h> 18 - 19 - struct omap_mbox_ops { 20 - int (*startup)(struct omap_mbox *mbox); 21 - void (*shutdown)(struct omap_mbox *mbox); 22 - /* fifo */ 23 - mbox_msg_t (*fifo_read)(struct omap_mbox *mbox); 24 - void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg); 25 - int (*fifo_empty)(struct omap_mbox *mbox); 26 - int (*fifo_full)(struct omap_mbox *mbox); 27 - /* irq */ 28 - void (*enable_irq)(struct omap_mbox *mbox, 29 - omap_mbox_irq_t irq); 30 - void (*disable_irq)(struct omap_mbox *mbox, 31 - omap_mbox_irq_t irq); 32 - void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); 33 - int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); 34 - /* ctx */ 35 - void (*save_ctx)(struct omap_mbox *mbox); 36 - void (*restore_ctx)(struct omap_mbox *mbox); 37 - }; 38 - 39 - struct omap_mbox_queue { 40 - spinlock_t lock; 41 - struct kfifo fifo; 42 - struct work_struct work; 43 - struct tasklet_struct tasklet; 44 - struct omap_mbox *mbox; 45 - bool full; 46 - }; 47 - 48 - struct omap_mbox { 49 - const char *name; 50 - int irq; 51 - struct omap_mbox_queue *txq, *rxq; 52 - struct omap_mbox_ops *ops; 53 - struct device *dev; 54 - void *priv; 55 - int use_count; 56 - struct blocking_notifier_head notifier; 57 - }; 58 - 59 - int omap_mbox_register(struct device *parent, struct omap_mbox **); 60 - int omap_mbox_unregister(void); 61 - 62 - #endif /* OMAP_MBOX_H */