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

remoteproc/omap: add a remoteproc driver for OMAP4

Add a remoteproc driver for OMAP4, so we can boot the dual-M3 and
and DSP subsystems.

Use the omap_device_* API to control the hardware state, and utilize
the OMAP mailbox to interrupt the remote processor when a new message
is pending (the mailbox payload is used to tell it which virtqueue was
the message placed in).

Conversely, when an inbound mailbox message arrives, tell the remoteproc
core which virtqueue is triggered.

Later we will also use the mailbox payload to signal omap-specific
events like remote crashes (which will be used to trigger remoteproc
recovery) and power management transitions. At that point we will also
extend the remoteproc core to support this.

Based on (but now quite far from) work done by Fernando Guzman Lugo
<fernando.lugo@ti.com> and Hari Kanigeri <h-kanigeri2@ti.com>.

Designed with Brian Swetland <swetland@google.com>.

Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Cc: Brian Swetland <swetland@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Greg KH <greg@kroah.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>

+397
+57
arch/arm/plat-omap/include/plat/remoteproc.h
··· 1 + /* 2 + * Remote Processor - omap-specific bits 3 + * 4 + * Copyright (C) 2011 Texas Instruments, Inc. 5 + * Copyright (C) 2011 Google, Inc. 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * version 2 as published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #ifndef _PLAT_REMOTEPROC_H 18 + #define _PLAT_REMOTEPROC_H 19 + 20 + struct rproc_ops; 21 + struct platform_device; 22 + 23 + /* 24 + * struct omap_rproc_pdata - omap remoteproc's platform data 25 + * @name: the remoteproc's name 26 + * @oh_name: omap hwmod device 27 + * @oh_name_opt: optional, secondary omap hwmod device 28 + * @firmware: name of firmware file to load 29 + * @mbox_name: name of omap mailbox device to use with this rproc 30 + * @ops: start/stop rproc handlers 31 + * @device_enable: omap-specific handler for enabling a device 32 + * @device_shutdown: omap-specific handler for shutting down a device 33 + */ 34 + struct omap_rproc_pdata { 35 + const char *name; 36 + const char *oh_name; 37 + const char *oh_name_opt; 38 + const char *firmware; 39 + const char *mbox_name; 40 + const struct rproc_ops *ops; 41 + int (*device_enable) (struct platform_device *pdev); 42 + int (*device_shutdown) (struct platform_device *pdev); 43 + }; 44 + 45 + #if defined(CONFIG_OMAP_REMOTEPROC) || defined(CONFIG_OMAP_REMOTEPROC_MODULE) 46 + 47 + void __init omap_rproc_reserve_cma(void); 48 + 49 + #else 50 + 51 + void __init omap_rproc_reserve_cma(void) 52 + { 53 + } 54 + 55 + #endif 56 + 57 + #endif /* _PLAT_REMOTEPROC_H */
+21
drivers/remoteproc/Kconfig
··· 1 1 # REMOTEPROC gets selected by whoever wants it 2 2 config REMOTEPROC 3 3 tristate 4 + 5 + config OMAP_REMOTEPROC 6 + tristate "OMAP remoteproc support" 7 + depends on ARCH_OMAP4 8 + select OMAP_IOMMU 9 + select REMOTEPROC 10 + select OMAP_MBOX_FWK 11 + select RPMSG 12 + default m 13 + help 14 + Say y here to support OMAP's remote processors (dual M3 15 + and DSP on OMAP4) via the remote processor framework. 16 + 17 + Currently only supported on OMAP4. 18 + 19 + Usually you want to say y here, in order to enable multimedia 20 + use-cases to run on your platform (multimedia codecs are 21 + offloaded to remote DSP processors using this framework). 22 + 23 + It's safe to say n here if you're not interested in multimedia 24 + offloading or just want a bare minimum kernel.
+1
drivers/remoteproc/Makefile
··· 6 6 remoteproc-y := remoteproc_core.o 7 7 remoteproc-y += remoteproc_debugfs.o 8 8 remoteproc-y += remoteproc_rpmsg.o 9 + obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
+249
drivers/remoteproc/omap_remoteproc.c
··· 1 + /* 2 + * OMAP Remote Processor driver 3 + * 4 + * Copyright (C) 2011 Texas Instruments, Inc. 5 + * Copyright (C) 2011 Google, Inc. 6 + * 7 + * Ohad Ben-Cohen <ohad@wizery.com> 8 + * Brian Swetland <swetland@google.com> 9 + * Fernando Guzman Lugo <fernando.lugo@ti.com> 10 + * Mark Grosen <mgrosen@ti.com> 11 + * Suman Anna <s-anna@ti.com> 12 + * Hari Kanigeri <h-kanigeri2@ti.com> 13 + * 14 + * This program is free software; you can redistribute it and/or 15 + * modify it under the terms of the GNU General Public License 16 + * version 2 as published by the Free Software Foundation. 17 + * 18 + * This program is distributed in the hope that it will be useful, 19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 + * GNU General Public License for more details. 22 + */ 23 + 24 + #include <linux/kernel.h> 25 + #include <linux/module.h> 26 + #include <linux/err.h> 27 + #include <linux/platform_device.h> 28 + #include <linux/dma-mapping.h> 29 + #include <linux/remoteproc.h> 30 + 31 + #include <plat/mailbox.h> 32 + #include <plat/remoteproc.h> 33 + 34 + #include "omap_remoteproc.h" 35 + #include "remoteproc_internal.h" 36 + 37 + /** 38 + * struct omap_rproc - omap remote processor state 39 + * @mbox: omap mailbox handle 40 + * @nb: notifier block that will be invoked on inbound mailbox messages 41 + * @rproc: rproc handle 42 + */ 43 + struct omap_rproc { 44 + struct omap_mbox *mbox; 45 + struct notifier_block nb; 46 + struct rproc *rproc; 47 + }; 48 + 49 + /** 50 + * omap_rproc_mbox_callback() - inbound mailbox message handler 51 + * @this: notifier block 52 + * @index: unused 53 + * @data: mailbox payload 54 + * 55 + * This handler is invoked by omap's mailbox driver whenever a mailbox 56 + * message is received. Usually, the mailbox payload simply contains 57 + * the index of the virtqueue that is kicked by the remote processor, 58 + * and we let remoteproc core handle it. 59 + * 60 + * In addition to virtqueue indices, we also have some out-of-band values 61 + * that indicates different events. Those values are deliberately very 62 + * big so they don't coincide with virtqueue indices. 63 + */ 64 + static int omap_rproc_mbox_callback(struct notifier_block *this, 65 + unsigned long index, void *data) 66 + { 67 + mbox_msg_t msg = (mbox_msg_t) data; 68 + struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); 69 + struct device *dev = oproc->rproc->dev; 70 + const char *name = oproc->rproc->name; 71 + 72 + dev_dbg(dev, "mbox msg: 0x%x\n", msg); 73 + 74 + switch (msg) { 75 + case RP_MBOX_CRASH: 76 + /* just log this for now. later, we'll also do recovery */ 77 + dev_err(dev, "omap rproc %s crashed\n", name); 78 + break; 79 + case RP_MBOX_ECHO_REPLY: 80 + dev_info(dev, "received echo reply from %s\n", name); 81 + break; 82 + default: 83 + /* ignore vq indices which are too large to be valid */ 84 + if (msg >= 2) { 85 + dev_warn(dev, "invalid mbox msg: 0x%x\n", msg); 86 + break; 87 + } 88 + 89 + /* 90 + * At this point, 'msg' contains the index of the vring 91 + * which was just triggered. 92 + */ 93 + if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) 94 + dev_dbg(dev, "no message was found in vqid %d\n", msg); 95 + } 96 + 97 + return NOTIFY_DONE; 98 + } 99 + 100 + /* kick a virtqueue */ 101 + static void omap_rproc_kick(struct rproc *rproc, int vqid) 102 + { 103 + struct omap_rproc *oproc = rproc->priv; 104 + int ret; 105 + 106 + /* send the index of the triggered virtqueue in the mailbox payload */ 107 + ret = omap_mbox_msg_send(oproc->mbox, vqid); 108 + if (ret) 109 + dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret); 110 + } 111 + 112 + /* 113 + * Power up the remote processor. 114 + * 115 + * This function will be invoked only after the firmware for this rproc 116 + * was loaded, parsed successfully, and all of its resource requirements 117 + * were met. 118 + */ 119 + static int omap_rproc_start(struct rproc *rproc) 120 + { 121 + struct omap_rproc *oproc = rproc->priv; 122 + struct platform_device *pdev = to_platform_device(rproc->dev); 123 + struct omap_rproc_pdata *pdata = pdev->dev.platform_data; 124 + int ret; 125 + 126 + oproc->nb.notifier_call = omap_rproc_mbox_callback; 127 + 128 + /* every omap rproc is assigned a mailbox instance for messaging */ 129 + oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb); 130 + if (IS_ERR(oproc->mbox)) { 131 + ret = PTR_ERR(oproc->mbox); 132 + dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); 133 + return ret; 134 + } 135 + 136 + /* 137 + * Ping the remote processor. this is only for sanity-sake; 138 + * there is no functional effect whatsoever. 139 + * 140 + * Note that the reply will _not_ arrive immediately: this message 141 + * will wait in the mailbox fifo until the remote processor is booted. 142 + */ 143 + ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); 144 + if (ret) { 145 + dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret); 146 + goto put_mbox; 147 + } 148 + 149 + ret = pdata->device_enable(pdev); 150 + if (ret) { 151 + dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret); 152 + goto put_mbox; 153 + } 154 + 155 + return 0; 156 + 157 + put_mbox: 158 + omap_mbox_put(oproc->mbox, &oproc->nb); 159 + return ret; 160 + } 161 + 162 + /* power off the remote processor */ 163 + static int omap_rproc_stop(struct rproc *rproc) 164 + { 165 + struct platform_device *pdev = to_platform_device(rproc->dev); 166 + struct omap_rproc_pdata *pdata = pdev->dev.platform_data; 167 + struct omap_rproc *oproc = rproc->priv; 168 + int ret; 169 + 170 + ret = pdata->device_shutdown(pdev); 171 + if (ret) 172 + return ret; 173 + 174 + omap_mbox_put(oproc->mbox, &oproc->nb); 175 + 176 + return 0; 177 + } 178 + 179 + static struct rproc_ops omap_rproc_ops = { 180 + .start = omap_rproc_start, 181 + .stop = omap_rproc_stop, 182 + .kick = omap_rproc_kick, 183 + }; 184 + 185 + static int __devinit omap_rproc_probe(struct platform_device *pdev) 186 + { 187 + struct omap_rproc_pdata *pdata = pdev->dev.platform_data; 188 + struct omap_rproc *oproc; 189 + struct rproc *rproc; 190 + int ret; 191 + 192 + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 193 + if (ret) { 194 + dev_err(pdev->dev.parent, "dma_set_coherent_mask: %d\n", ret); 195 + return ret; 196 + } 197 + 198 + rproc = rproc_alloc(&pdev->dev, pdata->name, &omap_rproc_ops, 199 + pdata->firmware, sizeof(*oproc)); 200 + if (!rproc) 201 + return -ENOMEM; 202 + 203 + oproc = rproc->priv; 204 + oproc->rproc = rproc; 205 + 206 + platform_set_drvdata(pdev, rproc); 207 + 208 + ret = rproc_register(rproc); 209 + if (ret) 210 + goto free_rproc; 211 + 212 + return 0; 213 + 214 + free_rproc: 215 + rproc_free(rproc); 216 + return ret; 217 + } 218 + 219 + static int __devexit omap_rproc_remove(struct platform_device *pdev) 220 + { 221 + struct rproc *rproc = platform_get_drvdata(pdev); 222 + 223 + return rproc_unregister(rproc); 224 + } 225 + 226 + static struct platform_driver omap_rproc_driver = { 227 + .probe = omap_rproc_probe, 228 + .remove = __devexit_p(omap_rproc_remove), 229 + .driver = { 230 + .name = "omap-rproc", 231 + .owner = THIS_MODULE, 232 + }, 233 + }; 234 + 235 + /* most of the below will go when module_platform_driver is merged */ 236 + static int __init omap_rproc_init(void) 237 + { 238 + return platform_driver_register(&omap_rproc_driver); 239 + } 240 + module_init(omap_rproc_init); 241 + 242 + static void __exit omap_rproc_exit(void) 243 + { 244 + platform_driver_unregister(&omap_rproc_driver); 245 + } 246 + module_exit(omap_rproc_exit); 247 + 248 + MODULE_LICENSE("GPL v2"); 249 + MODULE_DESCRIPTION("OMAP Remote Processor control driver");
+69
drivers/remoteproc/omap_remoteproc.h
··· 1 + /* 2 + * Remote processor messaging 3 + * 4 + * Copyright (C) 2011 Texas Instruments, Inc. 5 + * Copyright (C) 2011 Google, Inc. 6 + * All rights reserved. 7 + * 8 + * Redistribution and use in source and binary forms, with or without 9 + * modification, are permitted provided that the following conditions 10 + * are met: 11 + * 12 + * * Redistributions of source code must retain the above copyright 13 + * notice, this list of conditions and the following disclaimer. 14 + * * Redistributions in binary form must reproduce the above copyright 15 + * notice, this list of conditions and the following disclaimer in 16 + * the documentation and/or other materials provided with the 17 + * distribution. 18 + * * Neither the name Texas Instruments nor the names of its 19 + * contributors may be used to endorse or promote products derived 20 + * from this software without specific prior written permission. 21 + * 22 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 + */ 34 + 35 + #ifndef _OMAP_RPMSG_H 36 + #define _OMAP_RPMSG_H 37 + 38 + /* 39 + * enum - Predefined Mailbox Messages 40 + * 41 + * @RP_MBOX_READY: informs the M3's that we're up and running. this is 42 + * part of the init sequence sent that the M3 expects to see immediately 43 + * after it is booted. 44 + * 45 + * @RP_MBOX_PENDING_MSG: informs the receiver that there is an inbound 46 + * message waiting in its own receive-side vring. please note that currently 47 + * this message is optional: alternatively, one can explicitly send the index 48 + * of the triggered virtqueue itself. the preferred approach will be decided 49 + * as we progress and experiment with those two different approaches. 50 + * 51 + * @RP_MBOX_CRASH: this message is sent if BIOS crashes 52 + * 53 + * @RP_MBOX_ECHO_REQUEST: a mailbox-level "ping" message. 54 + * 55 + * @RP_MBOX_ECHO_REPLY: a mailbox-level reply to a "ping" 56 + * 57 + * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the 58 + * recovery mechanism (to some extent). 59 + */ 60 + enum omap_rp_mbox_messages { 61 + RP_MBOX_READY = 0xFFFFFF00, 62 + RP_MBOX_PENDING_MSG = 0xFFFFFF01, 63 + RP_MBOX_CRASH = 0xFFFFFF02, 64 + RP_MBOX_ECHO_REQUEST = 0xFFFFFF03, 65 + RP_MBOX_ECHO_REPLY = 0xFFFFFF04, 66 + RP_MBOX_ABORT_REQUEST = 0xFFFFFF05, 67 + }; 68 + 69 + #endif /* _OMAP_RPMSG_H */