162306a36Sopenharmony_ci/* SPDX-License-Identifier: BSD-3-Clause-Clear */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef ATH12K_CE_H 862306a36Sopenharmony_ci#define ATH12K_CE_H 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define CE_COUNT_MAX 16 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* Byte swap data words */ 1362306a36Sopenharmony_ci#define CE_ATTR_BYTE_SWAP_DATA 2 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* no interrupt on copy completion */ 1662306a36Sopenharmony_ci#define CE_ATTR_DIS_INTR 8 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Host software's Copy Engine configuration. */ 1962306a36Sopenharmony_ci#define CE_ATTR_FLAGS 0 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Threshold to poll for tx completion in case of Interrupt disabled CE's */ 2262306a36Sopenharmony_ci#define ATH12K_CE_USAGE_THRESHOLD 32 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Directions for interconnect pipe configuration. 2562306a36Sopenharmony_ci * These definitions may be used during configuration and are shared 2662306a36Sopenharmony_ci * between Host and Target. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Pipe Directions are relative to the Host, so PIPEDIR_IN means 2962306a36Sopenharmony_ci * "coming IN over air through Target to Host" as with a WiFi Rx operation. 3062306a36Sopenharmony_ci * Conversely, PIPEDIR_OUT means "going OUT from Host through Target over air" 3162306a36Sopenharmony_ci * as with a WiFi Tx operation. This is somewhat awkward for the "middle-man" 3262306a36Sopenharmony_ci * Target since things that are "PIPEDIR_OUT" are coming IN to the Target 3362306a36Sopenharmony_ci * over the interconnect. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci#define PIPEDIR_NONE 0 3662306a36Sopenharmony_ci#define PIPEDIR_IN 1 /* Target-->Host, WiFi Rx direction */ 3762306a36Sopenharmony_ci#define PIPEDIR_OUT 2 /* Host->Target, WiFi Tx direction */ 3862306a36Sopenharmony_ci#define PIPEDIR_INOUT 3 /* bidirectional */ 3962306a36Sopenharmony_ci#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* CE address/mask */ 4262306a36Sopenharmony_ci#define CE_HOST_IE_ADDRESS 0x00A1803C 4362306a36Sopenharmony_ci#define CE_HOST_IE_2_ADDRESS 0x00A18040 4462306a36Sopenharmony_ci#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define CE_HOST_IE_3_SHIFT 0xC 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define ATH12K_CE_RX_POST_RETRY_JIFFIES 50 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistruct ath12k_base; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Establish a mapping between a service/direction and a pipe. 5562306a36Sopenharmony_ci * Configuration information for a Copy Engine pipe and services. 5662306a36Sopenharmony_ci * Passed from Host to Target through QMI message and must be in 5762306a36Sopenharmony_ci * little endian format. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_cistruct service_to_pipe { 6062306a36Sopenharmony_ci __le32 service_id; 6162306a36Sopenharmony_ci __le32 pipedir; 6262306a36Sopenharmony_ci __le32 pipenum; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Configuration information for a Copy Engine pipe. 6662306a36Sopenharmony_ci * Passed from Host to Target through QMI message during startup (one per CE). 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * NOTE: Structure is shared between Host software and Target firmware! 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistruct ce_pipe_config { 7162306a36Sopenharmony_ci __le32 pipenum; 7262306a36Sopenharmony_ci __le32 pipedir; 7362306a36Sopenharmony_ci __le32 nentries; 7462306a36Sopenharmony_ci __le32 nbytes_max; 7562306a36Sopenharmony_ci __le32 flags; 7662306a36Sopenharmony_ci __le32 reserved; 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistruct ce_attr { 8062306a36Sopenharmony_ci /* CE_ATTR_* values */ 8162306a36Sopenharmony_ci unsigned int flags; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* #entries in source ring - Must be a power of 2 */ 8462306a36Sopenharmony_ci unsigned int src_nentries; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* Max source send size for this CE. 8762306a36Sopenharmony_ci * This is also the minimum size of a destination buffer. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci unsigned int src_sz_max; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* #entries in destination ring - Must be a power of 2 */ 9262306a36Sopenharmony_ci unsigned int dest_nentries; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb); 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define CE_DESC_RING_ALIGN 8 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct ath12k_ce_ring { 10062306a36Sopenharmony_ci /* Number of entries in this ring; must be power of 2 */ 10162306a36Sopenharmony_ci unsigned int nentries; 10262306a36Sopenharmony_ci unsigned int nentries_mask; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* For dest ring, this is the next index to be processed 10562306a36Sopenharmony_ci * by software after it was/is received into. 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * For src ring, this is the last descriptor that was sent 10862306a36Sopenharmony_ci * and completion processed by software. 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * Regardless of src or dest ring, this is an invariant 11162306a36Sopenharmony_ci * (modulo ring size): 11262306a36Sopenharmony_ci * write index >= read index >= sw_index 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci unsigned int sw_index; 11562306a36Sopenharmony_ci /* cached copy */ 11662306a36Sopenharmony_ci unsigned int write_index; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* Start of DMA-coherent area reserved for descriptors */ 11962306a36Sopenharmony_ci /* Host address space */ 12062306a36Sopenharmony_ci void *base_addr_owner_space_unaligned; 12162306a36Sopenharmony_ci /* CE address space */ 12262306a36Sopenharmony_ci u32 base_addr_ce_space_unaligned; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci /* Actual start of descriptors. 12562306a36Sopenharmony_ci * Aligned to descriptor-size boundary. 12662306a36Sopenharmony_ci * Points into reserved DMA-coherent area, above. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci /* Host address space */ 12962306a36Sopenharmony_ci void *base_addr_owner_space; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* CE address space */ 13262306a36Sopenharmony_ci u32 base_addr_ce_space; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* HAL ring id */ 13562306a36Sopenharmony_ci u32 hal_ring_id; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* keep last */ 13862306a36Sopenharmony_ci struct sk_buff *skb[]; 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistruct ath12k_ce_pipe { 14262306a36Sopenharmony_ci struct ath12k_base *ab; 14362306a36Sopenharmony_ci u16 pipe_num; 14462306a36Sopenharmony_ci unsigned int attr_flags; 14562306a36Sopenharmony_ci unsigned int buf_sz; 14662306a36Sopenharmony_ci unsigned int rx_buf_needed; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci void (*send_cb)(struct ath12k_ce_pipe *pipe); 14962306a36Sopenharmony_ci void (*recv_cb)(struct ath12k_base *ab, struct sk_buff *skb); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci struct tasklet_struct intr_tq; 15262306a36Sopenharmony_ci struct ath12k_ce_ring *src_ring; 15362306a36Sopenharmony_ci struct ath12k_ce_ring *dest_ring; 15462306a36Sopenharmony_ci struct ath12k_ce_ring *status_ring; 15562306a36Sopenharmony_ci u64 timestamp; 15662306a36Sopenharmony_ci}; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistruct ath12k_ce { 15962306a36Sopenharmony_ci struct ath12k_ce_pipe ce_pipe[CE_COUNT_MAX]; 16062306a36Sopenharmony_ci /* Protects rings of all ce pipes */ 16162306a36Sopenharmony_ci spinlock_t ce_lock; 16262306a36Sopenharmony_ci struct ath12k_hp_update_timer hp_timer[CE_COUNT_MAX]; 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciextern const struct ce_attr ath12k_host_ce_config_qcn9274[]; 16662306a36Sopenharmony_ciextern const struct ce_attr ath12k_host_ce_config_wcn7850[]; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_civoid ath12k_ce_cleanup_pipes(struct ath12k_base *ab); 16962306a36Sopenharmony_civoid ath12k_ce_rx_replenish_retry(struct timer_list *t); 17062306a36Sopenharmony_civoid ath12k_ce_per_engine_service(struct ath12k_base *ab, u16 ce_id); 17162306a36Sopenharmony_ciint ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id, 17262306a36Sopenharmony_ci u16 transfer_id); 17362306a36Sopenharmony_civoid ath12k_ce_rx_post_buf(struct ath12k_base *ab); 17462306a36Sopenharmony_ciint ath12k_ce_init_pipes(struct ath12k_base *ab); 17562306a36Sopenharmony_ciint ath12k_ce_alloc_pipes(struct ath12k_base *ab); 17662306a36Sopenharmony_civoid ath12k_ce_free_pipes(struct ath12k_base *ab); 17762306a36Sopenharmony_ciint ath12k_ce_get_attr_flags(struct ath12k_base *ab, int ce_id); 17862306a36Sopenharmony_civoid ath12k_ce_poll_send_completed(struct ath12k_base *ab, u8 pipe_id); 17962306a36Sopenharmony_civoid ath12k_ce_get_shadow_config(struct ath12k_base *ab, 18062306a36Sopenharmony_ci u32 **shadow_cfg, u32 *shadow_cfg_len); 18162306a36Sopenharmony_ci#endif 182