Commit | Line | Data |
---|---|---|
5b435de0 AS |
1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
888bf76e HM |
17 | #ifndef BRCMFMAC_SDIO_H |
18 | #define BRCMFMAC_SDIO_H | |
5b435de0 AS |
19 | |
20 | #include <linux/skbuff.h> | |
c1b20532 DK |
21 | #include <linux/firmware.h> |
22 | #include "firmware.h" | |
5b435de0 AS |
23 | |
24 | #define SDIO_FUNC_0 0 | |
25 | #define SDIO_FUNC_1 1 | |
26 | #define SDIO_FUNC_2 2 | |
27 | ||
28 | #define SDIOD_FBR_SIZE 0x100 | |
29 | ||
30 | /* io_en */ | |
31 | #define SDIO_FUNC_ENABLE_1 0x02 | |
32 | #define SDIO_FUNC_ENABLE_2 0x04 | |
33 | ||
34 | /* io_rdys */ | |
35 | #define SDIO_FUNC_READY_1 0x02 | |
36 | #define SDIO_FUNC_READY_2 0x04 | |
37 | ||
38 | /* intr_status */ | |
39 | #define INTR_STATUS_FUNC1 0x2 | |
40 | #define INTR_STATUS_FUNC2 0x4 | |
41 | ||
42 | /* Maximum number of I/O funcs */ | |
43 | #define SDIOD_MAX_IOFUNCS 7 | |
44 | ||
e9b8d91d | 45 | /* mask of register map */ |
d8b3fc59 | 46 | #define REG_F0_REG_MASK 0x7FF |
e9b8d91d FL |
47 | #define REG_F1_MISC_MASK 0x1FFFF |
48 | ||
5b435de0 AS |
49 | /* as of sdiod rev 0, supports 3 functions */ |
50 | #define SBSDIO_NUM_FUNCTION 3 | |
51 | ||
ba89bf19 | 52 | /* function 0 vendor specific CCCR registers */ |
4a3da990 PH |
53 | #define SDIO_CCCR_BRCM_CARDCAP 0xf0 |
54 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 | |
55 | #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 | |
56 | #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 | |
1e9ab4dd PH |
57 | #define SDIO_CCCR_BRCM_CARDCTRL 0xf1 |
58 | #define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02 | |
4a3da990 | 59 | #define SDIO_CCCR_BRCM_SEPINT 0xf2 |
ba89bf19 FL |
60 | |
61 | #define SDIO_SEPINT_MASK 0x01 | |
62 | #define SDIO_SEPINT_OE 0x02 | |
63 | #define SDIO_SEPINT_ACT_HI 0x04 | |
64 | ||
5b435de0 AS |
65 | /* function 1 miscellaneous registers */ |
66 | ||
67 | /* sprom command and status */ | |
68 | #define SBSDIO_SPROM_CS 0x10000 | |
69 | /* sprom info register */ | |
70 | #define SBSDIO_SPROM_INFO 0x10001 | |
71 | /* sprom indirect access data byte 0 */ | |
72 | #define SBSDIO_SPROM_DATA_LOW 0x10002 | |
73 | /* sprom indirect access data byte 1 */ | |
74 | #define SBSDIO_SPROM_DATA_HIGH 0x10003 | |
75 | /* sprom indirect access addr byte 0 */ | |
76 | #define SBSDIO_SPROM_ADDR_LOW 0x10004 | |
3cdf0a81 HG |
77 | /* gpio select */ |
78 | #define SBSDIO_GPIO_SELECT 0x10005 | |
79 | /* gpio output */ | |
80 | #define SBSDIO_GPIO_OUT 0x10006 | |
81 | /* gpio enable */ | |
82 | #define SBSDIO_GPIO_EN 0x10007 | |
5b435de0 AS |
83 | /* rev < 7, watermark for sdio device */ |
84 | #define SBSDIO_WATERMARK 0x10008 | |
85 | /* control busy signal generation */ | |
86 | #define SBSDIO_DEVICE_CTL 0x10009 | |
87 | ||
88 | /* SB Address Window Low (b15) */ | |
89 | #define SBSDIO_FUNC1_SBADDRLOW 0x1000A | |
90 | /* SB Address Window Mid (b23:b16) */ | |
91 | #define SBSDIO_FUNC1_SBADDRMID 0x1000B | |
92 | /* SB Address Window High (b31:b24) */ | |
93 | #define SBSDIO_FUNC1_SBADDRHIGH 0x1000C | |
94 | /* Frame Control (frame term/abort) */ | |
95 | #define SBSDIO_FUNC1_FRAMECTRL 0x1000D | |
96 | /* ChipClockCSR (ALP/HT ctl/status) */ | |
97 | #define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E | |
98 | /* SdioPullUp (on cmd, d0-d2) */ | |
99 | #define SBSDIO_FUNC1_SDIOPULLUP 0x1000F | |
100 | /* Write Frame Byte Count Low */ | |
101 | #define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 | |
102 | /* Write Frame Byte Count High */ | |
103 | #define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A | |
104 | /* Read Frame Byte Count Low */ | |
105 | #define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B | |
106 | /* Read Frame Byte Count High */ | |
107 | #define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C | |
4a3da990 PH |
108 | /* MesBusyCtl (rev 11) */ |
109 | #define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D | |
110 | /* Sdio Core Rev 12 */ | |
111 | #define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E | |
112 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1 | |
113 | #define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0 | |
114 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2 | |
115 | #define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1 | |
116 | #define SBSDIO_FUNC1_SLEEPCSR 0x1001F | |
117 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1 | |
118 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0 | |
119 | #define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1 | |
120 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2 | |
121 | #define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1 | |
5b435de0 AS |
122 | |
123 | #define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ | |
4a3da990 | 124 | #define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */ |
5b435de0 AS |
125 | |
126 | /* function 1 OCP space */ | |
127 | ||
128 | /* sb offset addr is <= 15 bits, 32k */ | |
129 | #define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF | |
130 | #define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 | |
131 | /* with b15, maps to 32-bit SB access */ | |
132 | #define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 | |
133 | ||
134 | /* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ | |
135 | ||
136 | #define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ | |
137 | #define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ | |
138 | #define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ | |
139 | /* Address bits from SBADDR regs */ | |
140 | #define SBSDIO_SBWINDOW_MASK 0xffff8000 | |
141 | ||
142 | #define SDIOH_READ 0 /* Read request */ | |
143 | #define SDIOH_WRITE 1 /* Write request */ | |
144 | ||
145 | #define SDIOH_DATA_FIX 0 /* Fixed addressing */ | |
146 | #define SDIOH_DATA_INC 1 /* Incremental addressing */ | |
147 | ||
148 | /* internal return code */ | |
149 | #define SUCCESS 0 | |
150 | #define ERROR 1 | |
151 | ||
6e3c7128 FL |
152 | /* Packet alignment for most efficient SDIO (can change based on platform) */ |
153 | #define BRCMF_SDALIGN (1 << 6) | |
154 | ||
63ce3d5d AS |
155 | /* watchdog polling interval */ |
156 | #define BRCMF_WD_POLL msecs_to_jiffies(10) | |
6e3c7128 | 157 | |
a1ce7a0d AS |
158 | /** |
159 | * enum brcmf_sdiod_state - the state of the bus. | |
160 | * | |
161 | * @BRCMF_SDIOD_DOWN: Device can be accessed, no DPC. | |
162 | * @BRCMF_SDIOD_DATA: Ready for data transfers, DPC enabled. | |
163 | * @BRCMF_SDIOD_NOMEDIUM: No medium access to dongle possible. | |
164 | */ | |
165 | enum brcmf_sdiod_state { | |
166 | BRCMF_SDIOD_DOWN, | |
167 | BRCMF_SDIOD_DATA, | |
168 | BRCMF_SDIOD_NOMEDIUM | |
a1cee865 HM |
169 | }; |
170 | ||
5b435de0 AS |
171 | struct brcmf_sdreg { |
172 | int func; | |
173 | int offset; | |
174 | int value; | |
175 | }; | |
176 | ||
2447ffb0 | 177 | struct brcmf_sdio; |
99824643 | 178 | struct brcmf_sdiod_freezer; |
2447ffb0 | 179 | |
5b435de0 AS |
180 | struct brcmf_sdio_dev { |
181 | struct sdio_func *func[SDIO_MAX_FUNCS]; | |
182 | u8 num_funcs; /* Supported funcs on client */ | |
5b435de0 | 183 | u32 sbwad; /* Save backplane window address */ |
964ec1cf | 184 | struct brcmf_sdio *bus; |
655713be | 185 | struct device *dev; |
d76d1c8c | 186 | struct brcmf_bus *bus_if; |
af5b5e62 | 187 | struct brcmf_mp_device *settings; |
668761ac | 188 | bool oob_irq_requested; |
b88a2e80 | 189 | bool sd_irq_requested; |
ba89bf19 FL |
190 | bool irq_en; /* irq enable flags */ |
191 | spinlock_t irq_en_lock; | |
192 | bool irq_wake; /* irq wake enable flags */ | |
71201496 AS |
193 | bool sg_support; |
194 | uint max_request_size; | |
195 | ushort max_segment_count; | |
196 | uint max_segment_size; | |
af1fa210 AS |
197 | uint txglomsz; |
198 | struct sg_table sgtable; | |
46d703a7 HM |
199 | char fw_name[BRCMF_FW_NAME_LEN]; |
200 | char nvram_name[BRCMF_FW_NAME_LEN]; | |
330b4e4b | 201 | bool wowl_enabled; |
a1ce7a0d | 202 | enum brcmf_sdiod_state state; |
99824643 | 203 | struct brcmf_sdiod_freezer *freezer; |
5b435de0 AS |
204 | }; |
205 | ||
cb7cf7be AS |
206 | /* sdio core registers */ |
207 | struct sdpcmd_regs { | |
208 | u32 corecontrol; /* 0x00, rev8 */ | |
209 | u32 corestatus; /* rev8 */ | |
210 | u32 PAD[1]; | |
211 | u32 biststatus; /* rev8 */ | |
212 | ||
213 | /* PCMCIA access */ | |
214 | u16 pcmciamesportaladdr; /* 0x010, rev8 */ | |
215 | u16 PAD[1]; | |
216 | u16 pcmciamesportalmask; /* rev8 */ | |
217 | u16 PAD[1]; | |
218 | u16 pcmciawrframebc; /* rev8 */ | |
219 | u16 PAD[1]; | |
220 | u16 pcmciaunderflowtimer; /* rev8 */ | |
221 | u16 PAD[1]; | |
222 | ||
223 | /* interrupt */ | |
224 | u32 intstatus; /* 0x020, rev8 */ | |
225 | u32 hostintmask; /* rev8 */ | |
226 | u32 intmask; /* rev8 */ | |
227 | u32 sbintstatus; /* rev8 */ | |
228 | u32 sbintmask; /* rev8 */ | |
229 | u32 funcintmask; /* rev4 */ | |
230 | u32 PAD[2]; | |
231 | u32 tosbmailbox; /* 0x040, rev8 */ | |
232 | u32 tohostmailbox; /* rev8 */ | |
233 | u32 tosbmailboxdata; /* rev8 */ | |
234 | u32 tohostmailboxdata; /* rev8 */ | |
235 | ||
236 | /* synchronized access to registers in SDIO clock domain */ | |
237 | u32 sdioaccess; /* 0x050, rev8 */ | |
238 | u32 PAD[3]; | |
239 | ||
240 | /* PCMCIA frame control */ | |
241 | u8 pcmciaframectrl; /* 0x060, rev8 */ | |
242 | u8 PAD[3]; | |
243 | u8 pcmciawatermark; /* rev8 */ | |
244 | u8 PAD[155]; | |
245 | ||
246 | /* interrupt batching control */ | |
247 | u32 intrcvlazy; /* 0x100, rev8 */ | |
248 | u32 PAD[3]; | |
249 | ||
250 | /* counters */ | |
251 | u32 cmd52rd; /* 0x110, rev8 */ | |
252 | u32 cmd52wr; /* rev8 */ | |
253 | u32 cmd53rd; /* rev8 */ | |
254 | u32 cmd53wr; /* rev8 */ | |
255 | u32 abort; /* rev8 */ | |
256 | u32 datacrcerror; /* rev8 */ | |
257 | u32 rdoutofsync; /* rev8 */ | |
258 | u32 wroutofsync; /* rev8 */ | |
259 | u32 writebusy; /* rev8 */ | |
260 | u32 readwait; /* rev8 */ | |
261 | u32 readterm; /* rev8 */ | |
262 | u32 writeterm; /* rev8 */ | |
263 | u32 PAD[40]; | |
264 | u32 clockctlstatus; /* rev8 */ | |
265 | u32 PAD[7]; | |
266 | ||
267 | u32 PAD[128]; /* DMA engines */ | |
268 | ||
269 | /* SDIO/PCMCIA CIS region */ | |
270 | char cis[512]; /* 0x400-0x5ff, rev6 */ | |
271 | ||
272 | /* PCMCIA function control registers */ | |
273 | char pcmciafcr[256]; /* 0x600-6ff, rev6 */ | |
274 | u16 PAD[55]; | |
275 | ||
276 | /* PCMCIA backplane access */ | |
277 | u16 backplanecsr; /* 0x76E, rev6 */ | |
278 | u16 backplaneaddr0; /* rev6 */ | |
279 | u16 backplaneaddr1; /* rev6 */ | |
280 | u16 backplaneaddr2; /* rev6 */ | |
281 | u16 backplaneaddr3; /* rev6 */ | |
282 | u16 backplanedata0; /* rev6 */ | |
283 | u16 backplanedata1; /* rev6 */ | |
284 | u16 backplanedata2; /* rev6 */ | |
285 | u16 backplanedata3; /* rev6 */ | |
286 | u16 PAD[31]; | |
287 | ||
288 | /* sprom "size" & "blank" info */ | |
289 | u16 spromstatus; /* 0x7BE, rev2 */ | |
290 | u32 PAD[464]; | |
291 | ||
292 | u16 PAD[0x80]; | |
293 | }; | |
294 | ||
ba89bf19 | 295 | /* Register/deregister interrupt handler. */ |
a39be27b AS |
296 | int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev); |
297 | int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev); | |
5b435de0 | 298 | |
e9b8d91d | 299 | /* sdio device register access interface */ |
a39be27b AS |
300 | u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
301 | u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); | |
302 | void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, | |
303 | int *ret); | |
304 | void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, | |
305 | int *ret); | |
e9b8d91d | 306 | |
5b435de0 AS |
307 | /* Buffer transfer to/from device (client) core via cmd53. |
308 | * fn: function number | |
5b435de0 AS |
309 | * flags: backplane width, address increment, sync/async |
310 | * buf: pointer to memory data buffer | |
311 | * nbytes: number of bytes to transfer to/from buf | |
312 | * pkt: pointer to packet associated with buf (if any) | |
313 | * complete: callback function for command completion (async only) | |
314 | * handle: handle for completion callback (first arg in callback) | |
315 | * Returns 0 or error code. | |
316 | * NOTE: Async operation is not currently supported. | |
317 | */ | |
a7cdd821 AS |
318 | int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev, |
319 | struct sk_buff_head *pktq); | |
320 | int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes); | |
321 | ||
322 | int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt); | |
323 | int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes); | |
324 | int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev, | |
325 | struct sk_buff_head *pktq, uint totlen); | |
5b435de0 AS |
326 | |
327 | /* Flags bits */ | |
328 | ||
329 | /* Four-byte target (backplane) width (vs. two-byte) */ | |
330 | #define SDIO_REQ_4BYTE 0x1 | |
331 | /* Fixed address (FIFO) (vs. incrementing address) */ | |
332 | #define SDIO_REQ_FIXED 0x2 | |
5b435de0 AS |
333 | |
334 | /* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). | |
335 | * rw: read or write (0/1) | |
336 | * addr: direct SDIO address | |
337 | * buf: pointer to memory data buffer | |
338 | * nbytes: number of bytes to transfer to/from buf | |
339 | * Returns 0 or error code. | |
340 | */ | |
a39be27b AS |
341 | int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, |
342 | u8 *data, uint size); | |
5b435de0 AS |
343 | |
344 | /* Issue an abort to the specified function */ | |
a39be27b | 345 | int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
e0045bf8 | 346 | void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev); |
99824643 AS |
347 | void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, |
348 | enum brcmf_sdiod_state state); | |
349 | #ifdef CONFIG_PM_SLEEP | |
350 | bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev); | |
351 | void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev); | |
352 | void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev); | |
353 | void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev); | |
354 | #else | |
355 | static inline bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev) | |
356 | { | |
357 | return false; | |
358 | } | |
359 | static inline void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev) | |
360 | { | |
361 | } | |
362 | static inline void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev) | |
363 | { | |
364 | } | |
365 | static inline void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev) | |
366 | { | |
367 | } | |
368 | #endif /* CONFIG_PM_SLEEP */ | |
5b435de0 | 369 | |
82d7f3c1 | 370 | struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); |
9fbe2a6d | 371 | void brcmf_sdio_remove(struct brcmf_sdio *bus); |
82d7f3c1 AS |
372 | void brcmf_sdio_isr(struct brcmf_sdio *bus); |
373 | ||
4011fc49 | 374 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active); |
330b4e4b | 375 | void brcmf_sdio_wowl_config(struct device *dev, bool enabled); |
99824643 AS |
376 | int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep); |
377 | void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus); | |
a1ce7a0d | 378 | |
888bf76e | 379 | #endif /* BRCMFMAC_SDIO_H */ |