| /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| #ifndef MSM_GSI_H |
| #define MSM_GSI_H |
| #include <linux/types.h> |
| |
| enum gsi_ver { |
| GSI_VER_ERR = 0, |
| GSI_VER_1_0 = 1, |
| GSI_VER_1_2 = 2, |
| GSI_VER_1_3 = 3, |
| GSI_VER_2_0 = 4, |
| GSI_VER_MAX, |
| }; |
| |
| enum gsi_status { |
| GSI_STATUS_SUCCESS = 0, |
| GSI_STATUS_ERROR = 1, |
| GSI_STATUS_RING_INSUFFICIENT_SPACE = 2, |
| GSI_STATUS_RING_EMPTY = 3, |
| GSI_STATUS_RES_ALLOC_FAILURE = 4, |
| GSI_STATUS_BAD_STATE = 5, |
| GSI_STATUS_INVALID_PARAMS = 6, |
| GSI_STATUS_UNSUPPORTED_OP = 7, |
| GSI_STATUS_NODEV = 8, |
| GSI_STATUS_POLL_EMPTY = 9, |
| GSI_STATUS_EVT_RING_INCOMPATIBLE = 10, |
| GSI_STATUS_TIMED_OUT = 11, |
| GSI_STATUS_AGAIN = 12, |
| }; |
| |
| enum gsi_per_evt { |
| GSI_PER_EVT_GLOB_ERROR, |
| GSI_PER_EVT_GLOB_GP1, |
| GSI_PER_EVT_GLOB_GP2, |
| GSI_PER_EVT_GLOB_GP3, |
| GSI_PER_EVT_GENERAL_BREAK_POINT, |
| GSI_PER_EVT_GENERAL_BUS_ERROR, |
| GSI_PER_EVT_GENERAL_CMD_FIFO_OVERFLOW, |
| GSI_PER_EVT_GENERAL_MCS_STACK_OVERFLOW, |
| }; |
| |
| /** |
| * gsi_per_notify - Peripheral callback info |
| * |
| * @user_data: cookie supplied in gsi_register_device |
| * @evt_id: type of notification |
| * @err_desc: error related information |
| * |
| */ |
| struct gsi_per_notify { |
| void *user_data; |
| enum gsi_per_evt evt_id; |
| union { |
| uint16_t err_desc; |
| } data; |
| }; |
| |
| enum gsi_intr_type { |
| GSI_INTR_MSI = 0x0, |
| GSI_INTR_IRQ = 0x1 |
| }; |
| |
| |
| /** |
| * gsi_per_props - Peripheral related properties |
| * |
| * @gsi: GSI core version |
| * @ee: EE where this driver and peripheral driver runs |
| * @intr: control interrupt type |
| * @intvec: write data for MSI write |
| * @msi_addr: MSI address |
| * @irq: IRQ number |
| * @phys_addr: physical address of GSI block |
| * @size: register size of GSI block |
| * @mhi_er_id_limits_valid: valid flag for mhi_er_id_limits |
| * @mhi_er_id_limits: MHI event ring start and end ids |
| * @notify_cb: general notification callback |
| * @req_clk_cb: callback to request peripheral clock |
| * granted should be set to true if request is completed |
| * synchronously, false otherwise (peripheral needs |
| * to call gsi_complete_clk_grant later when request is |
| * completed) |
| * if this callback is not provided, then GSI will assume |
| * peripheral is clocked at all times |
| * @rel_clk_cb: callback to release peripheral clock |
| * @user_data: cookie used for notifications |
| * |
| * All the callbacks are in interrupt context |
| * |
| */ |
| struct gsi_per_props { |
| enum gsi_ver ver; |
| unsigned int ee; |
| enum gsi_intr_type intr; |
| uint32_t intvec; |
| uint64_t msi_addr; |
| unsigned int irq; |
| phys_addr_t phys_addr; |
| unsigned long size; |
| bool mhi_er_id_limits_valid; |
| uint32_t mhi_er_id_limits[2]; |
| void (*notify_cb)(struct gsi_per_notify *notify); |
| void (*req_clk_cb)(void *user_data, bool *granted); |
| int (*rel_clk_cb)(void *user_data); |
| void *user_data; |
| }; |
| |
| enum gsi_evt_err { |
| GSI_EVT_OUT_OF_BUFFERS_ERR = 0x0, |
| GSI_EVT_OUT_OF_RESOURCES_ERR = 0x1, |
| GSI_EVT_UNSUPPORTED_INTER_EE_OP_ERR = 0x2, |
| GSI_EVT_EVT_RING_EMPTY_ERR = 0x3, |
| }; |
| |
| /** |
| * gsi_evt_err_notify - event ring error callback info |
| * |
| * @user_data: cookie supplied in gsi_alloc_evt_ring |
| * @evt_id: type of error |
| * @err_desc: more info about the error |
| * |
| */ |
| struct gsi_evt_err_notify { |
| void *user_data; |
| enum gsi_evt_err evt_id; |
| uint16_t err_desc; |
| }; |
| |
| enum gsi_evt_chtype { |
| GSI_EVT_CHTYPE_MHI_EV = 0x0, |
| GSI_EVT_CHTYPE_XHCI_EV = 0x1, |
| GSI_EVT_CHTYPE_GPI_EV = 0x2, |
| GSI_EVT_CHTYPE_XDCI_EV = 0x3 |
| }; |
| |
| enum gsi_evt_ring_elem_size { |
| GSI_EVT_RING_RE_SIZE_4B = 4, |
| GSI_EVT_RING_RE_SIZE_16B = 16, |
| }; |
| |
| /** |
| * gsi_evt_ring_props - Event ring related properties |
| * |
| * @intf: interface type (of the associated channel) |
| * @intr: interrupt type |
| * @re_size: size of event ring element |
| * @ring_len: length of ring in bytes (must be integral multiple of |
| * re_size) |
| * @ring_base_addr: physical base address of ring. Address must be aligned to |
| * ring_len rounded to power of two |
| * @ring_base_vaddr: virtual base address of ring (set to NULL when not |
| * applicable) |
| * @int_modt: cycles base interrupt moderation (32KHz clock) |
| * @int_modc: interrupt moderation packet counter |
| * @intvec: write data for MSI write |
| * @msi_addr: MSI address |
| * @rp_update_addr: physical address to which event read pointer should be |
| * written on every event generation. must be set to 0 when |
| * no update is desdired |
| * @exclusive: if true, only one GSI channel can be associated with this |
| * event ring. if false, the event ring can be shared among |
| * multiple GSI channels but in that case no polling |
| * (GSI_CHAN_MODE_POLL) is supported on any of those channels |
| * @err_cb: error notification callback |
| * @user_data: cookie used for error notifications |
| * @evchid_valid: is evchid valid? |
| * @evchid: the event ID that is being specifically requested (this is |
| * relevant for MHI where doorbell routing requires ERs to be |
| * physically contiguous) |
| */ |
| struct gsi_evt_ring_props { |
| enum gsi_evt_chtype intf; |
| enum gsi_intr_type intr; |
| enum gsi_evt_ring_elem_size re_size; |
| uint16_t ring_len; |
| uint64_t ring_base_addr; |
| void *ring_base_vaddr; |
| uint16_t int_modt; |
| uint8_t int_modc; |
| uint32_t intvec; |
| uint64_t msi_addr; |
| uint64_t rp_update_addr; |
| bool exclusive; |
| void (*err_cb)(struct gsi_evt_err_notify *notify); |
| void *user_data; |
| bool evchid_valid; |
| uint8_t evchid; |
| }; |
| |
| enum gsi_chan_mode { |
| GSI_CHAN_MODE_CALLBACK = 0x0, |
| GSI_CHAN_MODE_POLL = 0x1, |
| }; |
| |
| enum gsi_chan_prot { |
| GSI_CHAN_PROT_MHI = 0x0, |
| GSI_CHAN_PROT_XHCI = 0x1, |
| GSI_CHAN_PROT_GPI = 0x2, |
| GSI_CHAN_PROT_XDCI = 0x3 |
| }; |
| |
| enum gsi_chan_dir { |
| GSI_CHAN_DIR_FROM_GSI = 0x0, |
| GSI_CHAN_DIR_TO_GSI = 0x1 |
| }; |
| |
| enum gsi_max_prefetch { |
| GSI_ONE_PREFETCH_SEG = 0x0, |
| GSI_TWO_PREFETCH_SEG = 0x1 |
| }; |
| |
| enum gsi_chan_evt { |
| GSI_CHAN_EVT_INVALID = 0x0, |
| GSI_CHAN_EVT_SUCCESS = 0x1, |
| GSI_CHAN_EVT_EOT = 0x2, |
| GSI_CHAN_EVT_OVERFLOW = 0x3, |
| GSI_CHAN_EVT_EOB = 0x4, |
| GSI_CHAN_EVT_OOB = 0x5, |
| GSI_CHAN_EVT_DB_MODE = 0x6, |
| GSI_CHAN_EVT_UNDEFINED = 0x10, |
| GSI_CHAN_EVT_RE_ERROR = 0x11, |
| }; |
| |
| /** |
| * gsi_chan_xfer_notify - Channel callback info |
| * |
| * @chan_user_data: cookie supplied in gsi_alloc_channel |
| * @xfer_user_data: cookie of the gsi_xfer_elem that caused the |
| * event to be generated |
| * @evt_id: type of event triggered by the associated TRE |
| * (corresponding to xfer_user_data) |
| * @bytes_xfered: number of bytes transferred by the associated TRE |
| * (corresponding to xfer_user_data) |
| * |
| */ |
| struct gsi_chan_xfer_notify { |
| void *chan_user_data; |
| void *xfer_user_data; |
| enum gsi_chan_evt evt_id; |
| uint16_t bytes_xfered; |
| }; |
| |
| enum gsi_chan_err { |
| GSI_CHAN_INVALID_TRE_ERR = 0x0, |
| GSI_CHAN_NON_ALLOCATED_EVT_ACCESS_ERR = 0x1, |
| GSI_CHAN_OUT_OF_BUFFERS_ERR = 0x2, |
| GSI_CHAN_OUT_OF_RESOURCES_ERR = 0x3, |
| GSI_CHAN_UNSUPPORTED_INTER_EE_OP_ERR = 0x4, |
| GSI_CHAN_HWO_1_ERR = 0x5 |
| }; |
| |
| /** |
| * gsi_chan_err_notify - Channel general callback info |
| * |
| * @chan_user_data: cookie supplied in gsi_alloc_channel |
| * @evt_id: type of error |
| * @err_desc: more info about the error |
| * |
| */ |
| struct gsi_chan_err_notify { |
| void *chan_user_data; |
| enum gsi_chan_err evt_id; |
| uint16_t err_desc; |
| }; |
| |
| enum gsi_chan_ring_elem_size { |
| GSI_CHAN_RE_SIZE_4B = 4, |
| GSI_CHAN_RE_SIZE_16B = 16, |
| GSI_CHAN_RE_SIZE_32B = 32, |
| }; |
| |
| enum gsi_chan_use_db_eng { |
| GSI_CHAN_DIRECT_MODE = 0x0, |
| GSI_CHAN_DB_MODE = 0x1, |
| }; |
| |
| /** |
| * gsi_chan_props - Channel related properties |
| * |
| * @prot: interface type |
| * @dir: channel direction |
| * @ch_id: virtual channel ID |
| * @evt_ring_hdl: handle of associated event ring. set to ~0 if no |
| * event ring associated |
| * @re_size: size of channel ring element |
| * @ring_len: length of ring in bytes (must be integral multiple of |
| * re_size) |
| * @max_re_expected: maximal number of ring elements expected to be queued. |
| * used for data path statistics gathering. if 0 provided |
| * ring_len / re_size will be used. |
| * @ring_base_addr: physical base address of ring. Address must be aligned to |
| * ring_len rounded to power of two |
| * @ring_base_vaddr: virtual base address of ring (set to NULL when not |
| * applicable) |
| * @use_db_eng: 0 => direct mode (doorbells are written directly to RE |
| * engine) |
| * 1 => DB mode (doorbells are written to DB engine) |
| * @max_prefetch: limit number of pre-fetch segments for channel |
| * @low_weight: low channel weight (priority of channel for RE engine |
| * round robin algorithm); must be >= 1 |
| * @xfer_cb: transfer notification callback, this callback happens |
| * on event boundaries |
| * |
| * e.g. 1 |
| * |
| * out TD with 3 REs |
| * |
| * RE1: EOT=0, EOB=0, CHAIN=1; |
| * RE2: EOT=0, EOB=0, CHAIN=1; |
| * RE3: EOT=1, EOB=0, CHAIN=0; |
| * |
| * the callback will be triggered for RE3 using the |
| * xfer_user_data of that RE |
| * |
| * e.g. 2 |
| * |
| * in REs |
| * |
| * RE1: EOT=1, EOB=0, CHAIN=0; |
| * RE2: EOT=1, EOB=0, CHAIN=0; |
| * RE3: EOT=1, EOB=0, CHAIN=0; |
| * |
| * received packet consumes all of RE1, RE2 and part of RE3 |
| * for EOT condition. there will be three callbacks in below |
| * order |
| * |
| * callback for RE1 using GSI_CHAN_EVT_OVERFLOW |
| * callback for RE2 using GSI_CHAN_EVT_OVERFLOW |
| * callback for RE3 using GSI_CHAN_EVT_EOT |
| * |
| * @err_cb: error notification callback |
| * @chan_user_data: cookie used for notifications |
| * |
| * All the callbacks are in interrupt context |
| * |
| */ |
| struct gsi_chan_props { |
| enum gsi_chan_prot prot; |
| enum gsi_chan_dir dir; |
| uint8_t ch_id; |
| unsigned long evt_ring_hdl; |
| enum gsi_chan_ring_elem_size re_size; |
| uint16_t ring_len; |
| uint16_t max_re_expected; |
| uint64_t ring_base_addr; |
| void *ring_base_vaddr; |
| enum gsi_chan_use_db_eng use_db_eng; |
| enum gsi_max_prefetch max_prefetch; |
| uint8_t low_weight; |
| void (*xfer_cb)(struct gsi_chan_xfer_notify *notify); |
| void (*err_cb)(struct gsi_chan_err_notify *notify); |
| void *chan_user_data; |
| }; |
| |
| enum gsi_xfer_flag { |
| GSI_XFER_FLAG_CHAIN = 0x1, |
| GSI_XFER_FLAG_EOB = 0x100, |
| GSI_XFER_FLAG_EOT = 0x200, |
| GSI_XFER_FLAG_BEI = 0x400 |
| }; |
| |
| enum gsi_xfer_elem_type { |
| GSI_XFER_ELEM_DATA, |
| GSI_XFER_ELEM_IMME_CMD, |
| GSI_XFER_ELEM_NOP, |
| }; |
| |
| /** |
| * gsi_xfer_elem - Metadata about a single transfer |
| * |
| * @addr: physical address of buffer |
| * @len: size of buffer for GSI_XFER_ELEM_DATA: |
| * for outbound transfers this is the number of bytes to |
| * transfer. |
| * for inbound transfers, this is the maximum number of |
| * bytes the host expects from device in this transfer |
| * |
| * immediate command opcode for GSI_XFER_ELEM_IMME_CMD |
| * @flags: transfer flags, OR of all the applicable flags |
| * |
| * GSI_XFER_FLAG_BEI: Block event interrupt |
| * 1: Event generated by this ring element must not assert |
| * an interrupt to the host |
| * 0: Event generated by this ring element must assert an |
| * interrupt to the host |
| * |
| * GSI_XFER_FLAG_EOT: Interrupt on end of transfer |
| * 1: If an EOT condition is encountered when processing |
| * this ring element, an event is generated by the device |
| * with its completion code set to EOT. |
| * 0: If an EOT condition is encountered for this ring |
| * element, a completion event is not be generated by the |
| * device, unless IEOB is 1 |
| * |
| * GSI_XFER_FLAG_EOB: Interrupt on end of block |
| * 1: Device notifies host after processing this ring element |
| * by sending a completion event |
| * 0: Completion event is not required after processing this |
| * ring element |
| * |
| * GSI_XFER_FLAG_CHAIN: Chain bit that identifies the ring |
| * elements in a TD |
| * |
| * @type: transfer type |
| * |
| * GSI_XFER_ELEM_DATA: for all data transfers |
| * GSI_XFER_ELEM_IMME_CMD: for IPA immediate commands |
| * GSI_XFER_ELEM_NOP: for event generation only |
| * |
| * @xfer_user_data: cookie used in xfer_cb |
| * |
| */ |
| struct gsi_xfer_elem { |
| uint64_t addr; |
| uint16_t len; |
| uint16_t flags; |
| enum gsi_xfer_elem_type type; |
| void *xfer_user_data; |
| }; |
| |
| /** |
| * gsi_gpi_channel_scratch - GPI protocol SW config area of |
| * channel scratch |
| * |
| * @max_outstanding_tre: Used for the prefetch management sequence by the |
| * sequencer. Defines the maximum number of allowed |
| * outstanding TREs in IPA/GSI (in Bytes). RE engine |
| * prefetch will be limited by this configuration. It |
| * is suggested to configure this value to IPA_IF |
| * channel TLV queue size times element size. To disable |
| * the feature in doorbell mode (DB Mode=1). Maximum |
| * outstanding TREs should be set to 64KB |
| * (or any value larger or equal to ring length . RLEN) |
| * @outstanding_threshold: Used for the prefetch management sequence by the |
| * sequencer. Defines the threshold (in Bytes) as to when |
| * to update the channel doorbell. Should be smaller than |
| * Maximum outstanding TREs. value. It is suggested to |
| * configure this value to 2 * element size. |
| */ |
| struct __packed gsi_gpi_channel_scratch { |
| uint64_t resvd1; |
| uint32_t resvd2:16; |
| uint32_t max_outstanding_tre:16; |
| uint32_t resvd3:16; |
| uint32_t outstanding_threshold:16; |
| }; |
| |
| /** |
| * gsi_mhi_channel_scratch - MHI protocol SW config area of |
| * channel scratch |
| * |
| * @mhi_host_wp_addr: Valid only when UL/DL Sync En is asserted. Defines |
| * address in host from which channel write pointer |
| * should be read in polling mode |
| * @assert_bit40: 1: bit #41 in address should be asserted upon |
| * IPA_IF.ProcessDescriptor routine (for MHI over PCIe |
| * transfers) |
| * 0: bit #41 in address should be deasserted upon |
| * IPA_IF.ProcessDescriptor routine (for non-MHI over |
| * PCIe transfers) |
| * @polling_configuration: Uplink channels: Defines timer to poll on MHI |
| * context. Range: 1 to 31 milliseconds. |
| * Downlink channel: Defines transfer ring buffer |
| * availability threshold to poll on MHI context in |
| * multiple of 8. Range: 0 to 31, meaning 0 to 258 ring |
| * elements. E.g., value of 2 indicates 16 ring elements. |
| * Valid only when Burst Mode Enabled is set to 1 |
| * @burst_mode_enabled: 0: Burst mode is disabled for this channel |
| * 1: Burst mode is enabled for this channel |
| * @polling_mode: 0: the channel is not in polling mode, meaning the |
| * host should ring DBs. |
| * 1: the channel is in polling mode, meaning the host |
| * @oob_mod_threshold: Defines OOB moderation threshold. Units are in 8 |
| * ring elements. |
| * should not ring DBs until notified of DB mode/OOB mode |
| * @max_outstanding_tre: Used for the prefetch management sequence by the |
| * sequencer. Defines the maximum number of allowed |
| * outstanding TREs in IPA/GSI (in Bytes). RE engine |
| * prefetch will be limited by this configuration. It |
| * is suggested to configure this value to IPA_IF |
| * channel TLV queue size times element size. |
| * To disable the feature in doorbell mode (DB Mode=1). |
| * Maximum outstanding TREs should be set to 64KB |
| * (or any value larger or equal to ring length . RLEN) |
| * @outstanding_threshold: Used for the prefetch management sequence by the |
| * sequencer. Defines the threshold (in Bytes) as to when |
| * to update the channel doorbell. Should be smaller than |
| * Maximum outstanding TREs. value. It is suggested to |
| * configure this value to min(TLV_FIFO_SIZE/2,8) * |
| * element size. |
| */ |
| struct __packed gsi_mhi_channel_scratch { |
| uint64_t mhi_host_wp_addr; |
| uint32_t rsvd1:1; |
| uint32_t assert_bit40:1; |
| uint32_t polling_configuration:5; |
| uint32_t burst_mode_enabled:1; |
| uint32_t polling_mode:1; |
| uint32_t oob_mod_threshold:5; |
| uint32_t resvd2:2; |
| uint32_t max_outstanding_tre:16; |
| uint32_t resvd3:16; |
| uint32_t outstanding_threshold:16; |
| }; |
| |
| /** |
| * gsi_xdci_channel_scratch - xDCI protocol SW config area of |
| * channel scratch |
| * |
| * @const_buffer_size: TRB buffer size in KB (similar to IPA aggregationi |
| * configuration). Must be aligned to Max USB Packet Size |
| * @xferrscidx: Transfer Resource Index (XferRscIdx). The hardware-assigned |
| * transfer resource index for the transfer, which was |
| * returned in response to the Start Transfer command. |
| * This field is used for "Update Transfer" command |
| * @last_trb_addr: Address (LSB - based on alignment restrictions) of |
| * last TRB in queue. Used to identify rollover case |
| * @depcmd_low_addr: Used to generate "Update Transfer" command |
| * @max_outstanding_tre: Used for the prefetch management sequence by the |
| * sequencer. Defines the maximum number of allowed |
| * outstanding TREs in IPA/GSI (in Bytes). RE engine |
| * prefetch will be limited by this configuration. It |
| * is suggested to configure this value to IPA_IF |
| * channel TLV queue size times element size. |
| * To disable the feature in doorbell mode (DB Mode=1) |
| * Maximum outstanding TREs should be set to 64KB |
| * (or any value larger or equal to ring length . RLEN) |
| * @depcmd_hi_addr: Used to generate "Update Transfer" command |
| * @outstanding_threshold: Used for the prefetch management sequence by the |
| * sequencer. Defines the threshold (in Bytes) as to when |
| * to update the channel doorbell. Should be smaller than |
| * Maximum outstanding TREs. value. It is suggested to |
| * configure this value to 2 * element size. for MBIM the |
| * suggested configuration is the element size. |
| */ |
| struct __packed gsi_xdci_channel_scratch { |
| uint32_t last_trb_addr:16; |
| uint32_t resvd1:4; |
| uint32_t xferrscidx:7; |
| uint32_t const_buffer_size:5; |
| uint32_t depcmd_low_addr; |
| uint32_t depcmd_hi_addr:8; |
| uint32_t resvd2:8; |
| uint32_t max_outstanding_tre:16; |
| uint32_t resvd3:16; |
| uint32_t outstanding_threshold:16; |
| }; |
| |
| /** |
| * gsi_channel_scratch - channel scratch SW config area |
| * |
| */ |
| union __packed gsi_channel_scratch { |
| struct __packed gsi_gpi_channel_scratch gpi; |
| struct __packed gsi_mhi_channel_scratch mhi; |
| struct __packed gsi_xdci_channel_scratch xdci; |
| struct __packed { |
| uint32_t word1; |
| uint32_t word2; |
| uint32_t word3; |
| uint32_t word4; |
| } data; |
| }; |
| |
| /** |
| * gsi_mhi_evt_scratch - MHI protocol SW config area of |
| * event scratch |
| */ |
| struct __packed gsi_mhi_evt_scratch { |
| uint32_t resvd1; |
| uint32_t resvd2; |
| }; |
| |
| /** |
| * gsi_xdci_evt_scratch - xDCI protocol SW config area of |
| * event scratch |
| * |
| */ |
| struct __packed gsi_xdci_evt_scratch { |
| uint32_t gevntcount_low_addr; |
| uint32_t gevntcount_hi_addr:8; |
| uint32_t resvd1:24; |
| }; |
| |
| /** |
| * gsi_evt_scratch - event scratch SW config area |
| * |
| */ |
| union __packed gsi_evt_scratch { |
| struct __packed gsi_mhi_evt_scratch mhi; |
| struct __packed gsi_xdci_evt_scratch xdci; |
| struct __packed { |
| uint32_t word1; |
| uint32_t word2; |
| } data; |
| }; |
| |
| /** |
| * gsi_device_scratch - EE scratch config parameters |
| * |
| * @mhi_base_chan_idx_valid: is mhi_base_chan_idx valid? |
| * @mhi_base_chan_idx: base index of IPA MHI channel indexes. |
| * IPA MHI channel index = GSI channel ID + |
| * MHI base channel index |
| * @max_usb_pkt_size_valid: is max_usb_pkt_size valid? |
| * @max_usb_pkt_size: max USB packet size in bytes (valid values are |
| * 512 and 1024) |
| */ |
| struct gsi_device_scratch { |
| bool mhi_base_chan_idx_valid; |
| uint8_t mhi_base_chan_idx; |
| bool max_usb_pkt_size_valid; |
| uint16_t max_usb_pkt_size; |
| }; |
| |
| /** |
| * gsi_chan_info - information about channel occupancy |
| * |
| * @wp: channel write pointer (physical address) |
| * @rp: channel read pointer (physical address) |
| * @evt_valid: is evt* info valid? |
| * @evt_wp: event ring write pointer (physical address) |
| * @evt_rp: event ring read pointer (physical address) |
| */ |
| struct gsi_chan_info { |
| uint64_t wp; |
| uint64_t rp; |
| bool evt_valid; |
| uint64_t evt_wp; |
| uint64_t evt_rp; |
| }; |
| |
| #ifdef CONFIG_GSI |
| /** |
| * gsi_register_device - Peripheral should call this function to |
| * register itself with GSI before invoking any other APIs |
| * |
| * @props: Peripheral properties |
| * @dev_hdl: Handle populated by GSI, opaque to client |
| * |
| * @Return -GSI_STATUS_AGAIN if request should be re-tried later |
| * other error codes for failure |
| */ |
| int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl); |
| |
| /** |
| * gsi_complete_clk_grant - Peripheral should call this function to |
| * grant the clock resource requested by GSI previously that could not |
| * be granted synchronously. GSI will release the clock resource using |
| * the rel_clk_cb when appropriate |
| * |
| * @dev_hdl: Client handle previously obtained from |
| * gsi_register_device |
| * |
| * @Return gsi_status |
| */ |
| int gsi_complete_clk_grant(unsigned long dev_hdl); |
| |
| /** |
| * gsi_write_device_scratch - Peripheral should call this function to |
| * write to the EE scratch area |
| * |
| * @dev_hdl: Client handle previously obtained from |
| * gsi_register_device |
| * @val: Value to write |
| * |
| * @Return gsi_status |
| */ |
| int gsi_write_device_scratch(unsigned long dev_hdl, |
| struct gsi_device_scratch *val); |
| |
| /** |
| * gsi_deregister_device - Peripheral should call this function to |
| * de-register itself with GSI |
| * |
| * @dev_hdl: Client handle previously obtained from |
| * gsi_register_device |
| * @force: When set to true, cleanup is performed even if there |
| * are in use resources like channels, event rings, etc. |
| * this would be used after GSI reset to recover from some |
| * fatal error |
| * When set to false, there must not exist any allocated |
| * channels and event rings. |
| * |
| * @Return gsi_status |
| */ |
| int gsi_deregister_device(unsigned long dev_hdl, bool force); |
| |
| /** |
| * gsi_alloc_evt_ring - Peripheral should call this function to |
| * allocate an event ring |
| * |
| * @props: Event ring properties |
| * @dev_hdl: Client handle previously obtained from |
| * gsi_register_device |
| * @evt_ring_hdl: Handle populated by GSI, opaque to client |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_alloc_evt_ring(struct gsi_evt_ring_props *props, unsigned long dev_hdl, |
| unsigned long *evt_ring_hdl); |
| |
| /** |
| * gsi_write_evt_ring_scratch - Peripheral should call this function to |
| * write to the scratch area of the event ring context |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * @val: Value to write |
| * |
| * @Return gsi_status |
| */ |
| int gsi_write_evt_ring_scratch(unsigned long evt_ring_hdl, |
| union __packed gsi_evt_scratch val); |
| |
| /** |
| * gsi_dealloc_evt_ring - Peripheral should call this function to |
| * de-allocate an event ring. There should not exist any active |
| * channels using this event ring |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_dealloc_evt_ring(unsigned long evt_ring_hdl); |
| |
| /** |
| * gsi_query_evt_ring_db_addr - Peripheral should call this function to |
| * query the physical addresses of the event ring doorbell registers |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * @db_addr_wp_lsb: Physical address of doorbell register where the 32 |
| * LSBs of the doorbell value should be written |
| * @db_addr_wp_msb: Physical address of doorbell register where the 32 |
| * MSBs of the doorbell value should be written |
| * |
| * @Return gsi_status |
| */ |
| int gsi_query_evt_ring_db_addr(unsigned long evt_ring_hdl, |
| uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb); |
| |
| /** |
| * gsi_ring_evt_ring_db - Peripheral should call this function for |
| * ringing the event ring doorbell with given value |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * @value: The value to be used for ringing the doorbell |
| * |
| * @Return gsi_status |
| */ |
| int gsi_ring_evt_ring_db(unsigned long evt_ring_hdl, uint64_t value); |
| |
| /** |
| * gsi_reset_evt_ring - Peripheral should call this function to |
| * reset an event ring to recover from error state |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_reset_evt_ring(unsigned long evt_ring_hdl); |
| |
| /** |
| * gsi_get_evt_ring_cfg - This function returns the current config |
| * of the specified event ring |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * @props: where to copy properties to |
| * @scr: where to copy scratch info to |
| * |
| * @Return gsi_status |
| */ |
| int gsi_get_evt_ring_cfg(unsigned long evt_ring_hdl, |
| struct gsi_evt_ring_props *props, union gsi_evt_scratch *scr); |
| |
| /** |
| * gsi_set_evt_ring_cfg - This function applies the supplied config |
| * to the specified event ring. |
| * |
| * exclusive property of the event ring cannot be changed after |
| * gsi_alloc_evt_ring |
| * |
| * @evt_ring_hdl: Client handle previously obtained from |
| * gsi_alloc_evt_ring |
| * @props: the properties to apply |
| * @scr: the scratch info to apply |
| * |
| * @Return gsi_status |
| */ |
| int gsi_set_evt_ring_cfg(unsigned long evt_ring_hdl, |
| struct gsi_evt_ring_props *props, union gsi_evt_scratch *scr); |
| |
| /** |
| * gsi_alloc_channel - Peripheral should call this function to |
| * allocate a channel |
| * |
| * @props: Channel properties |
| * @dev_hdl: Client handle previously obtained from |
| * gsi_register_device |
| * @chan_hdl: Handle populated by GSI, opaque to client |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, |
| unsigned long *chan_hdl); |
| |
| /** |
| * gsi_write_channel_scratch - Peripheral should call this function to |
| * write to the scratch area of the channel context |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @val: Value to write |
| * |
| * @Return gsi_status |
| */ |
| int gsi_write_channel_scratch(unsigned long chan_hdl, |
| union __packed gsi_channel_scratch val); |
| |
| /** |
| * gsi_start_channel - Peripheral should call this function to |
| * start a channel i.e put into running state |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_start_channel(unsigned long chan_hdl); |
| |
| /** |
| * gsi_stop_channel - Peripheral should call this function to |
| * stop a channel. Stop will happen on a packet boundary |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * This function can sleep |
| * |
| * @Return -GSI_STATUS_AGAIN if client should call stop/stop_db again |
| * other error codes for failure |
| */ |
| int gsi_stop_channel(unsigned long chan_hdl); |
| |
| /** |
| * gsi_reset_channel - Peripheral should call this function to |
| * reset a channel to recover from error state |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_reset_channel(unsigned long chan_hdl); |
| |
| /** |
| * gsi_dealloc_channel - Peripheral should call this function to |
| * de-allocate a channel |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * This function can sleep |
| * |
| * @Return gsi_status |
| */ |
| int gsi_dealloc_channel(unsigned long chan_hdl); |
| |
| /** |
| * gsi_stop_db_channel - Peripheral should call this function to |
| * stop a channel when all transfer elements till the doorbell |
| * have been processed |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * This function can sleep |
| * |
| * @Return -GSI_STATUS_AGAIN if client should call stop/stop_db again |
| * other error codes for failure |
| */ |
| int gsi_stop_db_channel(unsigned long chan_hdl); |
| |
| /** |
| * gsi_query_channel_db_addr - Peripheral should call this function to |
| * query the physical addresses of the channel doorbell registers |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @db_addr_wp_lsb: Physical address of doorbell register where the 32 |
| * LSBs of the doorbell value should be written |
| * @db_addr_wp_msb: Physical address of doorbell register where the 32 |
| * MSBs of the doorbell value should be written |
| * |
| * @Return gsi_status |
| */ |
| int gsi_query_channel_db_addr(unsigned long chan_hdl, |
| uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb); |
| |
| /** |
| * gsi_query_channel_info - Peripheral can call this function to query the |
| * channel and associated event ring (if any) status. |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @info: Where to read the values into |
| * |
| * @Return gsi_status |
| */ |
| int gsi_query_channel_info(unsigned long chan_hdl, |
| struct gsi_chan_info *info); |
| |
| /** |
| * gsi_is_channel_empty - Peripheral can call this function to query if |
| * the channel is empty. This is only applicable to GPI. "Empty" means |
| * GSI has consumed all descriptors for a TO_GSI channel and SW has |
| * processed all completed descriptors for a FROM_GSI channel. |
| * |
| * @chan_hdl: Client handle previously obtained from gsi_alloc_channel |
| * @is_empty: set by GSI based on channel emptiness |
| * |
| * @Return gsi_status |
| */ |
| int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty); |
| |
| /** |
| * gsi_get_channel_cfg - This function returns the current config |
| * of the specified channel |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @props: where to copy properties to |
| * @scr: where to copy scratch info to |
| * |
| * @Return gsi_status |
| */ |
| int gsi_get_channel_cfg(unsigned long chan_hdl, struct gsi_chan_props *props, |
| union gsi_channel_scratch *scr); |
| |
| /** |
| * gsi_set_channel_cfg - This function applies the supplied config |
| * to the specified channel |
| * |
| * ch_id and evt_ring_hdl of the channel cannot be changed after |
| * gsi_alloc_channel |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @props: the properties to apply |
| * @scr: the scratch info to apply |
| * |
| * @Return gsi_status |
| */ |
| int gsi_set_channel_cfg(unsigned long chan_hdl, struct gsi_chan_props *props, |
| union gsi_channel_scratch *scr); |
| |
| /** |
| * gsi_poll_channel - Peripheral should call this function to query for |
| * completed transfer descriptors. |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @notify: Information about the completed transfer if any |
| * |
| * @Return gsi_status (GSI_STATUS_POLL_EMPTY is returned if no transfers |
| * completed) |
| */ |
| int gsi_poll_channel(unsigned long chan_hdl, |
| struct gsi_chan_xfer_notify *notify); |
| |
| /** |
| * gsi_config_channel_mode - Peripheral should call this function |
| * to configure the channel mode. |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @mode: Mode to move the channel into |
| * |
| * @Return gsi_status |
| */ |
| int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode); |
| |
| /** |
| * gsi_queue_xfer - Peripheral should call this function |
| * to queue transfers on the given channel |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * @num_xfers: Number of transfer in the array @ xfer |
| * @xfer: Array of num_xfers transfer descriptors |
| * @ring_db: If true, tell HW about these queued xfers |
| * If false, do not notify HW at this time |
| * |
| * @Return gsi_status |
| */ |
| int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers, |
| struct gsi_xfer_elem *xfer, bool ring_db); |
| |
| /** |
| * gsi_start_xfer - Peripheral should call this function to |
| * inform HW about queued xfers |
| * |
| * @chan_hdl: Client handle previously obtained from |
| * gsi_alloc_channel |
| * |
| * @Return gsi_status |
| */ |
| int gsi_start_xfer(unsigned long chan_hdl); |
| |
| /** |
| * gsi_configure_regs - Peripheral should call this function |
| * to configure the GSI registers before/after the FW is |
| * loaded but before it is enabled. |
| * |
| * @gsi_base_addr: Base address of GSI register space |
| * @gsi_size: Mapping size of the GSI register space |
| * @per_base_addr: Base address of the peripheral using GSI |
| * |
| * @Return gsi_status |
| */ |
| int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, |
| phys_addr_t per_base_addr); |
| |
| /** |
| * gsi_enable_fw - Peripheral should call this function |
| * to enable the GSI FW after the FW has been loaded to the SRAM. |
| * |
| * @gsi_base_addr: Base address of GSI register space |
| * @gsi_size: Mapping size of the GSI register space |
| * @ver: GSI core version |
| |
| * @Return gsi_status |
| */ |
| int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver); |
| |
| /** |
| * gsi_get_inst_ram_offset_and_size - Peripheral should call this function |
| * to get instruction RAM base address offset and size. Peripheral typically |
| * uses this info to load GSI FW into the IRAM. |
| * |
| * @base_offset:[OUT] - IRAM base offset address |
| * @size: [OUT] - IRAM size |
| |
| * @Return none |
| */ |
| void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, |
| unsigned long *size); |
| |
| /** |
| * gsi_halt_channel_ee - Peripheral should call this function |
| * to stop other EE's channel. This is usually used in SSR clean |
| * |
| * @chan_idx: Virtual channel index |
| * @ee: EE |
| * @code: [out] response code for operation |
| |
| * @Return gsi_status |
| */ |
| int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code); |
| |
| /* |
| * Here is a typical sequence of calls |
| * |
| * gsi_register_device |
| * |
| * gsi_write_device_scratch (if the protocol needs this) |
| * |
| * gsi_alloc_evt_ring (for as many event rings as needed) |
| * gsi_write_evt_ring_scratch |
| * |
| * gsi_alloc_channel (for as many channels as needed; channels can have |
| * no event ring, an exclusive event ring or a shared event ring) |
| * gsi_write_channel_scratch |
| * gsi_start_channel |
| * gsi_queue_xfer/gsi_start_xfer |
| * gsi_config_channel_mode/gsi_poll_channel (if clients wants to poll on |
| * xfer completions) |
| * gsi_stop_db_channel/gsi_stop_channel |
| * |
| * gsi_dealloc_channel |
| * |
| * gsi_dealloc_evt_ring |
| * |
| * gsi_deregister_device |
| * |
| */ |
| #else |
| static inline int gsi_register_device(struct gsi_per_props *props, |
| unsigned long *dev_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_complete_clk_grant(unsigned long dev_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_write_device_scratch(unsigned long dev_hdl, |
| struct gsi_device_scratch *val) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_deregister_device(unsigned long dev_hdl, bool force) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_alloc_evt_ring(struct gsi_evt_ring_props *props, |
| unsigned long dev_hdl, |
| unsigned long *evt_ring_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_write_evt_ring_scratch(unsigned long evt_ring_hdl, |
| union __packed gsi_evt_scratch val) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_dealloc_evt_ring(unsigned long evt_ring_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_query_evt_ring_db_addr(unsigned long evt_ring_hdl, |
| uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_ring_evt_ring_db(unsigned long evt_ring_hdl, |
| uint64_t value) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_reset_evt_ring(unsigned long evt_ring_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_alloc_channel(struct gsi_chan_props *props, |
| unsigned long dev_hdl, |
| unsigned long *chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_write_channel_scratch(unsigned long chan_hdl, |
| union __packed gsi_channel_scratch val) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_start_channel(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_stop_channel(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_reset_channel(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_dealloc_channel(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_stop_db_channel(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_query_channel_db_addr(unsigned long chan_hdl, |
| uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_query_channel_info(unsigned long chan_hdl, |
| struct gsi_chan_info *info) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_poll_channel(unsigned long chan_hdl, |
| struct gsi_chan_xfer_notify *notify) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_config_channel_mode(unsigned long chan_hdl, |
| enum gsi_chan_mode mode) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_queue_xfer(unsigned long chan_hdl, uint16_t num_xfers, |
| struct gsi_xfer_elem *xfer, bool ring_db) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_start_xfer(unsigned long chan_hdl) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_get_channel_cfg(unsigned long chan_hdl, |
| struct gsi_chan_props *props, |
| union gsi_channel_scratch *scr) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_set_channel_cfg(unsigned long chan_hdl, |
| struct gsi_chan_props *props, |
| union gsi_channel_scratch *scr) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_get_evt_ring_cfg(unsigned long evt_ring_hdl, |
| struct gsi_evt_ring_props *props, union gsi_evt_scratch *scr) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_set_evt_ring_cfg(unsigned long evt_ring_hdl, |
| struct gsi_evt_ring_props *props, union gsi_evt_scratch *scr) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, |
| phys_addr_t per_base_addr) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| |
| static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, |
| unsigned long *size) |
| { |
| } |
| |
| static inline int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, |
| int *code) |
| { |
| return -GSI_STATUS_UNSUPPORTED_OP; |
| } |
| #endif |
| #endif |