Ohad Ben-Cohen | 400e64d | 2011-10-20 16:52:46 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Remote Processor Framework |
| 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 REMOTEPROC_H |
| 36 | #define REMOTEPROC_H |
| 37 | |
| 38 | #include <linux/types.h> |
| 39 | #include <linux/kref.h> |
| 40 | #include <linux/klist.h> |
| 41 | #include <linux/mutex.h> |
| 42 | #include <linux/virtio.h> |
| 43 | #include <linux/completion.h> |
| 44 | |
| 45 | /* |
| 46 | * The alignment between the consumer and producer parts of the vring. |
| 47 | * Note: this is part of the "wire" protocol. If you change this, you need |
| 48 | * to update your peers too. |
| 49 | */ |
| 50 | #define AMP_VRING_ALIGN (4096) |
| 51 | |
| 52 | /** |
| 53 | * struct fw_resource - describes an entry from the resource section |
| 54 | * @type: resource type |
| 55 | * @id: index number of the resource |
| 56 | * @da: device address of the resource |
| 57 | * @pa: physical address of the resource |
| 58 | * @len: size, in bytes, of the resource |
| 59 | * @flags: properties of the resource, e.g. iommu protection required |
| 60 | * @reserved: must be 0 atm |
| 61 | * @name: name of resource |
| 62 | * |
| 63 | * The remote processor firmware should contain a "resource table": |
| 64 | * array of 'struct fw_resource' entries. |
| 65 | * |
| 66 | * Some resources entries are mere announcements, where the host is informed |
| 67 | * of specific remoteproc configuration. Other entries require the host to |
| 68 | * do something (e.g. reserve a requested resource) and possibly also reply |
| 69 | * by overwriting a member inside 'struct fw_resource' with info about the |
| 70 | * allocated resource. |
| 71 | * |
| 72 | * Different resource entries use different members of this struct, |
| 73 | * with different meanings. This is pretty limiting and error-prone, |
| 74 | * so the plan is to move to variable-length TLV-based resource entries, |
| 75 | * where each resource type will have its own structure. |
| 76 | */ |
| 77 | struct fw_resource { |
| 78 | u32 type; |
| 79 | u32 id; |
| 80 | u64 da; |
| 81 | u64 pa; |
| 82 | u32 len; |
| 83 | u32 flags; |
| 84 | u8 reserved[16]; |
| 85 | u8 name[48]; |
| 86 | } __packed; |
| 87 | |
| 88 | /** |
| 89 | * enum fw_resource_type - types of resource entries |
| 90 | * |
| 91 | * @RSC_CARVEOUT: request for allocation of a physically contiguous |
| 92 | * memory region. |
| 93 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. |
| 94 | * @RSC_TRACE: announces the availability of a trace buffer into which |
| 95 | * the remote processor will be writing logs. In this case, |
| 96 | * 'da' indicates the device address where logs are written to, |
| 97 | * and 'len' is the size of the trace buffer. |
| 98 | * @RSC_VRING: request for allocation of a virtio vring (address should |
| 99 | * be indicated in 'da', and 'len' should contain the number |
| 100 | * of buffers supported by the vring). |
| 101 | * @RSC_VIRTIO_DEV: this entry declares about support for a virtio device, |
| 102 | * and serves as the virtio header. 'da' holds the |
| 103 | * the virtio device features, 'pa' holds the virtio guest |
| 104 | * features, 'len' holds the virtio status, and 'flags' holds |
| 105 | * the virtio id (currently only VIRTIO_ID_RPMSG is supported). |
Ohad Ben-Cohen | e12bc14 | 2012-01-31 16:07:27 +0200 | [diff] [blame^] | 106 | * @RSC_LAST: just keep this one at the end |
Ohad Ben-Cohen | 400e64d | 2011-10-20 16:52:46 +0200 | [diff] [blame] | 107 | * |
| 108 | * Most of the resource entries share the basic idea of address/length |
| 109 | * negotiation with the host: the firmware usually asks (on behalf of the |
| 110 | * remote processor that will soon be booted with it) for memory |
| 111 | * of size 'len' bytes, and the host needs to allocate it and provide |
| 112 | * the device/physical address (when relevant) in 'da'/'pa' respectively. |
| 113 | * |
| 114 | * If the firmware is compiled with hard coded device addresses, and |
| 115 | * can't handle dynamically allocated 'da' values, then the 'da' field |
| 116 | * will contain the expected device addresses (today we actually only support |
| 117 | * this scheme, as there aren't yet any use cases for dynamically allocated |
| 118 | * device addresses). |
Ohad Ben-Cohen | e12bc14 | 2012-01-31 16:07:27 +0200 | [diff] [blame^] | 119 | * |
| 120 | * Please note that these values are used as indices to the rproc_handle_rsc |
| 121 | * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to |
| 122 | * check the validity of an index before the lookup table is accessed, so |
| 123 | * please update it as needed. |
Ohad Ben-Cohen | 400e64d | 2011-10-20 16:52:46 +0200 | [diff] [blame] | 124 | */ |
| 125 | enum fw_resource_type { |
| 126 | RSC_CARVEOUT = 0, |
| 127 | RSC_DEVMEM = 1, |
| 128 | RSC_TRACE = 2, |
| 129 | RSC_VRING = 3, |
| 130 | RSC_VIRTIO_DEV = 4, |
Ohad Ben-Cohen | e12bc14 | 2012-01-31 16:07:27 +0200 | [diff] [blame^] | 131 | RSC_LAST = 5, |
Ohad Ben-Cohen | 400e64d | 2011-10-20 16:52:46 +0200 | [diff] [blame] | 132 | }; |
| 133 | |
| 134 | /** |
| 135 | * struct rproc_mem_entry - memory entry descriptor |
| 136 | * @va: virtual address |
| 137 | * @dma: dma address |
| 138 | * @len: length, in bytes |
| 139 | * @da: device address |
| 140 | * @priv: associated data |
| 141 | * @node: list node |
| 142 | */ |
| 143 | struct rproc_mem_entry { |
| 144 | void *va; |
| 145 | dma_addr_t dma; |
| 146 | int len; |
| 147 | u64 da; |
| 148 | void *priv; |
| 149 | struct list_head node; |
| 150 | }; |
| 151 | |
| 152 | struct rproc; |
| 153 | |
| 154 | /** |
| 155 | * struct rproc_ops - platform-specific device handlers |
| 156 | * @start: power on the device and boot it |
| 157 | * @stop: power off the device |
| 158 | * @kick: kick a virtqueue (virtqueue id given as a parameter) |
| 159 | */ |
| 160 | struct rproc_ops { |
| 161 | int (*start)(struct rproc *rproc); |
| 162 | int (*stop)(struct rproc *rproc); |
| 163 | void (*kick)(struct rproc *rproc, int vqid); |
| 164 | }; |
| 165 | |
| 166 | /** |
| 167 | * enum rproc_state - remote processor states |
| 168 | * @RPROC_OFFLINE: device is powered off |
| 169 | * @RPROC_SUSPENDED: device is suspended; needs to be woken up to receive |
| 170 | * a message. |
| 171 | * @RPROC_RUNNING: device is up and running |
| 172 | * @RPROC_CRASHED: device has crashed; need to start recovery |
| 173 | * @RPROC_LAST: just keep this one at the end |
| 174 | * |
| 175 | * Please note that the values of these states are used as indices |
| 176 | * to rproc_state_string, a state-to-name lookup table, |
| 177 | * so please keep the two synchronized. @RPROC_LAST is used to check |
| 178 | * the validity of an index before the lookup table is accessed, so |
| 179 | * please update it as needed too. |
| 180 | */ |
| 181 | enum rproc_state { |
| 182 | RPROC_OFFLINE = 0, |
| 183 | RPROC_SUSPENDED = 1, |
| 184 | RPROC_RUNNING = 2, |
| 185 | RPROC_CRASHED = 3, |
| 186 | RPROC_LAST = 4, |
| 187 | }; |
| 188 | |
| 189 | /** |
| 190 | * struct rproc - represents a physical remote processor device |
| 191 | * @node: klist node of this rproc object |
| 192 | * @domain: iommu domain |
| 193 | * @name: human readable name of the rproc |
| 194 | * @firmware: name of firmware file to be loaded |
| 195 | * @priv: private data which belongs to the platform-specific rproc module |
| 196 | * @ops: platform-specific start/stop rproc handlers |
| 197 | * @dev: underlying device |
| 198 | * @refcount: refcount of users that have a valid pointer to this rproc |
| 199 | * @power: refcount of users who need this rproc powered up |
| 200 | * @state: state of the device |
| 201 | * @lock: lock which protects concurrent manipulations of the rproc |
| 202 | * @dbg_dir: debugfs directory of this rproc device |
| 203 | * @traces: list of trace buffers |
| 204 | * @num_traces: number of trace buffers |
| 205 | * @carveouts: list of physically contiguous memory allocations |
| 206 | * @mappings: list of iommu mappings we initiated, needed on shutdown |
| 207 | * @firmware_loading_complete: marks e/o asynchronous firmware loading |
| 208 | * @bootaddr: address of first instruction to boot rproc with (optional) |
| 209 | * @rvdev: virtio device (we only support a single rpmsg virtio device for now) |
| 210 | */ |
| 211 | struct rproc { |
| 212 | struct klist_node node; |
| 213 | struct iommu_domain *domain; |
| 214 | const char *name; |
| 215 | const char *firmware; |
| 216 | void *priv; |
| 217 | const struct rproc_ops *ops; |
| 218 | struct device *dev; |
| 219 | struct kref refcount; |
| 220 | atomic_t power; |
| 221 | unsigned int state; |
| 222 | struct mutex lock; |
| 223 | struct dentry *dbg_dir; |
| 224 | struct list_head traces; |
| 225 | int num_traces; |
| 226 | struct list_head carveouts; |
| 227 | struct list_head mappings; |
| 228 | struct completion firmware_loading_complete; |
| 229 | u64 bootaddr; |
| 230 | struct rproc_vdev *rvdev; |
| 231 | }; |
| 232 | |
| 233 | /** |
| 234 | * struct rproc_vdev - remoteproc state for a supported virtio device |
| 235 | * @rproc: the rproc handle |
| 236 | * @vdev: the virio device |
| 237 | * @vq: the virtqueues for this vdev |
| 238 | * @vring: the vrings for this vdev |
| 239 | * @dfeatures: virtio device features |
| 240 | * @gfeatures: virtio guest features |
| 241 | */ |
| 242 | struct rproc_vdev { |
| 243 | struct rproc *rproc; |
| 244 | struct virtio_device vdev; |
| 245 | struct virtqueue *vq[2]; |
| 246 | struct rproc_mem_entry vring[2]; |
| 247 | unsigned long dfeatures; |
| 248 | unsigned long gfeatures; |
| 249 | }; |
| 250 | |
| 251 | struct rproc *rproc_get_by_name(const char *name); |
| 252 | void rproc_put(struct rproc *rproc); |
| 253 | |
| 254 | struct rproc *rproc_alloc(struct device *dev, const char *name, |
| 255 | const struct rproc_ops *ops, |
| 256 | const char *firmware, int len); |
| 257 | void rproc_free(struct rproc *rproc); |
| 258 | int rproc_register(struct rproc *rproc); |
| 259 | int rproc_unregister(struct rproc *rproc); |
| 260 | |
| 261 | int rproc_boot(struct rproc *rproc); |
| 262 | void rproc_shutdown(struct rproc *rproc); |
| 263 | |
| 264 | static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) |
| 265 | { |
| 266 | struct rproc_vdev *rvdev = container_of(vdev, struct rproc_vdev, vdev); |
| 267 | |
| 268 | return rvdev->rproc; |
| 269 | } |
| 270 | |
| 271 | #endif /* REMOTEPROC_H */ |