]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
brcm80211: fmac: remove width parameter from brcmf_sdioh_request_buffer
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
CommitLineData
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/* ****************** SDIO CARD Interface Functions **************************/
17
18#include <linux/types.h>
19#include <linux/netdevice.h>
ee40fa06 20#include <linux/export.h>
5b435de0
AS
21#include <linux/pci.h>
22#include <linux/pci_ids.h>
23#include <linux/sched.h>
24#include <linux/completion.h>
25#include <linux/mmc/sdio.h>
26#include <linux/mmc/sdio_func.h>
27#include <linux/mmc/card.h>
28
29#include <defs.h>
30#include <brcm_hw_ids.h>
31#include <brcmu_utils.h>
32#include <brcmu_wifi.h>
33#include <soc.h>
34#include "dhd.h"
35#include "dhd_bus.h"
36#include "dhd_dbg.h"
37#include "sdio_host.h"
38
39#define SDIOH_API_ACCESS_RETRY_LIMIT 2
40
41static void brcmf_sdioh_irqhandler(struct sdio_func *func)
42{
43 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
44
45 brcmf_dbg(TRACE, "***IRQHandler\n");
46
47 sdio_release_host(func);
48
49 brcmf_sdbrcm_isr(sdiodev->bus);
50
51 sdio_claim_host(func);
52}
53
54int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
55{
56 brcmf_dbg(TRACE, "Entering\n");
57
58 sdio_claim_host(sdiodev->func[1]);
59 sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
60 sdio_release_host(sdiodev->func[1]);
61
62 return 0;
63}
64
65int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
66{
67 brcmf_dbg(TRACE, "Entering\n");
68
69 sdio_claim_host(sdiodev->func[1]);
70 sdio_release_irq(sdiodev->func[1]);
71 sdio_release_host(sdiodev->func[1]);
72
73 return 0;
74}
75
76u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
77 int *err)
78{
79 int status;
80 s32 retry = 0;
81 u8 data = 0;
82
83 do {
84 if (retry) /* wait for 1 ms till bus get settled down */
85 udelay(1000);
86 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
87 addr, (u8 *) &data);
88 } while (status != 0
89 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
90 if (err)
91 *err = status;
92
93 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
94 fnc_num, addr, data);
95
96 return data;
97}
98
99void
100brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
101 u8 data, int *err)
102{
103 int status;
104 s32 retry = 0;
105
106 do {
107 if (retry) /* wait for 1 ms till bus get settled down */
108 udelay(1000);
109 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
110 addr, (u8 *) &data);
111 } while (status != 0
112 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
113 if (err)
114 *err = status;
115
116 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
117 fnc_num, addr, data);
118}
119
120int
121brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
122{
123 int err = 0;
124 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
125 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
126 if (!err)
127 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
128 SBSDIO_FUNC1_SBADDRMID,
129 (address >> 16) & SBSDIO_SBADDRMID_MASK,
130 &err);
131 if (!err)
132 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
133 SBSDIO_FUNC1_SBADDRHIGH,
134 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
135 &err);
136
137 return err;
138}
139
140u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
141{
142 int status;
143 u32 word = 0;
144 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
145
146 brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
147
148 if (bar0 != sdiodev->sbwad) {
149 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
150 return 0xFFFFFFFF;
151
152 sdiodev->sbwad = bar0;
153 }
154
155 addr &= SBSDIO_SB_OFT_ADDR_MASK;
156 if (size == 4)
157 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
158
159 status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
160 addr, &word, size);
161
162 sdiodev->regfail = (status != 0);
163
164 brcmf_dbg(INFO, "u32data = 0x%x\n", word);
165
166 /* if ok, return appropriately masked word */
167 if (status == 0) {
168 switch (size) {
169 case sizeof(u8):
170 return word & 0xff;
171 case sizeof(u16):
172 return word & 0xffff;
173 case sizeof(u32):
174 return word;
175 default:
176 sdiodev->regfail = true;
177
178 }
179 }
180
181 /* otherwise, bad sdio access or invalid size */
182 brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
183 return 0xFFFFFFFF;
184}
185
186u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
187 u32 data)
188{
189 int status;
190 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
191 int err = 0;
192
193 brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
194 addr, size * 8, data);
195
196 if (bar0 != sdiodev->sbwad) {
197 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
198 if (err)
199 return err;
200
201 sdiodev->sbwad = bar0;
202 }
203
204 addr &= SBSDIO_SB_OFT_ADDR_MASK;
205 if (size == 4)
206 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
207 status =
208 brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
209 addr, &data, size);
210 sdiodev->regfail = (status != 0);
211
212 if (status == 0)
213 return 0;
214
215 brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
216 data, addr, size);
217 return 0xFFFFFFFF;
218}
219
220bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
221{
222 return sdiodev->regfail;
223}
224
5adfeb63
AS
225static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
226 uint flags, uint width, u32 *addr)
5b435de0 227{
5adfeb63 228 uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
5b435de0
AS
229 int err = 0;
230
5b435de0
AS
231 /* Async not implemented yet */
232 if (flags & SDIO_REQ_ASYNC)
233 return -ENOTSUPP;
234
235 if (bar0 != sdiodev->sbwad) {
236 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
237 if (err)
238 return err;
239
240 sdiodev->sbwad = bar0;
241 }
242
5adfeb63
AS
243 *addr &= SBSDIO_SB_OFT_ADDR_MASK;
244
245 if (width == 4)
246 *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
247
248 return 0;
249}
250
251int
252brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
253 uint flags, u8 *buf, uint nbytes)
254{
255 struct sk_buff *mypkt;
256 int err;
257
258 mypkt = brcmu_pkt_buf_get_skb(nbytes);
259 if (!mypkt) {
260 brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
261 nbytes);
262 return -EIO;
263 }
264
265 err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
266 if (!err)
267 memcpy(buf, mypkt->data, nbytes);
268
269 brcmu_pkt_buf_free_skb(mypkt);
270 return err;
271}
272
273int
274brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
275 uint flags, struct sk_buff *pkt)
276{
277 uint incr_fix;
278 uint width;
279 int err = 0;
280
281 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
282 fn, addr, pkt->len);
283
284 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
285 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
286 if (err)
287 return err;
5b435de0
AS
288
289 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
5adfeb63 290 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
5e8e13b9 291 fn, addr, 0, NULL, pkt);
5adfeb63
AS
292
293 return err;
294}
295
296int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
297 uint flags, struct sk_buff_head *pktq)
298{
299 uint incr_fix;
300 uint width;
301 int err = 0;
302
303 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
304 fn, addr, pktq->qlen);
305
5b435de0 306 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
5adfeb63
AS
307 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
308 if (err)
309 return err;
5b435de0 310
5adfeb63
AS
311 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
312 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
313 pktq);
5b435de0 314
5adfeb63 315 return err;
5b435de0
AS
316}
317
318int
319brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
5adfeb63
AS
320 uint flags, u8 *buf, uint nbytes)
321{
322 struct sk_buff *mypkt;
323 int err;
324
325 mypkt = brcmu_pkt_buf_get_skb(nbytes);
326 if (!mypkt) {
327 brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
328 nbytes);
329 return -EIO;
330 }
331
332 memcpy(mypkt->data, buf, nbytes);
333 err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt);
334
335 brcmu_pkt_buf_free_skb(mypkt);
336 return err;
337
338}
339
340int
341brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
342 uint flags, struct sk_buff *pkt)
5b435de0
AS
343{
344 uint incr_fix;
345 uint width;
346 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
347 int err = 0;
348
5adfeb63
AS
349 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
350 fn, addr, pkt->len);
5b435de0
AS
351
352 /* Async not implemented yet */
353 if (flags & SDIO_REQ_ASYNC)
354 return -ENOTSUPP;
355
356 if (bar0 != sdiodev->sbwad) {
357 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
358 if (err)
359 return err;
360
361 sdiodev->sbwad = bar0;
362 }
363
364 addr &= SBSDIO_SB_OFT_ADDR_MASK;
365
366 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
367 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
368 if (width == 4)
369 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
370
371 return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
5e8e13b9 372 addr, 0, NULL, pkt);
5b435de0
AS
373}
374
375int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
376 u8 *buf, uint nbytes)
377{
378 addr &= SBSDIO_SB_OFT_ADDR_MASK;
379 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
380
381 return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
382 (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
5e8e13b9 383 addr, nbytes, buf, NULL);
5b435de0
AS
384}
385
386int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
387{
388 char t_func = (char)fn;
389 brcmf_dbg(TRACE, "Enter\n");
390
391 /* issue abort cmd52 command through F0 */
392 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
393 SDIO_CCCR_ABORT, &t_func);
394
395 brcmf_dbg(TRACE, "Exit\n");
396 return 0;
397}
398
399int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
400{
401 u32 regs = 0;
402 int ret = 0;
403
404 ret = brcmf_sdioh_attach(sdiodev);
405 if (ret)
406 goto out;
407
408 regs = SI_ENUM_BASE;
409
410 /* Report the BAR, to fix if needed */
411 sdiodev->sbwad = SI_ENUM_BASE;
412
413 /* try to attach to the target device */
414 sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
415 if (!sdiodev->bus) {
416 brcmf_dbg(ERROR, "device attach failed\n");
417 ret = -ENODEV;
418 goto out;
419 }
420
421out:
422 if (ret)
423 brcmf_sdio_remove(sdiodev);
424
425 return ret;
426}
427EXPORT_SYMBOL(brcmf_sdio_probe);
428
429int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
430{
431 if (sdiodev->bus) {
432 brcmf_sdbrcm_disconnect(sdiodev->bus);
433 sdiodev->bus = NULL;
434 }
435
436 brcmf_sdioh_detach(sdiodev);
437
438 sdiodev->sbwad = 0;
439
440 return 0;
441}
442EXPORT_SYMBOL(brcmf_sdio_remove);
443
444void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
445{
446 if (enable)
447 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
448 else
449 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
450}