18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: ISC */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2004-2011 Atheros Communications Inc.
48c2ecf20Sopenharmony_ci * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
58c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef _SDIO_H_
98c2ecf20Sopenharmony_ci#define _SDIO_H_
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_BLOCK_SIZE              256
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define ATH10K_SDIO_MAX_BUFFER_SIZE             4096 /*Unsure of this constant*/
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* Mailbox address in SDIO address space */
168c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_BASE_ADDR               0x1000
178c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_WIDTH                   0x800
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_TOT_WIDTH \
208c2ecf20Sopenharmony_ci	(ATH10K_HIF_MBOX_NUM_MAX * ATH10K_HIF_MBOX_WIDTH)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX0_EXT_BASE_ADDR          0x5000
238c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX0_EXT_WIDTH              (36 * 1024)
248c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0     (56 * 1024)
258c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX1_EXT_WIDTH              (36 * 1024)
268c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE        (2 * 1024)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH \
298c2ecf20Sopenharmony_ci	(ATH10K_SDIO_MAX_BUFFER_SIZE - sizeof(struct ath10k_htc_hdr))
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define ATH10K_HIF_MBOX_NUM_MAX                 4
328c2ecf20Sopenharmony_ci#define ATH10K_SDIO_BUS_REQUEST_MAX_NUM         1024
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ (100 * HZ)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* HTC runs over mailbox 0 */
378c2ecf20Sopenharmony_ci#define ATH10K_HTC_MAILBOX                      0
388c2ecf20Sopenharmony_ci#define ATH10K_HTC_MAILBOX_MASK                 BIT(ATH10K_HTC_MAILBOX)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/* GMBOX addresses */
418c2ecf20Sopenharmony_ci#define ATH10K_HIF_GMBOX_BASE_ADDR              0x7000
428c2ecf20Sopenharmony_ci#define ATH10K_HIF_GMBOX_WIDTH                  0x4000
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* Modified versions of the sdio.h macros.
458c2ecf20Sopenharmony_ci * The macros in sdio.h can't be used easily with the FIELD_{PREP|GET}
468c2ecf20Sopenharmony_ci * macros in bitfield.h, so we define our own macros here.
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci#define ATH10K_SDIO_DRIVE_DTSX_MASK \
498c2ecf20Sopenharmony_ci	(SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define ATH10K_SDIO_DRIVE_DTSX_TYPE_B           0
528c2ecf20Sopenharmony_ci#define ATH10K_SDIO_DRIVE_DTSX_TYPE_A           1
538c2ecf20Sopenharmony_ci#define ATH10K_SDIO_DRIVE_DTSX_TYPE_C           2
548c2ecf20Sopenharmony_ci#define ATH10K_SDIO_DRIVE_DTSX_TYPE_D           3
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* SDIO CCCR register definitions */
578c2ecf20Sopenharmony_ci#define CCCR_SDIO_IRQ_MODE_REG                  0xF0
588c2ecf20Sopenharmony_ci#define CCCR_SDIO_IRQ_MODE_REG_SDIO3            0x16
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR   0xF2
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A      0x02
638c2ecf20Sopenharmony_ci#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C      0x04
648c2ecf20Sopenharmony_ci#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D      0x08
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS       0xF0
678c2ecf20Sopenharmony_ci#define CCCR_SDIO_ASYNC_INT_DELAY_MASK          0xC0
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* mode to enable special 4-bit interrupt assertion without clock */
708c2ecf20Sopenharmony_ci#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ            BIT(0)
718c2ecf20Sopenharmony_ci#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3      BIT(1)
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define ATH10K_SDIO_TARGET_DEBUG_INTR_MASK      0x01
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/* The theoretical maximum number of RX messages that can be fetched
768c2ecf20Sopenharmony_ci * from the mbox interrupt handler in one loop is derived in the following
778c2ecf20Sopenharmony_ci * way:
788c2ecf20Sopenharmony_ci *
798c2ecf20Sopenharmony_ci * Let's assume that each packet in a bundle of the maximum bundle size
808c2ecf20Sopenharmony_ci * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE) has the HTC header bundle count set
818c2ecf20Sopenharmony_ci * to the maximum value (HTC_HOST_MAX_MSG_PER_RX_BUNDLE).
828c2ecf20Sopenharmony_ci *
838c2ecf20Sopenharmony_ci * in this case the driver must allocate
848c2ecf20Sopenharmony_ci * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2) skb's.
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_ci#define ATH10K_SDIO_MAX_RX_MSGS \
878c2ecf20Sopenharmony_ci	(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL   0x00000868u
908c2ecf20Sopenharmony_ci#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
918c2ecf20Sopenharmony_ci#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cienum sdio_mbox_state {
948c2ecf20Sopenharmony_ci	SDIO_MBOX_UNKNOWN_STATE = 0,
958c2ecf20Sopenharmony_ci	SDIO_MBOX_REQUEST_TO_SLEEP_STATE = 1,
968c2ecf20Sopenharmony_ci	SDIO_MBOX_SLEEP_STATE = 2,
978c2ecf20Sopenharmony_ci	SDIO_MBOX_AWAKE_STATE = 3,
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#define ATH10K_CIS_READ_WAIT_4_RTC_CYCLE_IN_US	125
1018c2ecf20Sopenharmony_ci#define ATH10K_CIS_RTC_STATE_ADDR		0x1138
1028c2ecf20Sopenharmony_ci#define ATH10K_CIS_RTC_STATE_ON			0x01
1038c2ecf20Sopenharmony_ci#define ATH10K_CIS_XTAL_SETTLE_DURATION_IN_US	1500
1048c2ecf20Sopenharmony_ci#define ATH10K_CIS_READ_RETRY			10
1058c2ecf20Sopenharmony_ci#define ATH10K_MIN_SLEEP_INACTIVITY_TIME_MS	50
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/* TODO: remove this and use skb->cb instead, much cleaner approach */
1088c2ecf20Sopenharmony_cistruct ath10k_sdio_bus_request {
1098c2ecf20Sopenharmony_ci	struct list_head list;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	/* sdio address */
1128c2ecf20Sopenharmony_ci	u32 address;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	struct sk_buff *skb;
1158c2ecf20Sopenharmony_ci	enum ath10k_htc_ep_id eid;
1168c2ecf20Sopenharmony_ci	int status;
1178c2ecf20Sopenharmony_ci	/* Specifies if the current request is an HTC message.
1188c2ecf20Sopenharmony_ci	 * If not, the eid is not applicable an the TX completion handler
1198c2ecf20Sopenharmony_ci	 * associated with the endpoint will not be invoked.
1208c2ecf20Sopenharmony_ci	 */
1218c2ecf20Sopenharmony_ci	bool htc_msg;
1228c2ecf20Sopenharmony_ci	/* Completion that (if set) will be invoked for non HTC requests
1238c2ecf20Sopenharmony_ci	 * (htc_msg == false) when the request has been processed.
1248c2ecf20Sopenharmony_ci	 */
1258c2ecf20Sopenharmony_ci	struct completion *comp;
1268c2ecf20Sopenharmony_ci};
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistruct ath10k_sdio_rx_data {
1298c2ecf20Sopenharmony_ci	struct sk_buff *skb;
1308c2ecf20Sopenharmony_ci	size_t alloc_len;
1318c2ecf20Sopenharmony_ci	size_t act_len;
1328c2ecf20Sopenharmony_ci	enum ath10k_htc_ep_id eid;
1338c2ecf20Sopenharmony_ci	bool part_of_bundle;
1348c2ecf20Sopenharmony_ci	bool last_in_bundle;
1358c2ecf20Sopenharmony_ci	bool trailer_only;
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct ath10k_sdio_irq_proc_regs {
1398c2ecf20Sopenharmony_ci	u8 host_int_status;
1408c2ecf20Sopenharmony_ci	u8 cpu_int_status;
1418c2ecf20Sopenharmony_ci	u8 error_int_status;
1428c2ecf20Sopenharmony_ci	u8 counter_int_status;
1438c2ecf20Sopenharmony_ci	u8 mbox_frame;
1448c2ecf20Sopenharmony_ci	u8 rx_lookahead_valid;
1458c2ecf20Sopenharmony_ci	u8 host_int_status2;
1468c2ecf20Sopenharmony_ci	u8 gmbox_rx_avail;
1478c2ecf20Sopenharmony_ci	__le32 rx_lookahead[2 * ATH10K_HIF_MBOX_NUM_MAX];
1488c2ecf20Sopenharmony_ci	__le32 int_status_enable;
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistruct ath10k_sdio_irq_enable_regs {
1528c2ecf20Sopenharmony_ci	u8 int_status_en;
1538c2ecf20Sopenharmony_ci	u8 cpu_int_status_en;
1548c2ecf20Sopenharmony_ci	u8 err_int_status_en;
1558c2ecf20Sopenharmony_ci	u8 cntr_int_status_en;
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistruct ath10k_sdio_irq_data {
1598c2ecf20Sopenharmony_ci	/* protects irq_proc_reg and irq_en_reg below.
1608c2ecf20Sopenharmony_ci	 * We use a mutex here and not a spinlock since we will have the
1618c2ecf20Sopenharmony_ci	 * mutex locked while calling the sdio_memcpy_ functions.
1628c2ecf20Sopenharmony_ci	 * These function require non atomic context, and hence, spinlocks
1638c2ecf20Sopenharmony_ci	 * can be held while calling these functions.
1648c2ecf20Sopenharmony_ci	 */
1658c2ecf20Sopenharmony_ci	struct mutex mtx;
1668c2ecf20Sopenharmony_ci	struct ath10k_sdio_irq_proc_regs *irq_proc_reg;
1678c2ecf20Sopenharmony_ci	struct ath10k_sdio_irq_enable_regs *irq_en_reg;
1688c2ecf20Sopenharmony_ci};
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistruct ath10k_mbox_ext_info {
1718c2ecf20Sopenharmony_ci	u32 htc_ext_addr;
1728c2ecf20Sopenharmony_ci	u32 htc_ext_sz;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistruct ath10k_mbox_info {
1768c2ecf20Sopenharmony_ci	u32 htc_addr;
1778c2ecf20Sopenharmony_ci	struct ath10k_mbox_ext_info ext_info[2];
1788c2ecf20Sopenharmony_ci	u32 block_size;
1798c2ecf20Sopenharmony_ci	u32 block_mask;
1808c2ecf20Sopenharmony_ci	u32 gmbox_addr;
1818c2ecf20Sopenharmony_ci	u32 gmbox_sz;
1828c2ecf20Sopenharmony_ci};
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistruct ath10k_sdio {
1858c2ecf20Sopenharmony_ci	struct sdio_func *func;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	struct ath10k_mbox_info mbox_info;
1888c2ecf20Sopenharmony_ci	bool swap_mbox;
1898c2ecf20Sopenharmony_ci	u32 mbox_addr[ATH10K_HTC_EP_COUNT];
1908c2ecf20Sopenharmony_ci	u32 mbox_size[ATH10K_HTC_EP_COUNT];
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* available bus requests */
1938c2ecf20Sopenharmony_ci	struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
1948c2ecf20Sopenharmony_ci	/* free list of bus requests */
1958c2ecf20Sopenharmony_ci	struct list_head bus_req_freeq;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	struct sk_buff_head rx_head;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* protects access to bus_req_freeq */
2008c2ecf20Sopenharmony_ci	spinlock_t lock;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	struct ath10k_sdio_rx_data rx_pkts[ATH10K_SDIO_MAX_RX_MSGS];
2038c2ecf20Sopenharmony_ci	size_t n_rx_pkts;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	struct ath10k *ar;
2068c2ecf20Sopenharmony_ci	struct ath10k_sdio_irq_data irq_data;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* temporary buffer for sdio read.
2098c2ecf20Sopenharmony_ci	 * It is allocated when probe, and used for receive bundled packets,
2108c2ecf20Sopenharmony_ci	 * the read for bundled packets is not parallel, so it does not need
2118c2ecf20Sopenharmony_ci	 * protected.
2128c2ecf20Sopenharmony_ci	 */
2138c2ecf20Sopenharmony_ci	u8 *vsg_buffer;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	/* temporary buffer for BMI requests */
2168c2ecf20Sopenharmony_ci	u8 *bmi_buf;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	bool is_disabled;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	struct workqueue_struct *workqueue;
2218c2ecf20Sopenharmony_ci	struct work_struct wr_async_work;
2228c2ecf20Sopenharmony_ci	struct list_head wr_asyncq;
2238c2ecf20Sopenharmony_ci	/* protects access to wr_asyncq */
2248c2ecf20Sopenharmony_ci	spinlock_t wr_async_lock;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	struct work_struct async_work_rx;
2278c2ecf20Sopenharmony_ci	struct timer_list sleep_timer;
2288c2ecf20Sopenharmony_ci	enum sdio_mbox_state mbox_state;
2298c2ecf20Sopenharmony_ci};
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	return (struct ath10k_sdio *)ar->drv_priv;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci#endif
237