162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (C) 2018-2023 Linaro Ltd. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef _GSI_H_ 762306a36Sopenharmony_ci#define _GSI_H_ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/spinlock.h> 1162306a36Sopenharmony_ci#include <linux/mutex.h> 1262306a36Sopenharmony_ci#include <linux/completion.h> 1362306a36Sopenharmony_ci#include <linux/platform_device.h> 1462306a36Sopenharmony_ci#include <linux/netdevice.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "ipa_version.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Maximum number of channels and event rings supported by the driver */ 1962306a36Sopenharmony_ci#define GSI_CHANNEL_COUNT_MAX 28 2062306a36Sopenharmony_ci#define GSI_EVT_RING_COUNT_MAX 28 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Maximum TLV FIFO size for a channel; 64 here is arbitrary (and high) */ 2362306a36Sopenharmony_ci#define GSI_TLV_MAX 64 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct device; 2662306a36Sopenharmony_cistruct scatterlist; 2762306a36Sopenharmony_cistruct platform_device; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct gsi; 3062306a36Sopenharmony_cistruct gsi_trans; 3162306a36Sopenharmony_cistruct gsi_channel_data; 3262306a36Sopenharmony_cistruct ipa_gsi_endpoint_data; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct gsi_ring { 3562306a36Sopenharmony_ci void *virt; /* ring array base address */ 3662306a36Sopenharmony_ci dma_addr_t addr; /* primarily low 32 bits used */ 3762306a36Sopenharmony_ci u32 count; /* number of elements in ring */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* The ring index value indicates the next "open" entry in the ring. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * A channel ring consists of TRE entries filled by the AP and passed 4262306a36Sopenharmony_ci * to the hardware for processing. For a channel ring, the ring index 4362306a36Sopenharmony_ci * identifies the next unused entry to be filled by the AP. In this 4462306a36Sopenharmony_ci * case the initial value is assumed by hardware to be 0. 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * An event ring consists of event structures filled by the hardware 4762306a36Sopenharmony_ci * and passed to the AP. For event rings, the ring index identifies 4862306a36Sopenharmony_ci * the next ring entry that is not known to have been filled by the 4962306a36Sopenharmony_ci * hardware. The initial value used is arbitrary (so we use 0). 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci u32 index; 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Transactions use several resources that can be allocated dynamically 5562306a36Sopenharmony_ci * but taken from a fixed-size pool. The number of elements required for 5662306a36Sopenharmony_ci * the pool is limited by the total number of TREs that can be outstanding. 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * If sufficient TREs are available to reserve for a transaction, 5962306a36Sopenharmony_ci * allocation from these pools is guaranteed to succeed. Furthermore, 6062306a36Sopenharmony_ci * these resources are implicitly freed whenever the TREs in the 6162306a36Sopenharmony_ci * transaction they're associated with are released. 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * The result of a pool allocation of multiple elements is always 6462306a36Sopenharmony_ci * contiguous. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_cistruct gsi_trans_pool { 6762306a36Sopenharmony_ci void *base; /* base address of element pool */ 6862306a36Sopenharmony_ci u32 count; /* # elements in the pool */ 6962306a36Sopenharmony_ci u32 free; /* next free element in pool (modulo) */ 7062306a36Sopenharmony_ci u32 size; /* size (bytes) of an element */ 7162306a36Sopenharmony_ci u32 max_alloc; /* max allocation request */ 7262306a36Sopenharmony_ci dma_addr_t addr; /* DMA address if DMA pool (or 0) */ 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct gsi_trans_info { 7662306a36Sopenharmony_ci atomic_t tre_avail; /* TREs available for allocation */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci u16 free_id; /* first free trans in array */ 7962306a36Sopenharmony_ci u16 allocated_id; /* first allocated transaction */ 8062306a36Sopenharmony_ci u16 committed_id; /* first committed transaction */ 8162306a36Sopenharmony_ci u16 pending_id; /* first pending transaction */ 8262306a36Sopenharmony_ci u16 completed_id; /* first completed transaction */ 8362306a36Sopenharmony_ci u16 polled_id; /* first polled transaction */ 8462306a36Sopenharmony_ci struct gsi_trans *trans; /* transaction array */ 8562306a36Sopenharmony_ci struct gsi_trans **map; /* TRE -> transaction map */ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci struct gsi_trans_pool sg_pool; /* scatterlist pool */ 8862306a36Sopenharmony_ci struct gsi_trans_pool cmd_pool; /* command payload DMA pool */ 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* Hardware values signifying the state of a channel */ 9262306a36Sopenharmony_cienum gsi_channel_state { 9362306a36Sopenharmony_ci GSI_CHANNEL_STATE_NOT_ALLOCATED = 0x0, 9462306a36Sopenharmony_ci GSI_CHANNEL_STATE_ALLOCATED = 0x1, 9562306a36Sopenharmony_ci GSI_CHANNEL_STATE_STARTED = 0x2, 9662306a36Sopenharmony_ci GSI_CHANNEL_STATE_STOPPED = 0x3, 9762306a36Sopenharmony_ci GSI_CHANNEL_STATE_STOP_IN_PROC = 0x4, 9862306a36Sopenharmony_ci GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2-v4.9 */ 9962306a36Sopenharmony_ci GSI_CHANNEL_STATE_ERROR = 0xf, 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* We only care about channels between IPA and AP */ 10362306a36Sopenharmony_cistruct gsi_channel { 10462306a36Sopenharmony_ci struct gsi *gsi; 10562306a36Sopenharmony_ci bool toward_ipa; 10662306a36Sopenharmony_ci bool command; /* AP command TX channel or not */ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci u8 trans_tre_max; /* max TREs in a transaction */ 10962306a36Sopenharmony_ci u16 tre_count; 11062306a36Sopenharmony_ci u16 event_count; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci struct gsi_ring tre_ring; 11362306a36Sopenharmony_ci u32 evt_ring_id; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* The following counts are used only for TX endpoints */ 11662306a36Sopenharmony_ci u64 byte_count; /* total # bytes transferred */ 11762306a36Sopenharmony_ci u64 trans_count; /* total # transactions */ 11862306a36Sopenharmony_ci u64 queued_byte_count; /* last reported queued byte count */ 11962306a36Sopenharmony_ci u64 queued_trans_count; /* ...and queued trans count */ 12062306a36Sopenharmony_ci u64 compl_byte_count; /* last reported completed byte count */ 12162306a36Sopenharmony_ci u64 compl_trans_count; /* ...and completed trans count */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci struct gsi_trans_info trans_info; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci struct napi_struct napi; 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* Hardware values signifying the state of an event ring */ 12962306a36Sopenharmony_cienum gsi_evt_ring_state { 13062306a36Sopenharmony_ci GSI_EVT_RING_STATE_NOT_ALLOCATED = 0x0, 13162306a36Sopenharmony_ci GSI_EVT_RING_STATE_ALLOCATED = 0x1, 13262306a36Sopenharmony_ci GSI_EVT_RING_STATE_ERROR = 0xf, 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistruct gsi_evt_ring { 13662306a36Sopenharmony_ci struct gsi_channel *channel; 13762306a36Sopenharmony_ci struct gsi_ring ring; 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistruct gsi { 14162306a36Sopenharmony_ci struct device *dev; /* Same as IPA device */ 14262306a36Sopenharmony_ci enum ipa_version version; 14362306a36Sopenharmony_ci void __iomem *virt; /* I/O mapped registers */ 14462306a36Sopenharmony_ci const struct regs *regs; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci u32 irq; 14762306a36Sopenharmony_ci u32 channel_count; 14862306a36Sopenharmony_ci u32 evt_ring_count; 14962306a36Sopenharmony_ci u32 event_bitmap; /* allocated event rings */ 15062306a36Sopenharmony_ci u32 modem_channel_bitmap; /* modem channels to allocate */ 15162306a36Sopenharmony_ci u32 type_enabled_bitmap; /* GSI IRQ types enabled */ 15262306a36Sopenharmony_ci u32 ieob_enabled_bitmap; /* IEOB IRQ enabled (event rings) */ 15362306a36Sopenharmony_ci int result; /* Negative errno (generic commands) */ 15462306a36Sopenharmony_ci struct completion completion; /* Signals GSI command completion */ 15562306a36Sopenharmony_ci struct mutex mutex; /* protects commands, programming */ 15662306a36Sopenharmony_ci struct gsi_channel channel[GSI_CHANNEL_COUNT_MAX]; 15762306a36Sopenharmony_ci struct gsi_evt_ring evt_ring[GSI_EVT_RING_COUNT_MAX]; 15862306a36Sopenharmony_ci struct net_device dummy_dev; /* needed for NAPI */ 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/** 16262306a36Sopenharmony_ci * gsi_setup() - Set up the GSI subsystem 16362306a36Sopenharmony_ci * @gsi: Address of GSI structure embedded in an IPA structure 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * Return: 0 if successful, or a negative error code 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * Performs initialization that must wait until the GSI hardware is 16862306a36Sopenharmony_ci * ready (including firmware loaded). 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ciint gsi_setup(struct gsi *gsi); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/** 17362306a36Sopenharmony_ci * gsi_teardown() - Tear down GSI subsystem 17462306a36Sopenharmony_ci * @gsi: GSI address previously passed to a successful gsi_setup() call 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_civoid gsi_teardown(struct gsi *gsi); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/** 17962306a36Sopenharmony_ci * gsi_channel_tre_max() - Channel maximum number of in-flight TREs 18062306a36Sopenharmony_ci * @gsi: GSI pointer 18162306a36Sopenharmony_ci * @channel_id: Channel whose limit is to be returned 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * Return: The maximum number of TREs outstanding on the channel 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ciu32 gsi_channel_tre_max(struct gsi *gsi, u32 channel_id); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/** 18862306a36Sopenharmony_ci * gsi_channel_start() - Start an allocated GSI channel 18962306a36Sopenharmony_ci * @gsi: GSI pointer 19062306a36Sopenharmony_ci * @channel_id: Channel to start 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * Return: 0 if successful, or a negative error code 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_ciint gsi_channel_start(struct gsi *gsi, u32 channel_id); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/** 19762306a36Sopenharmony_ci * gsi_channel_stop() - Stop a started GSI channel 19862306a36Sopenharmony_ci * @gsi: GSI pointer returned by gsi_setup() 19962306a36Sopenharmony_ci * @channel_id: Channel to stop 20062306a36Sopenharmony_ci * 20162306a36Sopenharmony_ci * Return: 0 if successful, or a negative error code 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ciint gsi_channel_stop(struct gsi *gsi, u32 channel_id); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/** 20662306a36Sopenharmony_ci * gsi_modem_channel_flow_control() - Set channel flow control state (IPA v4.2+) 20762306a36Sopenharmony_ci * @gsi: GSI pointer returned by gsi_setup() 20862306a36Sopenharmony_ci * @channel_id: Modem TX channel to control 20962306a36Sopenharmony_ci * @enable: Whether to enable flow control (i.e., prevent flow) 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_civoid gsi_modem_channel_flow_control(struct gsi *gsi, u32 channel_id, 21262306a36Sopenharmony_ci bool enable); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/** 21562306a36Sopenharmony_ci * gsi_channel_reset() - Reset an allocated GSI channel 21662306a36Sopenharmony_ci * @gsi: GSI pointer 21762306a36Sopenharmony_ci * @channel_id: Channel to be reset 21862306a36Sopenharmony_ci * @doorbell: Whether to (possibly) enable the doorbell engine 21962306a36Sopenharmony_ci * 22062306a36Sopenharmony_ci * Reset a channel and reconfigure it. The @doorbell flag indicates 22162306a36Sopenharmony_ci * that the doorbell engine should be enabled if needed. 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * GSI hardware relinquishes ownership of all pending receive buffer 22462306a36Sopenharmony_ci * transactions and they will complete with their cancelled flag set. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_civoid gsi_channel_reset(struct gsi *gsi, u32 channel_id, bool doorbell); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci/** 22962306a36Sopenharmony_ci * gsi_suspend() - Prepare the GSI subsystem for suspend 23062306a36Sopenharmony_ci * @gsi: GSI pointer 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_civoid gsi_suspend(struct gsi *gsi); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/** 23562306a36Sopenharmony_ci * gsi_resume() - Resume the GSI subsystem following suspend 23662306a36Sopenharmony_ci * @gsi: GSI pointer 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_civoid gsi_resume(struct gsi *gsi); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/** 24162306a36Sopenharmony_ci * gsi_channel_suspend() - Suspend a GSI channel 24262306a36Sopenharmony_ci * @gsi: GSI pointer 24362306a36Sopenharmony_ci * @channel_id: Channel to suspend 24462306a36Sopenharmony_ci * 24562306a36Sopenharmony_ci * For IPA v4.0+, suspend is implemented by stopping the channel. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ciint gsi_channel_suspend(struct gsi *gsi, u32 channel_id); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/** 25062306a36Sopenharmony_ci * gsi_channel_resume() - Resume a suspended GSI channel 25162306a36Sopenharmony_ci * @gsi: GSI pointer 25262306a36Sopenharmony_ci * @channel_id: Channel to resume 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * For IPA v4.0+, the stopped channel is started again. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_ciint gsi_channel_resume(struct gsi *gsi, u32 channel_id); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/** 25962306a36Sopenharmony_ci * gsi_init() - Initialize the GSI subsystem 26062306a36Sopenharmony_ci * @gsi: Address of GSI structure embedded in an IPA structure 26162306a36Sopenharmony_ci * @pdev: IPA platform device 26262306a36Sopenharmony_ci * @version: IPA hardware version (implies GSI version) 26362306a36Sopenharmony_ci * @count: Number of entries in the configuration data array 26462306a36Sopenharmony_ci * @data: Endpoint and channel configuration data 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * Return: 0 if successful, or a negative error code 26762306a36Sopenharmony_ci * 26862306a36Sopenharmony_ci * Early stage initialization of the GSI subsystem, performing tasks 26962306a36Sopenharmony_ci * that can be done before the GSI hardware is ready to use. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_ciint gsi_init(struct gsi *gsi, struct platform_device *pdev, 27262306a36Sopenharmony_ci enum ipa_version version, u32 count, 27362306a36Sopenharmony_ci const struct ipa_gsi_endpoint_data *data); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/** 27662306a36Sopenharmony_ci * gsi_exit() - Exit the GSI subsystem 27762306a36Sopenharmony_ci * @gsi: GSI address previously passed to a successful gsi_init() call 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_civoid gsi_exit(struct gsi *gsi); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#endif /* _GSI_H_ */ 282