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