162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * NXP Wireless LAN device driver: SDIO specific definitions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2011-2020 NXP
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef	_MWIFIEX_SDIO_H
962306a36Sopenharmony_ci#define	_MWIFIEX_SDIO_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/completion.h>
1362306a36Sopenharmony_ci#include <linux/mmc/sdio.h>
1462306a36Sopenharmony_ci#include <linux/mmc/sdio_ids.h>
1562306a36Sopenharmony_ci#include <linux/mmc/sdio_func.h>
1662306a36Sopenharmony_ci#include <linux/mmc/card.h>
1762306a36Sopenharmony_ci#include <linux/mmc/host.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "main.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin"
2262306a36Sopenharmony_ci#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin"
2362306a36Sopenharmony_ci#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin"
2462306a36Sopenharmony_ci#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
2562306a36Sopenharmony_ci#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
2662306a36Sopenharmony_ci#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
2762306a36Sopenharmony_ci#define SD8977_DEFAULT_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
2862306a36Sopenharmony_ci#define SD8978_SDIOUART_FW_NAME "mrvl/sdiouartiw416_combo_v0.bin"
2962306a36Sopenharmony_ci#define SD8987_DEFAULT_FW_NAME "mrvl/sd8987_uapsta.bin"
3062306a36Sopenharmony_ci#define SD8997_DEFAULT_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
3162306a36Sopenharmony_ci#define SD8997_SDIOUART_FW_NAME "mrvl/sdiouart8997_combo_v4.bin"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define BLOCK_MODE	1
3462306a36Sopenharmony_ci#define BYTE_MODE	0
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define MWIFIEX_SDIO_IO_PORT_MASK		0xfffff
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define MWIFIEX_SDIO_BYTE_MODE_MASK	0x80000000
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define MWIFIEX_MAX_FUNC2_REG_NUM	13
4162306a36Sopenharmony_ci#define MWIFIEX_SDIO_SCRATCH_SIZE	10
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define SDIO_MPA_ADDR_BASE		0x1000
4462306a36Sopenharmony_ci#define CTRL_PORT			0
4562306a36Sopenharmony_ci#define CTRL_PORT_MASK			0x0001
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define CMD_PORT_UPLD_INT_MASK		(0x1U<<6)
4862306a36Sopenharmony_ci#define CMD_PORT_DNLD_INT_MASK		(0x1U<<7)
4962306a36Sopenharmony_ci#define HOST_TERM_CMD53			(0x1U << 2)
5062306a36Sopenharmony_ci#define REG_PORT			0
5162306a36Sopenharmony_ci#define MEM_PORT			0x10000
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define CMD53_NEW_MODE			(0x1U << 0)
5462306a36Sopenharmony_ci#define CMD_PORT_RD_LEN_EN		(0x1U << 2)
5562306a36Sopenharmony_ci#define CMD_PORT_AUTO_EN		(0x1U << 0)
5662306a36Sopenharmony_ci#define CMD_PORT_SLCT			0x8000
5762306a36Sopenharmony_ci#define UP_LD_CMD_PORT_HOST_INT_STATUS	(0x40U)
5862306a36Sopenharmony_ci#define DN_LD_CMD_PORT_HOST_INT_STATUS	(0x80U)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define MWIFIEX_MP_AGGR_BUF_SIZE_16K	(16384)
6162306a36Sopenharmony_ci#define MWIFIEX_MP_AGGR_BUF_SIZE_32K	(32768)
6262306a36Sopenharmony_ci/* we leave one block of 256 bytes for DMA alignment*/
6362306a36Sopenharmony_ci#define MWIFIEX_MP_AGGR_BUF_SIZE_MAX    (65280)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* Misc. Config Register : Auto Re-enable interrupts */
6662306a36Sopenharmony_ci#define AUTO_RE_ENABLE_INT              BIT(4)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Host Control Registers : Configuration */
6962306a36Sopenharmony_ci#define CONFIGURATION_REG		0x00
7062306a36Sopenharmony_ci/* Host Control Registers : Host power up */
7162306a36Sopenharmony_ci#define HOST_POWER_UP			(0x1U << 1)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* Host Control Registers : Upload host interrupt mask */
7462306a36Sopenharmony_ci#define UP_LD_HOST_INT_MASK		(0x1U)
7562306a36Sopenharmony_ci/* Host Control Registers : Download host interrupt mask */
7662306a36Sopenharmony_ci#define DN_LD_HOST_INT_MASK		(0x2U)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* Host Control Registers : Upload host interrupt status */
7962306a36Sopenharmony_ci#define UP_LD_HOST_INT_STATUS		(0x1U)
8062306a36Sopenharmony_ci/* Host Control Registers : Download host interrupt status */
8162306a36Sopenharmony_ci#define DN_LD_HOST_INT_STATUS		(0x2U)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* Host Control Registers : Host interrupt status */
8462306a36Sopenharmony_ci#define CARD_INT_STATUS_REG		0x28
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* Card Control Registers : Card I/O ready */
8762306a36Sopenharmony_ci#define CARD_IO_READY                   (0x1U << 3)
8862306a36Sopenharmony_ci/* Card Control Registers : Download card ready */
8962306a36Sopenharmony_ci#define DN_LD_CARD_RDY                  (0x1U << 0)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* Max retry number of CMD53 write */
9262306a36Sopenharmony_ci#define MAX_WRITE_IOMEM_RETRY		2
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* SDIO Tx aggregation in progress ? */
9562306a36Sopenharmony_ci#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0)
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/* SDIO Tx aggregation buffer room for next packet ? */
9862306a36Sopenharmony_ci#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len)	\
9962306a36Sopenharmony_ci						<= a->mpa_tx.buf_size)
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */
10262306a36Sopenharmony_ci#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do {		\
10362306a36Sopenharmony_ci	memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len],			\
10462306a36Sopenharmony_ci			payload, pkt_len);				\
10562306a36Sopenharmony_ci	a->mpa_tx.buf_len += pkt_len;					\
10662306a36Sopenharmony_ci	if (!a->mpa_tx.pkt_cnt)						\
10762306a36Sopenharmony_ci		a->mpa_tx.start_port = port;				\
10862306a36Sopenharmony_ci	if (a->mpa_tx.start_port <= port)				\
10962306a36Sopenharmony_ci		a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt));		\
11062306a36Sopenharmony_ci	else								\
11162306a36Sopenharmony_ci		a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+		\
11262306a36Sopenharmony_ci						(a->max_ports -	\
11362306a36Sopenharmony_ci						a->mp_end_port)));	\
11462306a36Sopenharmony_ci	a->mpa_tx.pkt_cnt++;						\
11562306a36Sopenharmony_ci} while (0)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/* SDIO Tx aggregation limit ? */
11862306a36Sopenharmony_ci#define MP_TX_AGGR_PKT_LIMIT_REACHED(a)					\
11962306a36Sopenharmony_ci			(a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit)
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* Reset SDIO Tx aggregation buffer parameters */
12262306a36Sopenharmony_ci#define MP_TX_AGGR_BUF_RESET(a) do {					\
12362306a36Sopenharmony_ci	a->mpa_tx.pkt_cnt = 0;						\
12462306a36Sopenharmony_ci	a->mpa_tx.buf_len = 0;						\
12562306a36Sopenharmony_ci	a->mpa_tx.ports = 0;						\
12662306a36Sopenharmony_ci	a->mpa_tx.start_port = 0;					\
12762306a36Sopenharmony_ci} while (0)
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/* SDIO Rx aggregation limit ? */
13062306a36Sopenharmony_ci#define MP_RX_AGGR_PKT_LIMIT_REACHED(a)					\
13162306a36Sopenharmony_ci			(a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit)
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/* SDIO Rx aggregation in progress ? */
13462306a36Sopenharmony_ci#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/* SDIO Rx aggregation buffer room for next packet ? */
13762306a36Sopenharmony_ci#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len)				\
13862306a36Sopenharmony_ci			((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size)
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/* Reset SDIO Rx aggregation buffer parameters */
14162306a36Sopenharmony_ci#define MP_RX_AGGR_BUF_RESET(a) do {					\
14262306a36Sopenharmony_ci	a->mpa_rx.pkt_cnt = 0;						\
14362306a36Sopenharmony_ci	a->mpa_rx.buf_len = 0;						\
14462306a36Sopenharmony_ci	a->mpa_rx.ports = 0;						\
14562306a36Sopenharmony_ci	a->mpa_rx.start_port = 0;					\
14662306a36Sopenharmony_ci} while (0)
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/* data structure for SDIO MPA TX */
14962306a36Sopenharmony_cistruct mwifiex_sdio_mpa_tx {
15062306a36Sopenharmony_ci	/* multiport tx aggregation buffer pointer */
15162306a36Sopenharmony_ci	u8 *buf;
15262306a36Sopenharmony_ci	u32 buf_len;
15362306a36Sopenharmony_ci	u32 pkt_cnt;
15462306a36Sopenharmony_ci	u32 ports;
15562306a36Sopenharmony_ci	u16 start_port;
15662306a36Sopenharmony_ci	u8 enabled;
15762306a36Sopenharmony_ci	u32 buf_size;
15862306a36Sopenharmony_ci	u32 pkt_aggr_limit;
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistruct mwifiex_sdio_mpa_rx {
16262306a36Sopenharmony_ci	u8 *buf;
16362306a36Sopenharmony_ci	u32 buf_len;
16462306a36Sopenharmony_ci	u32 pkt_cnt;
16562306a36Sopenharmony_ci	u32 ports;
16662306a36Sopenharmony_ci	u16 start_port;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	struct sk_buff **skb_arr;
16962306a36Sopenharmony_ci	u32 *len_arr;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	u8 enabled;
17262306a36Sopenharmony_ci	u32 buf_size;
17362306a36Sopenharmony_ci	u32 pkt_aggr_limit;
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ciint mwifiex_bus_register(void);
17762306a36Sopenharmony_civoid mwifiex_bus_unregister(void);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistruct mwifiex_sdio_card_reg {
18062306a36Sopenharmony_ci	u8 start_rd_port;
18162306a36Sopenharmony_ci	u8 start_wr_port;
18262306a36Sopenharmony_ci	u8 base_0_reg;
18362306a36Sopenharmony_ci	u8 base_1_reg;
18462306a36Sopenharmony_ci	u8 poll_reg;
18562306a36Sopenharmony_ci	u8 host_int_enable;
18662306a36Sopenharmony_ci	u8 host_int_rsr_reg;
18762306a36Sopenharmony_ci	u8 host_int_status_reg;
18862306a36Sopenharmony_ci	u8 host_int_mask_reg;
18962306a36Sopenharmony_ci	u8 host_strap_reg;
19062306a36Sopenharmony_ci	u8 host_strap_mask;
19162306a36Sopenharmony_ci	u8 host_strap_value;
19262306a36Sopenharmony_ci	u8 status_reg_0;
19362306a36Sopenharmony_ci	u8 status_reg_1;
19462306a36Sopenharmony_ci	u8 sdio_int_mask;
19562306a36Sopenharmony_ci	u32 data_port_mask;
19662306a36Sopenharmony_ci	u8 io_port_0_reg;
19762306a36Sopenharmony_ci	u8 io_port_1_reg;
19862306a36Sopenharmony_ci	u8 io_port_2_reg;
19962306a36Sopenharmony_ci	u8 max_mp_regs;
20062306a36Sopenharmony_ci	u8 rd_bitmap_l;
20162306a36Sopenharmony_ci	u8 rd_bitmap_u;
20262306a36Sopenharmony_ci	u8 rd_bitmap_1l;
20362306a36Sopenharmony_ci	u8 rd_bitmap_1u;
20462306a36Sopenharmony_ci	u8 wr_bitmap_l;
20562306a36Sopenharmony_ci	u8 wr_bitmap_u;
20662306a36Sopenharmony_ci	u8 wr_bitmap_1l;
20762306a36Sopenharmony_ci	u8 wr_bitmap_1u;
20862306a36Sopenharmony_ci	u8 rd_len_p0_l;
20962306a36Sopenharmony_ci	u8 rd_len_p0_u;
21062306a36Sopenharmony_ci	u8 card_misc_cfg_reg;
21162306a36Sopenharmony_ci	u8 card_cfg_2_1_reg;
21262306a36Sopenharmony_ci	u8 cmd_rd_len_0;
21362306a36Sopenharmony_ci	u8 cmd_rd_len_1;
21462306a36Sopenharmony_ci	u8 cmd_rd_len_2;
21562306a36Sopenharmony_ci	u8 cmd_rd_len_3;
21662306a36Sopenharmony_ci	u8 cmd_cfg_0;
21762306a36Sopenharmony_ci	u8 cmd_cfg_1;
21862306a36Sopenharmony_ci	u8 cmd_cfg_2;
21962306a36Sopenharmony_ci	u8 cmd_cfg_3;
22062306a36Sopenharmony_ci	u8 fw_dump_host_ready;
22162306a36Sopenharmony_ci	u8 fw_dump_ctrl;
22262306a36Sopenharmony_ci	u8 fw_dump_start;
22362306a36Sopenharmony_ci	u8 fw_dump_end;
22462306a36Sopenharmony_ci	u8 func1_dump_reg_start;
22562306a36Sopenharmony_ci	u8 func1_dump_reg_end;
22662306a36Sopenharmony_ci	u8 func1_scratch_reg;
22762306a36Sopenharmony_ci	u8 func1_spec_reg_num;
22862306a36Sopenharmony_ci	u8 func1_spec_reg_table[MWIFIEX_MAX_FUNC2_REG_NUM];
22962306a36Sopenharmony_ci};
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistruct sdio_mmc_card {
23262306a36Sopenharmony_ci	struct sdio_func *func;
23362306a36Sopenharmony_ci	struct mwifiex_adapter *adapter;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	struct completion fw_done;
23662306a36Sopenharmony_ci	const char *firmware;
23762306a36Sopenharmony_ci	const char *firmware_sdiouart;
23862306a36Sopenharmony_ci	const struct mwifiex_sdio_card_reg *reg;
23962306a36Sopenharmony_ci	u8 max_ports;
24062306a36Sopenharmony_ci	u8 mp_agg_pkt_limit;
24162306a36Sopenharmony_ci	u16 tx_buf_size;
24262306a36Sopenharmony_ci	u32 mp_tx_agg_buf_size;
24362306a36Sopenharmony_ci	u32 mp_rx_agg_buf_size;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	u32 mp_rd_bitmap;
24662306a36Sopenharmony_ci	u32 mp_wr_bitmap;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	u16 mp_end_port;
24962306a36Sopenharmony_ci	u32 mp_data_port_mask;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	u8 curr_rd_port;
25262306a36Sopenharmony_ci	u8 curr_wr_port;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	u8 *mp_regs;
25562306a36Sopenharmony_ci	bool supports_sdio_new_mode;
25662306a36Sopenharmony_ci	bool has_control_mask;
25762306a36Sopenharmony_ci	bool can_dump_fw;
25862306a36Sopenharmony_ci	bool fw_dump_enh;
25962306a36Sopenharmony_ci	bool can_auto_tdls;
26062306a36Sopenharmony_ci	bool can_ext_scan;
26162306a36Sopenharmony_ci	bool fw_ready_extra_delay;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	struct mwifiex_sdio_mpa_tx mpa_tx;
26462306a36Sopenharmony_ci	struct mwifiex_sdio_mpa_rx mpa_rx;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	struct work_struct work;
26762306a36Sopenharmony_ci	unsigned long work_flags;
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistruct mwifiex_sdio_device {
27162306a36Sopenharmony_ci	const char *firmware;
27262306a36Sopenharmony_ci	const char *firmware_sdiouart;
27362306a36Sopenharmony_ci	const struct mwifiex_sdio_card_reg *reg;
27462306a36Sopenharmony_ci	u8 max_ports;
27562306a36Sopenharmony_ci	u8 mp_agg_pkt_limit;
27662306a36Sopenharmony_ci	u16 tx_buf_size;
27762306a36Sopenharmony_ci	u32 mp_tx_agg_buf_size;
27862306a36Sopenharmony_ci	u32 mp_rx_agg_buf_size;
27962306a36Sopenharmony_ci	bool supports_sdio_new_mode;
28062306a36Sopenharmony_ci	bool has_control_mask;
28162306a36Sopenharmony_ci	bool can_dump_fw;
28262306a36Sopenharmony_ci	bool fw_dump_enh;
28362306a36Sopenharmony_ci	bool can_auto_tdls;
28462306a36Sopenharmony_ci	bool can_ext_scan;
28562306a36Sopenharmony_ci	bool fw_ready_extra_delay;
28662306a36Sopenharmony_ci};
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci/*
28962306a36Sopenharmony_ci * .cmdrsp_complete handler
29062306a36Sopenharmony_ci */
29162306a36Sopenharmony_cistatic inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter,
29262306a36Sopenharmony_ci					       struct sk_buff *skb)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
29562306a36Sopenharmony_ci	return 0;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci/*
29962306a36Sopenharmony_ci * .event_complete handler
30062306a36Sopenharmony_ci */
30162306a36Sopenharmony_cistatic inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter,
30262306a36Sopenharmony_ci					      struct sk_buff *skb)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
30562306a36Sopenharmony_ci	return 0;
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic inline bool
30962306a36Sopenharmony_cimp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	u8 tmp;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (card->curr_rd_port < card->mpa_rx.start_port) {
31462306a36Sopenharmony_ci		if (card->supports_sdio_new_mode)
31562306a36Sopenharmony_ci			tmp = card->mp_end_port >> 1;
31662306a36Sopenharmony_ci		else
31762306a36Sopenharmony_ci			tmp = card->mp_agg_pkt_limit;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		if (((card->max_ports - card->mpa_rx.start_port) +
32062306a36Sopenharmony_ci		    card->curr_rd_port) >= tmp)
32162306a36Sopenharmony_ci			return true;
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if (!card->supports_sdio_new_mode)
32562306a36Sopenharmony_ci		return false;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	if ((card->curr_rd_port - card->mpa_rx.start_port) >=
32862306a36Sopenharmony_ci	    (card->mp_end_port >> 1))
32962306a36Sopenharmony_ci		return true;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	return false;
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic inline bool
33562306a36Sopenharmony_cimp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	u16 tmp;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	if (card->curr_wr_port < card->mpa_tx.start_port) {
34062306a36Sopenharmony_ci		if (card->supports_sdio_new_mode)
34162306a36Sopenharmony_ci			tmp = card->mp_end_port >> 1;
34262306a36Sopenharmony_ci		else
34362306a36Sopenharmony_ci			tmp = card->mp_agg_pkt_limit;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		if (((card->max_ports - card->mpa_tx.start_port) +
34662306a36Sopenharmony_ci		    card->curr_wr_port) >= tmp)
34762306a36Sopenharmony_ci			return true;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	if (!card->supports_sdio_new_mode)
35162306a36Sopenharmony_ci		return false;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if ((card->curr_wr_port - card->mpa_tx.start_port) >=
35462306a36Sopenharmony_ci	    (card->mp_end_port >> 1))
35562306a36Sopenharmony_ci		return true;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	return false;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */
36162306a36Sopenharmony_cistatic inline void mp_rx_aggr_setup(struct sdio_mmc_card *card,
36262306a36Sopenharmony_ci				    u16 rx_len, u8 port)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	card->mpa_rx.buf_len += rx_len;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	if (!card->mpa_rx.pkt_cnt)
36762306a36Sopenharmony_ci		card->mpa_rx.start_port = port;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	if (card->supports_sdio_new_mode) {
37062306a36Sopenharmony_ci		card->mpa_rx.ports |= (1 << port);
37162306a36Sopenharmony_ci	} else {
37262306a36Sopenharmony_ci		if (card->mpa_rx.start_port <= port)
37362306a36Sopenharmony_ci			card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt);
37462306a36Sopenharmony_ci		else
37562306a36Sopenharmony_ci			card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1);
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci	card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL;
37862306a36Sopenharmony_ci	card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len;
37962306a36Sopenharmony_ci	card->mpa_rx.pkt_cnt++;
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci#endif /* _MWIFIEX_SDIO_H */
382