| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* |
| 3 | * Copyright (c) 2022, Linaro Ltd. |
| 4 | * |
| 5 | */ |
| 6 | #ifndef _MHI_EP_H_ |
| 7 | #define _MHI_EP_H_ |
| 8 | |
| 9 | #include <linux/dma-direction.h> |
| 10 | #include <linux/mhi.h> |
| 11 | |
| 12 | #define MHI_EP_DEFAULT_MTU 0x8000 |
| 13 | |
| 14 | /** |
| 15 | * struct mhi_ep_channel_config - Channel configuration structure for controller |
| 16 | * @name: The name of this channel |
| 17 | * @num: The number assigned to this channel |
| 18 | * @num_elements: The number of elements that can be queued to this channel |
| 19 | * @dir: Direction that data may flow on this channel |
| 20 | */ |
| 21 | struct mhi_ep_channel_config { |
| 22 | char *name; |
| 23 | u32 num; |
| 24 | u32 num_elements; |
| 25 | enum dma_data_direction dir; |
| 26 | }; |
| 27 | |
| 28 | /** |
| 29 | * struct mhi_ep_cntrl_config - MHI Endpoint controller configuration |
| 30 | * @mhi_version: MHI spec version supported by the controller |
| 31 | * @max_channels: Maximum number of channels supported |
| 32 | * @num_channels: Number of channels defined in @ch_cfg |
| 33 | * @ch_cfg: Array of defined channels |
| 34 | */ |
| 35 | struct mhi_ep_cntrl_config { |
| 36 | u32 mhi_version; |
| 37 | u32 max_channels; |
| 38 | u32 num_channels; |
| 39 | const struct mhi_ep_channel_config *ch_cfg; |
| 40 | }; |
| 41 | |
| 42 | /** |
| 43 | * struct mhi_ep_db_info - MHI Endpoint doorbell info |
| 44 | * @mask: Mask of the doorbell interrupt |
| 45 | * @status: Status of the doorbell interrupt |
| 46 | */ |
| 47 | struct mhi_ep_db_info { |
| 48 | u32 mask; |
| 49 | u32 status; |
| 50 | }; |
| 51 | |
| 52 | /** |
| 53 | * struct mhi_ep_buf_info - MHI Endpoint transfer buffer info |
| 54 | * @mhi_dev: MHI device associated with this buffer |
| 55 | * @dev_addr: Address of the buffer in endpoint |
| 56 | * @host_addr: Address of the bufffer in host |
| 57 | * @size: Size of the buffer |
| 58 | * @code: Transfer completion code |
| 59 | * @cb: Callback to be executed by controller drivers after transfer completion (async) |
| 60 | * @cb_buf: Opaque buffer to be passed to the callback |
| 61 | */ |
| 62 | struct mhi_ep_buf_info { |
| 63 | struct mhi_ep_device *mhi_dev; |
| 64 | void *dev_addr; |
| 65 | u64 host_addr; |
| 66 | size_t size; |
| 67 | int code; |
| 68 | |
| 69 | void (*cb)(struct mhi_ep_buf_info *buf_info); |
| 70 | void *cb_buf; |
| 71 | }; |
| 72 | |
| 73 | /** |
| 74 | * struct mhi_ep_cntrl - MHI Endpoint controller structure |
| 75 | * @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI |
| 76 | * Endpoint controller |
| 77 | * @mhi_dev: MHI Endpoint device instance for the controller |
| 78 | * @mmio: MMIO region containing the MHI registers |
| 79 | * @mhi_chan: Points to the channel configuration table |
| 80 | * @mhi_event: Points to the event ring configurations table |
| 81 | * @mhi_cmd: Points to the command ring configurations table |
| 82 | * @sm: MHI Endpoint state machine |
| 83 | * @ch_ctx_cache: Cache of host channel context data structure |
| 84 | * @ev_ctx_cache: Cache of host event context data structure |
| 85 | * @cmd_ctx_cache: Cache of host command context data structure |
| 86 | * @ch_ctx_host_pa: Physical address of host channel context data structure |
| 87 | * @ev_ctx_host_pa: Physical address of host event context data structure |
| 88 | * @cmd_ctx_host_pa: Physical address of host command context data structure |
| 89 | * @ch_ctx_cache_phys: Physical address of the host channel context cache |
| 90 | * @ev_ctx_cache_phys: Physical address of the host event context cache |
| 91 | * @cmd_ctx_cache_phys: Physical address of the host command context cache |
| 92 | * @chdb: Array of channel doorbell interrupt info |
| 93 | * @event_lock: Lock for protecting event rings |
| 94 | * @state_lock: Lock for protecting state transitions |
| 95 | * @list_lock: Lock for protecting state transition and channel doorbell lists |
| 96 | * @st_transition_list: List of state transitions |
| 97 | * @ch_db_list: List of queued channel doorbells |
| 98 | * @wq: Dedicated workqueue for handling rings and state changes |
| 99 | * @state_work: State transition worker |
| 100 | * @reset_work: Worker for MHI Endpoint reset |
| 101 | * @cmd_ring_work: Worker for processing command rings |
| 102 | * @ch_ring_work: Worker for processing channel rings |
| 103 | * @raise_irq: CB function for raising IRQ to the host |
| 104 | * @alloc_map: CB function for allocating memory in endpoint for storing host context and mapping it |
| 105 | * @unmap_free: CB function to unmap and free the allocated memory in endpoint for storing host context |
| 106 | * @read_sync: CB function for reading from host memory synchronously |
| 107 | * @write_sync: CB function for writing to host memory synchronously |
| 108 | * @read_async: CB function for reading from host memory asynchronously |
| 109 | * @write_async: CB function for writing to host memory asynchronously |
| 110 | * @mhi_state: MHI Endpoint state |
| 111 | * @max_chan: Maximum channels supported by the endpoint controller |
| 112 | * @mru: MRU (Maximum Receive Unit) value of the endpoint controller |
| 113 | * @event_rings: Number of event rings supported by the endpoint controller |
| 114 | * @hw_event_rings: Number of hardware event rings supported by the endpoint controller |
| 115 | * @chdb_offset: Channel doorbell offset set by the host |
| 116 | * @erdb_offset: Event ring doorbell offset set by the host |
| 117 | * @index: MHI Endpoint controller index |
| 118 | * @irq: IRQ used by the endpoint controller |
| 119 | * @enabled: Check if the endpoint controller is enabled or not |
| 120 | */ |
| 121 | struct mhi_ep_cntrl { |
| 122 | struct device *cntrl_dev; |
| 123 | struct mhi_ep_device *mhi_dev; |
| 124 | void __iomem *mmio; |
| 125 | |
| 126 | struct mhi_ep_chan *mhi_chan; |
| 127 | struct mhi_ep_event *mhi_event; |
| 128 | struct mhi_ep_cmd *mhi_cmd; |
| 129 | struct mhi_ep_sm *sm; |
| 130 | |
| 131 | struct mhi_chan_ctxt *ch_ctx_cache; |
| 132 | struct mhi_event_ctxt *ev_ctx_cache; |
| 133 | struct mhi_cmd_ctxt *cmd_ctx_cache; |
| 134 | u64 ch_ctx_host_pa; |
| 135 | u64 ev_ctx_host_pa; |
| 136 | u64 cmd_ctx_host_pa; |
| 137 | phys_addr_t ch_ctx_cache_phys; |
| 138 | phys_addr_t ev_ctx_cache_phys; |
| 139 | phys_addr_t cmd_ctx_cache_phys; |
| 140 | |
| 141 | struct mhi_ep_db_info chdb[4]; |
| 142 | struct mutex event_lock; |
| 143 | struct mutex state_lock; |
| 144 | spinlock_t list_lock; |
| 145 | |
| 146 | struct list_head st_transition_list; |
| 147 | struct list_head ch_db_list; |
| 148 | |
| 149 | struct workqueue_struct *wq; |
| 150 | struct work_struct state_work; |
| 151 | struct work_struct reset_work; |
| 152 | struct work_struct cmd_ring_work; |
| 153 | struct work_struct ch_ring_work; |
| 154 | struct kmem_cache *ring_item_cache; |
| 155 | struct kmem_cache *ev_ring_el_cache; |
| 156 | struct kmem_cache *tre_buf_cache; |
| 157 | |
| 158 | void (*raise_irq)(struct mhi_ep_cntrl *mhi_cntrl, u32 vector); |
| 159 | int (*alloc_map)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t *phys_ptr, |
| 160 | void __iomem **virt, size_t size); |
| 161 | void (*unmap_free)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t phys, |
| 162 | void __iomem *virt, size_t size); |
| 163 | int (*read_sync)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); |
| 164 | int (*write_sync)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); |
| 165 | int (*read_async)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); |
| 166 | int (*write_async)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); |
| 167 | |
| 168 | enum mhi_state mhi_state; |
| 169 | |
| 170 | u32 max_chan; |
| 171 | u32 mru; |
| 172 | u32 event_rings; |
| 173 | u32 hw_event_rings; |
| 174 | u32 chdb_offset; |
| 175 | u32 erdb_offset; |
| 176 | u32 index; |
| 177 | int irq; |
| 178 | bool enabled; |
| 179 | }; |
| 180 | |
| 181 | /** |
| 182 | * struct mhi_ep_device - Structure representing an MHI Endpoint device that binds |
| 183 | * to channels or is associated with controllers |
| 184 | * @dev: Driver model device node for the MHI Endpoint device |
| 185 | * @mhi_cntrl: Controller the device belongs to |
| 186 | * @id: Pointer to MHI Endpoint device ID struct |
| 187 | * @name: Name of the associated MHI Endpoint device |
| 188 | * @ul_chan: UL (from host to endpoint) channel for the device |
| 189 | * @dl_chan: DL (from endpoint to host) channel for the device |
| 190 | * @dev_type: MHI device type |
| 191 | */ |
| 192 | struct mhi_ep_device { |
| 193 | struct device dev; |
| 194 | struct mhi_ep_cntrl *mhi_cntrl; |
| 195 | const struct mhi_device_id *id; |
| 196 | const char *name; |
| 197 | struct mhi_ep_chan *ul_chan; |
| 198 | struct mhi_ep_chan *dl_chan; |
| 199 | enum mhi_device_type dev_type; |
| 200 | }; |
| 201 | |
| 202 | /** |
| 203 | * struct mhi_ep_driver - Structure representing a MHI Endpoint client driver |
| 204 | * @id_table: Pointer to MHI Endpoint device ID table |
| 205 | * @driver: Device driver model driver |
| 206 | * @probe: CB function for client driver probe function |
| 207 | * @remove: CB function for client driver remove function |
| 208 | * @ul_xfer_cb: CB function for UL (from host to endpoint) data transfer |
| 209 | * @dl_xfer_cb: CB function for DL (from endpoint to host) data transfer |
| 210 | */ |
| 211 | struct mhi_ep_driver { |
| 212 | const struct mhi_device_id *id_table; |
| 213 | struct device_driver driver; |
| 214 | int (*probe)(struct mhi_ep_device *mhi_ep, |
| 215 | const struct mhi_device_id *id); |
| 216 | void (*remove)(struct mhi_ep_device *mhi_ep); |
| 217 | void (*ul_xfer_cb)(struct mhi_ep_device *mhi_dev, |
| 218 | struct mhi_result *result); |
| 219 | void (*dl_xfer_cb)(struct mhi_ep_device *mhi_dev, |
| 220 | struct mhi_result *result); |
| 221 | }; |
| 222 | |
| 223 | #define to_mhi_ep_device(dev) container_of(dev, struct mhi_ep_device, dev) |
| 224 | #define to_mhi_ep_driver(drv) container_of_const(drv, struct mhi_ep_driver, driver) |
| 225 | |
| 226 | /* |
| 227 | * module_mhi_ep_driver() - Helper macro for drivers that don't do |
| 228 | * anything special other than using default mhi_ep_driver_register() and |
| 229 | * mhi_ep_driver_unregister(). This eliminates a lot of boilerplate. |
| 230 | * Each module may only use this macro once. |
| 231 | */ |
| 232 | #define module_mhi_ep_driver(mhi_drv) \ |
| 233 | module_driver(mhi_drv, mhi_ep_driver_register, \ |
| 234 | mhi_ep_driver_unregister) |
| 235 | |
| 236 | /* |
| 237 | * Macro to avoid include chaining to get THIS_MODULE |
| 238 | */ |
| 239 | #define mhi_ep_driver_register(mhi_drv) \ |
| 240 | __mhi_ep_driver_register(mhi_drv, THIS_MODULE) |
| 241 | |
| 242 | /** |
| 243 | * __mhi_ep_driver_register - Register a driver with MHI Endpoint bus |
| 244 | * @mhi_drv: Driver to be associated with the device |
| 245 | * @owner: The module owner |
| 246 | * |
| 247 | * Return: 0 if driver registrations succeeds, a negative error code otherwise. |
| 248 | */ |
| 249 | int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner); |
| 250 | |
| 251 | /** |
| 252 | * mhi_ep_driver_unregister - Unregister a driver from MHI Endpoint bus |
| 253 | * @mhi_drv: Driver associated with the device |
| 254 | */ |
| 255 | void mhi_ep_driver_unregister(struct mhi_ep_driver *mhi_drv); |
| 256 | |
| 257 | /** |
| 258 | * mhi_ep_register_controller - Register MHI Endpoint controller |
| 259 | * @mhi_cntrl: MHI Endpoint controller to register |
| 260 | * @config: Configuration to use for the controller |
| 261 | * |
| 262 | * Return: 0 if controller registrations succeeds, a negative error code otherwise. |
| 263 | */ |
| 264 | int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl, |
| 265 | const struct mhi_ep_cntrl_config *config); |
| 266 | |
| 267 | /** |
| 268 | * mhi_ep_unregister_controller - Unregister MHI Endpoint controller |
| 269 | * @mhi_cntrl: MHI Endpoint controller to unregister |
| 270 | */ |
| 271 | void mhi_ep_unregister_controller(struct mhi_ep_cntrl *mhi_cntrl); |
| 272 | |
| 273 | /** |
| 274 | * mhi_ep_power_up - Power up the MHI endpoint stack |
| 275 | * @mhi_cntrl: MHI Endpoint controller |
| 276 | * |
| 277 | * Return: 0 if power up succeeds, a negative error code otherwise. |
| 278 | */ |
| 279 | int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl); |
| 280 | |
| 281 | /** |
| 282 | * mhi_ep_power_down - Power down the MHI endpoint stack |
| 283 | * @mhi_cntrl: MHI controller |
| 284 | */ |
| 285 | void mhi_ep_power_down(struct mhi_ep_cntrl *mhi_cntrl); |
| 286 | |
| 287 | /** |
| 288 | * mhi_ep_queue_is_empty - Determine whether the transfer queue is empty |
| 289 | * @mhi_dev: Device associated with the channels |
| 290 | * @dir: DMA direction for the channel |
| 291 | * |
| 292 | * Return: true if the queue is empty, false otherwise. |
| 293 | */ |
| 294 | bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_direction dir); |
| 295 | |
| 296 | /** |
| 297 | * mhi_ep_queue_skb - Send SKBs to host over MHI Endpoint |
| 298 | * @mhi_dev: Device associated with the DL channel |
| 299 | * @skb: SKBs to be queued |
| 300 | * |
| 301 | * Return: 0 if the SKBs has been sent successfully, a negative error code otherwise. |
| 302 | */ |
| 303 | int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb); |
| 304 | |
| 305 | #endif |
| 306 | |