summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath10k/sdio.h
blob: b6ac927628b199e0d9dce0deaed3ef0df40e762a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/* SPDX-License-Identifier: ISC */
/*
 * Copyright (c) 2004-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
 * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
 */

#ifndef _SDIO_H_
#define _SDIO_H_

#define ATH10K_HIF_MBOX_BLOCK_SIZE              256

#define ATH10K_SDIO_MAX_BUFFER_SIZE             4096 /*Unsure of this constant*/

/* Mailbox address in SDIO address space */
#define ATH10K_HIF_MBOX_BASE_ADDR               0x1000
#define ATH10K_HIF_MBOX_WIDTH                   0x800

#define ATH10K_HIF_MBOX_TOT_WIDTH \
	(ATH10K_HIF_MBOX_NUM_MAX * ATH10K_HIF_MBOX_WIDTH)

#define ATH10K_HIF_MBOX0_EXT_BASE_ADDR          0x5000
#define ATH10K_HIF_MBOX0_EXT_WIDTH              (36 * 1024)
#define ATH10K_HIF_MBOX0_EXT_WIDTH_ROME_2_0     (56 * 1024)
#define ATH10K_HIF_MBOX1_EXT_WIDTH              (36 * 1024)
#define ATH10K_HIF_MBOX_DUMMY_SPACE_SIZE        (2 * 1024)

#define ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH \
	(ATH10K_SDIO_MAX_BUFFER_SIZE - sizeof(struct ath10k_htc_hdr))

#define ATH10K_HIF_MBOX_NUM_MAX                 4
#define ATH10K_SDIO_BUS_REQUEST_MAX_NUM         1024

#define ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ (100 * HZ)

/* HTC runs over mailbox 0 */
#define ATH10K_HTC_MAILBOX                      0
#define ATH10K_HTC_MAILBOX_MASK                 BIT(ATH10K_HTC_MAILBOX)

/* GMBOX addresses */
#define ATH10K_HIF_GMBOX_BASE_ADDR              0x7000
#define ATH10K_HIF_GMBOX_WIDTH                  0x4000

/* Modified versions of the sdio.h macros.
 * The macros in sdio.h can't be used easily with the FIELD_{PREP|GET}
 * macros in bitfield.h, so we define our own macros here.
 */
#define ATH10K_SDIO_DRIVE_DTSX_MASK \
	(SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT)

#define ATH10K_SDIO_DRIVE_DTSX_TYPE_B           0
#define ATH10K_SDIO_DRIVE_DTSX_TYPE_A           1
#define ATH10K_SDIO_DRIVE_DTSX_TYPE_C           2
#define ATH10K_SDIO_DRIVE_DTSX_TYPE_D           3

/* SDIO CCCR register definitions */
#define CCCR_SDIO_IRQ_MODE_REG                  0xF0
#define CCCR_SDIO_IRQ_MODE_REG_SDIO3            0x16

#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR   0xF2

#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A      0x02
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C      0x04
#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D      0x08

#define CCCR_SDIO_ASYNC_INT_DELAY_ADDRESS       0xF0
#define CCCR_SDIO_ASYNC_INT_DELAY_MASK          0xC0

/* mode to enable special 4-bit interrupt assertion without clock */
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ            BIT(0)
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ_SDIO3      BIT(1)

#define ATH10K_SDIO_TARGET_DEBUG_INTR_MASK      0x01

/* The theoretical maximum number of RX messages that can be fetched
 * from the mbox interrupt handler in one loop is derived in the following
 * way:
 *
 * Let's assume that each packet in a bundle of the maximum bundle size
 * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE) has the HTC header bundle count set
 * to the maximum value (HTC_HOST_MAX_MSG_PER_RX_BUNDLE).
 *
 * in this case the driver must allocate
 * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2) skb's.
 */
#define ATH10K_SDIO_MAX_RX_MSGS \
	(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2)

#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL   0x00000868u
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000

enum sdio_mbox_state {
	SDIO_MBOX_UNKNOWN_STATE = 0,
	SDIO_MBOX_REQUEST_TO_SLEEP_STATE = 1,
	SDIO_MBOX_SLEEP_STATE = 2,
	SDIO_MBOX_AWAKE_STATE = 3,
};

#define ATH10K_CIS_READ_WAIT_4_RTC_CYCLE_IN_US	125
#define ATH10K_CIS_RTC_STATE_ADDR		0x1138
#define ATH10K_CIS_RTC_STATE_ON			0x01
#define ATH10K_CIS_XTAL_SETTLE_DURATION_IN_US	1500
#define ATH10K_CIS_READ_RETRY			10
#define ATH10K_MIN_SLEEP_INACTIVITY_TIME_MS	50

/* TODO: remove this and use skb->cb instead, much cleaner approach */
struct ath10k_sdio_bus_request {
	struct list_head list;

	/* sdio address */
	u32 address;

	struct sk_buff *skb;
	enum ath10k_htc_ep_id eid;
	int status;
	/* Specifies if the current request is an HTC message.
	 * If not, the eid is not applicable an the TX completion handler
	 * associated with the endpoint will not be invoked.
	 */
	bool htc_msg;
	/* Completion that (if set) will be invoked for non HTC requests
	 * (htc_msg == false) when the request has been processed.
	 */
	struct completion *comp;
};

struct ath10k_sdio_rx_data {
	struct sk_buff *skb;
	size_t alloc_len;
	size_t act_len;
	enum ath10k_htc_ep_id eid;
	bool part_of_bundle;
	bool last_in_bundle;
	bool trailer_only;
};

struct ath10k_sdio_irq_proc_regs {
	u8 host_int_status;
	u8 cpu_int_status;
	u8 error_int_status;
	u8 counter_int_status;
	u8 mbox_frame;
	u8 rx_lookahead_valid;
	u8 host_int_status2;
	u8 gmbox_rx_avail;
	__le32 rx_lookahead[2 * ATH10K_HIF_MBOX_NUM_MAX];
	__le32 int_status_enable;
};

struct ath10k_sdio_irq_enable_regs {
	u8 int_status_en;
	u8 cpu_int_status_en;
	u8 err_int_status_en;
	u8 cntr_int_status_en;
};

struct ath10k_sdio_irq_data {
	/* protects irq_proc_reg and irq_en_reg below.
	 * We use a mutex here and not a spinlock since we will have the
	 * mutex locked while calling the sdio_memcpy_ functions.
	 * These function require non atomic context, and hence, spinlocks
	 * can be held while calling these functions.
	 */
	struct mutex mtx;
	struct ath10k_sdio_irq_proc_regs *irq_proc_reg;
	struct ath10k_sdio_irq_enable_regs *irq_en_reg;
};

struct ath10k_mbox_ext_info {
	u32 htc_ext_addr;
	u32 htc_ext_sz;
};

struct ath10k_mbox_info {
	u32 htc_addr;
	struct ath10k_mbox_ext_info ext_info[2];
	u32 block_size;
	u32 block_mask;
	u32 gmbox_addr;
	u32 gmbox_sz;
};

struct ath10k_sdio {
	struct sdio_func *func;

	struct ath10k_mbox_info mbox_info;
	bool swap_mbox;
	u32 mbox_addr[ATH10K_HTC_EP_COUNT];
	u32 mbox_size[ATH10K_HTC_EP_COUNT];

	/* available bus requests */
	struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
	/* free list of bus requests */
	struct list_head bus_req_freeq;

	struct sk_buff_head rx_head;

	/* protects access to bus_req_freeq */
	spinlock_t lock;

	struct ath10k_sdio_rx_data rx_pkts[ATH10K_SDIO_MAX_RX_MSGS];
	size_t n_rx_pkts;

	struct ath10k *ar;
	struct ath10k_sdio_irq_data irq_data;

	/* temporary buffer for sdio read.
	 * It is allocated when probe, and used for receive bundled packets,
	 * the read for bundled packets is not parallel, so it does not need
	 * protected.
	 */
	u8 *vsg_buffer;

	/* temporary buffer for BMI requests */
	u8 *bmi_buf;

	bool is_disabled;

	struct workqueue_struct *workqueue;
	struct work_struct wr_async_work;
	struct list_head wr_asyncq;
	/* protects access to wr_asyncq */
	spinlock_t wr_async_lock;

	struct work_struct async_work_rx;
	struct timer_list sleep_timer;
	enum sdio_mbox_state mbox_state;
};

static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
{
	return (struct ath10k_sdio *)ar->drv_priv;
}

#endif