| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * Copyright (c) 2022, Linaro Ltd. | |
| * | |
| */ | |
| #ifndef _MHI_EP_H_ | |
| #define _MHI_EP_H_ | |
| #include <linux/dma-direction.h> | |
| #include <linux/mhi.h> | |
| #define MHI_EP_DEFAULT_MTU 0x8000 | |
| /** | |
| * struct mhi_ep_channel_config - Channel configuration structure for controller | |
| * @name: The name of this channel | |
| * @num: The number assigned to this channel | |
| * @num_elements: The number of elements that can be queued to this channel | |
| * @dir: Direction that data may flow on this channel | |
| */ | |
| struct mhi_ep_channel_config { | |
| char *name; | |
| u32 num; | |
| u32 num_elements; | |
| enum dma_data_direction dir; | |
| }; | |
| /** | |
| * struct mhi_ep_cntrl_config - MHI Endpoint controller configuration | |
| * @mhi_version: MHI spec version supported by the controller | |
| * @max_channels: Maximum number of channels supported | |
| * @num_channels: Number of channels defined in @ch_cfg | |
| * @ch_cfg: Array of defined channels | |
| */ | |
| struct mhi_ep_cntrl_config { | |
| u32 mhi_version; | |
| u32 max_channels; | |
| u32 num_channels; | |
| const struct mhi_ep_channel_config *ch_cfg; | |
| }; | |
| /** | |
| * struct mhi_ep_db_info - MHI Endpoint doorbell info | |
| * @mask: Mask of the doorbell interrupt | |
| * @status: Status of the doorbell interrupt | |
| */ | |
| struct mhi_ep_db_info { | |
| u32 mask; | |
| u32 status; | |
| }; | |
| /** | |
| * struct mhi_ep_buf_info - MHI Endpoint transfer buffer info | |
| * @mhi_dev: MHI device associated with this buffer | |
| * @dev_addr: Address of the buffer in endpoint | |
| * @host_addr: Address of the bufffer in host | |
| * @size: Size of the buffer | |
| * @code: Transfer completion code | |
| * @cb: Callback to be executed by controller drivers after transfer completion (async) | |
| * @cb_buf: Opaque buffer to be passed to the callback | |
| */ | |
| struct mhi_ep_buf_info { | |
| struct mhi_ep_device *mhi_dev; | |
| void *dev_addr; | |
| u64 host_addr; | |
| size_t size; | |
| int code; | |
| void (*cb)(struct mhi_ep_buf_info *buf_info); | |
| void *cb_buf; | |
| }; | |
| /** | |
| * struct mhi_ep_cntrl - MHI Endpoint controller structure | |
| * @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI | |
| * Endpoint controller | |
| * @mhi_dev: MHI Endpoint device instance for the controller | |
| * @mmio: MMIO region containing the MHI registers | |
| * @mhi_chan: Points to the channel configuration table | |
| * @mhi_event: Points to the event ring configurations table | |
| * @mhi_cmd: Points to the command ring configurations table | |
| * @sm: MHI Endpoint state machine | |
| * @ch_ctx_cache: Cache of host channel context data structure | |
| * @ev_ctx_cache: Cache of host event context data structure | |
| * @cmd_ctx_cache: Cache of host command context data structure | |
| * @ch_ctx_host_pa: Physical address of host channel context data structure | |
| * @ev_ctx_host_pa: Physical address of host event context data structure | |
| * @cmd_ctx_host_pa: Physical address of host command context data structure | |
| * @ch_ctx_cache_phys: Physical address of the host channel context cache | |
| * @ev_ctx_cache_phys: Physical address of the host event context cache | |
| * @cmd_ctx_cache_phys: Physical address of the host command context cache | |
| * @chdb: Array of channel doorbell interrupt info | |
| * @event_lock: Lock for protecting event rings | |
| * @state_lock: Lock for protecting state transitions | |
| * @list_lock: Lock for protecting state transition and channel doorbell lists | |
| * @st_transition_list: List of state transitions | |
| * @ch_db_list: List of queued channel doorbells | |
| * @wq: Dedicated workqueue for handling rings and state changes | |
| * @state_work: State transition worker | |
| * @reset_work: Worker for MHI Endpoint reset | |
| * @cmd_ring_work: Worker for processing command rings | |
| * @ch_ring_work: Worker for processing channel rings | |
| * @raise_irq: CB function for raising IRQ to the host | |
| * @alloc_map: CB function for allocating memory in endpoint for storing host context and mapping it | |
| * @unmap_free: CB function to unmap and free the allocated memory in endpoint for storing host context | |
| * @read_sync: CB function for reading from host memory synchronously | |
| * @write_sync: CB function for writing to host memory synchronously | |
| * @read_async: CB function for reading from host memory asynchronously | |
| * @write_async: CB function for writing to host memory asynchronously | |
| * @mhi_state: MHI Endpoint state | |
| * @max_chan: Maximum channels supported by the endpoint controller | |
| * @mru: MRU (Maximum Receive Unit) value of the endpoint controller | |
| * @event_rings: Number of event rings supported by the endpoint controller | |
| * @hw_event_rings: Number of hardware event rings supported by the endpoint controller | |
| * @chdb_offset: Channel doorbell offset set by the host | |
| * @erdb_offset: Event ring doorbell offset set by the host | |
| * @index: MHI Endpoint controller index | |
| * @irq: IRQ used by the endpoint controller | |
| * @enabled: Check if the endpoint controller is enabled or not | |
| */ | |
| struct mhi_ep_cntrl { | |
| struct device *cntrl_dev; | |
| struct mhi_ep_device *mhi_dev; | |
| void __iomem *mmio; | |
| struct mhi_ep_chan *mhi_chan; | |
| struct mhi_ep_event *mhi_event; | |
| struct mhi_ep_cmd *mhi_cmd; | |
| struct mhi_ep_sm *sm; | |
| struct mhi_chan_ctxt *ch_ctx_cache; | |
| struct mhi_event_ctxt *ev_ctx_cache; | |
| struct mhi_cmd_ctxt *cmd_ctx_cache; | |
| u64 ch_ctx_host_pa; | |
| u64 ev_ctx_host_pa; | |
| u64 cmd_ctx_host_pa; | |
| phys_addr_t ch_ctx_cache_phys; | |
| phys_addr_t ev_ctx_cache_phys; | |
| phys_addr_t cmd_ctx_cache_phys; | |
| struct mhi_ep_db_info chdb[4]; | |
| struct mutex event_lock; | |
| struct mutex state_lock; | |
| spinlock_t list_lock; | |
| struct list_head st_transition_list; | |
| struct list_head ch_db_list; | |
| struct workqueue_struct *wq; | |
| struct work_struct state_work; | |
| struct work_struct reset_work; | |
| struct work_struct cmd_ring_work; | |
| struct work_struct ch_ring_work; | |
| struct kmem_cache *ring_item_cache; | |
| struct kmem_cache *ev_ring_el_cache; | |
| struct kmem_cache *tre_buf_cache; | |
| void (*raise_irq)(struct mhi_ep_cntrl *mhi_cntrl, u32 vector); | |
| int (*alloc_map)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t *phys_ptr, | |
| void __iomem **virt, size_t size); | |
| void (*unmap_free)(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr, phys_addr_t phys, | |
| void __iomem *virt, size_t size); | |
| int (*read_sync)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); | |
| int (*write_sync)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); | |
| int (*read_async)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); | |
| int (*write_async)(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_buf_info *buf_info); | |
| enum mhi_state mhi_state; | |
| u32 max_chan; | |
| u32 mru; | |
| u32 event_rings; | |
| u32 hw_event_rings; | |
| u32 chdb_offset; | |
| u32 erdb_offset; | |
| u32 index; | |
| int irq; | |
| bool enabled; | |
| }; | |
| /** | |
| * struct mhi_ep_device - Structure representing an MHI Endpoint device that binds | |
| * to channels or is associated with controllers | |
| * @dev: Driver model device node for the MHI Endpoint device | |
| * @mhi_cntrl: Controller the device belongs to | |
| * @id: Pointer to MHI Endpoint device ID struct | |
| * @name: Name of the associated MHI Endpoint device | |
| * @ul_chan: UL (from host to endpoint) channel for the device | |
| * @dl_chan: DL (from endpoint to host) channel for the device | |
| * @dev_type: MHI device type | |
| */ | |
| struct mhi_ep_device { | |
| struct device dev; | |
| struct mhi_ep_cntrl *mhi_cntrl; | |
| const struct mhi_device_id *id; | |
| const char *name; | |
| struct mhi_ep_chan *ul_chan; | |
| struct mhi_ep_chan *dl_chan; | |
| enum mhi_device_type dev_type; | |
| }; | |
| /** | |
| * struct mhi_ep_driver - Structure representing a MHI Endpoint client driver | |
| * @id_table: Pointer to MHI Endpoint device ID table | |
| * @driver: Device driver model driver | |
| * @probe: CB function for client driver probe function | |
| * @remove: CB function for client driver remove function | |
| * @ul_xfer_cb: CB function for UL (from host to endpoint) data transfer | |
| * @dl_xfer_cb: CB function for DL (from endpoint to host) data transfer | |
| */ | |
| struct mhi_ep_driver { | |
| const struct mhi_device_id *id_table; | |
| struct device_driver driver; | |
| int (*probe)(struct mhi_ep_device *mhi_ep, | |
| const struct mhi_device_id *id); | |
| void (*remove)(struct mhi_ep_device *mhi_ep); | |
| void (*ul_xfer_cb)(struct mhi_ep_device *mhi_dev, | |
| struct mhi_result *result); | |
| void (*dl_xfer_cb)(struct mhi_ep_device *mhi_dev, | |
| struct mhi_result *result); | |
| }; | |
| #define to_mhi_ep_device(dev) container_of(dev, struct mhi_ep_device, dev) | |
| #define to_mhi_ep_driver(drv) container_of_const(drv, struct mhi_ep_driver, driver) | |
| /* | |
| * module_mhi_ep_driver() - Helper macro for drivers that don't do | |
| * anything special other than using default mhi_ep_driver_register() and | |
| * mhi_ep_driver_unregister(). This eliminates a lot of boilerplate. | |
| * Each module may only use this macro once. | |
| */ | |
| #define module_mhi_ep_driver(mhi_drv) \ | |
| module_driver(mhi_drv, mhi_ep_driver_register, \ | |
| mhi_ep_driver_unregister) | |
| /* | |
| * Macro to avoid include chaining to get THIS_MODULE | |
| */ | |
| #define mhi_ep_driver_register(mhi_drv) \ | |
| __mhi_ep_driver_register(mhi_drv, THIS_MODULE) | |
| /** | |
| * __mhi_ep_driver_register - Register a driver with MHI Endpoint bus | |
| * @mhi_drv: Driver to be associated with the device | |
| * @owner: The module owner | |
| * | |
| * Return: 0 if driver registrations succeeds, a negative error code otherwise. | |
| */ | |
| int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner); | |
| /** | |
| * mhi_ep_driver_unregister - Unregister a driver from MHI Endpoint bus | |
| * @mhi_drv: Driver associated with the device | |
| */ | |
| void mhi_ep_driver_unregister(struct mhi_ep_driver *mhi_drv); | |
| /** | |
| * mhi_ep_register_controller - Register MHI Endpoint controller | |
| * @mhi_cntrl: MHI Endpoint controller to register | |
| * @config: Configuration to use for the controller | |
| * | |
| * Return: 0 if controller registrations succeeds, a negative error code otherwise. | |
| */ | |
| int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl, | |
| const struct mhi_ep_cntrl_config *config); | |
| /** | |
| * mhi_ep_unregister_controller - Unregister MHI Endpoint controller | |
| * @mhi_cntrl: MHI Endpoint controller to unregister | |
| */ | |
| void mhi_ep_unregister_controller(struct mhi_ep_cntrl *mhi_cntrl); | |
| /** | |
| * mhi_ep_power_up - Power up the MHI endpoint stack | |
| * @mhi_cntrl: MHI Endpoint controller | |
| * | |
| * Return: 0 if power up succeeds, a negative error code otherwise. | |
| */ | |
| int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl); | |
| /** | |
| * mhi_ep_power_down - Power down the MHI endpoint stack | |
| * @mhi_cntrl: MHI controller | |
| */ | |
| void mhi_ep_power_down(struct mhi_ep_cntrl *mhi_cntrl); | |
| /** | |
| * mhi_ep_queue_is_empty - Determine whether the transfer queue is empty | |
| * @mhi_dev: Device associated with the channels | |
| * @dir: DMA direction for the channel | |
| * | |
| * Return: true if the queue is empty, false otherwise. | |
| */ | |
| bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_direction dir); | |
| /** | |
| * mhi_ep_queue_skb - Send SKBs to host over MHI Endpoint | |
| * @mhi_dev: Device associated with the DL channel | |
| * @skb: SKBs to be queued | |
| * | |
| * Return: 0 if the SKBs has been sent successfully, a negative error code otherwise. | |
| */ | |
| int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb); | |
| #endif |