staging: brcm80211: remove function pointer of interrupt isr in brcmfmac
[pohmelfs.git] / drivers / staging / brcm80211 / brcmfmac / bcmsdh.c
blobc9893e9287b85e3790924eab7cca4f4bef441859
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
16 /* ****************** SDIO CARD Interface Functions **************************/
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <linux/pci.h>
21 #include <linux/pci_ids.h>
22 #include <linux/sched.h>
23 #include <linux/completion.h>
25 #include <defs.h>
26 #include <brcm_hw_ids.h>
27 #include <brcmu_utils.h>
28 #include <brcmu_wifi.h>
29 #include <soc.h>
30 #include "dhd.h"
31 #include "dhd_bus.h"
32 #include "dhd_dbg.h"
33 #include "sdio_host.h"
35 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
37 #define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
38 #define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
39 #define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
41 #define SDIOH_DATA_PIO 0 /* PIO mode */
42 #define SDIOH_DATA_DMA 1 /* DMA mode */
44 /* Module parameters specific to each host-controller driver */
46 module_param(sd_f2_blocksize, int, 0);
48 int
49 brcmf_sdcard_iovar_op(struct brcmf_sdio_dev *sdiodev, const char *name,
50 void *params, int plen, void *arg, int len, bool set)
52 return brcmf_sdioh_iovar_op(sdiodev->sdioh, name, params, plen, arg,
53 len, set);
56 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
58 return brcmf_sdioh_interrupt_register(sdiodev->sdioh);
61 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
63 return brcmf_sdioh_interrupt_deregister(sdiodev->sdioh);
66 u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
67 int *err)
69 int status;
70 s32 retry = 0;
71 u8 data = 0;
73 do {
74 if (retry) /* wait for 1 ms till bus get settled down */
75 udelay(1000);
76 status =
77 brcmf_sdioh_cfg_read(sdiodev->sdioh, fnc_num, addr,
78 (u8 *) &data);
79 } while (status != 0
80 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
81 if (err)
82 *err = status;
84 BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
85 __func__, fnc_num, addr, data));
87 return data;
90 void
91 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
92 u8 data, int *err)
94 int status;
95 s32 retry = 0;
97 do {
98 if (retry) /* wait for 1 ms till bus get settled down */
99 udelay(1000);
100 status =
101 brcmf_sdioh_cfg_write(sdiodev->sdioh, fnc_num, addr,
102 (u8 *) &data);
103 } while (status != 0
104 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
105 if (err)
106 *err = status;
108 BRCMF_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
109 __func__, fnc_num, addr, data));
112 int brcmf_sdcard_cis_read(struct brcmf_sdio_dev *sdiodev, uint func, u8 * cis,
113 uint length)
115 int status;
117 u8 *tmp_buf, *tmp_ptr;
118 u8 *ptr;
119 bool ascii = func & ~0xf;
120 func &= 0x7;
122 status = brcmf_sdioh_cis_read(sdiodev->sdioh, func, cis, length);
124 if (ascii) {
125 /* Move binary bits to tmp and format them
126 into the provided buffer. */
127 tmp_buf = kmalloc(length, GFP_ATOMIC);
128 if (tmp_buf == NULL) {
129 BRCMF_ERROR(("%s: out of memory\n", __func__));
130 return -ENOMEM;
132 memcpy(tmp_buf, cis, length);
133 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
134 tmp_ptr++) {
135 ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
136 if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
137 ptr += sprintf((char *)ptr, "\n");
139 kfree(tmp_buf);
142 return status;
145 static int
146 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
148 int err = 0;
149 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
150 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
151 if (!err)
152 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
153 SBSDIO_FUNC1_SBADDRMID,
154 (address >> 16) & SBSDIO_SBADDRMID_MASK,
155 &err);
156 if (!err)
157 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
158 SBSDIO_FUNC1_SBADDRHIGH,
159 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
160 &err);
162 return err;
165 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
167 int status;
168 u32 word = 0;
169 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
171 BRCMF_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
173 if (bar0 != sdiodev->sbwad) {
174 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
175 return 0xFFFFFFFF;
177 sdiodev->sbwad = bar0;
180 addr &= SBSDIO_SB_OFT_ADDR_MASK;
181 if (size == 4)
182 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
184 status = brcmf_sdioh_request_word(sdiodev->sdioh, SDIOH_CMD_TYPE_NORMAL,
185 SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
187 sdiodev->regfail = (status != 0);
189 BRCMF_INFO(("u32data = 0x%x\n", word));
191 /* if ok, return appropriately masked word */
192 if (status == 0) {
193 switch (size) {
194 case sizeof(u8):
195 return word & 0xff;
196 case sizeof(u16):
197 return word & 0xffff;
198 case sizeof(u32):
199 return word;
200 default:
201 sdiodev->regfail = true;
206 /* otherwise, bad sdio access or invalid size */
207 BRCMF_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
208 addr, size));
209 return 0xFFFFFFFF;
212 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
213 u32 data)
215 int status;
216 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
217 int err = 0;
219 BRCMF_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
220 __func__, addr, size * 8, data));
222 if (bar0 != sdiodev->sbwad) {
223 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
224 if (err)
225 return err;
227 sdiodev->sbwad = bar0;
230 addr &= SBSDIO_SB_OFT_ADDR_MASK;
231 if (size == 4)
232 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
233 status =
234 brcmf_sdioh_request_word(sdiodev->sdioh, SDIOH_CMD_TYPE_NORMAL,
235 SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
236 sdiodev->regfail = (status != 0);
238 if (status == 0)
239 return 0;
241 BRCMF_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
242 __func__, data, addr, size));
243 return 0xFFFFFFFF;
246 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
248 return sdiodev->regfail;
252 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
253 uint flags,
254 u8 *buf, uint nbytes, struct sk_buff *pkt,
255 void (*complete)(void *handle, int status,
256 bool sync_waiting),
257 void *handle)
259 int status;
260 uint incr_fix;
261 uint width;
262 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
263 int err = 0;
265 BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
266 __func__, fn, addr, nbytes));
268 /* Async not implemented yet */
269 if (flags & SDIO_REQ_ASYNC)
270 return -ENOTSUPP;
272 if (bar0 != sdiodev->sbwad) {
273 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
274 if (err)
275 return err;
277 sdiodev->sbwad = bar0;
280 addr &= SBSDIO_SB_OFT_ADDR_MASK;
282 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
283 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
284 if (width == 4)
285 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
287 status = brcmf_sdioh_request_buffer(sdiodev->sdioh, SDIOH_DATA_PIO,
288 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
290 return status;
294 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
295 uint flags, u8 *buf, uint nbytes, void *pkt,
296 void (*complete)(void *handle, int status,
297 bool sync_waiting),
298 void *handle)
300 uint incr_fix;
301 uint width;
302 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
303 int err = 0;
305 BRCMF_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
306 __func__, fn, addr, nbytes));
308 /* Async not implemented yet */
309 if (flags & SDIO_REQ_ASYNC)
310 return -ENOTSUPP;
312 if (bar0 != sdiodev->sbwad) {
313 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
314 if (err)
315 return err;
317 sdiodev->sbwad = bar0;
320 addr &= SBSDIO_SB_OFT_ADDR_MASK;
322 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
323 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
324 if (width == 4)
325 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
327 return brcmf_sdioh_request_buffer(sdiodev->sdioh, SDIOH_DATA_PIO,
328 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
331 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
332 u8 *buf, uint nbytes)
334 addr &= SBSDIO_SB_OFT_ADDR_MASK;
335 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
337 return brcmf_sdioh_request_buffer(sdiodev->sdioh, SDIOH_DATA_PIO,
338 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
339 addr, 4, nbytes, buf, NULL);
342 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
344 return brcmf_sdioh_abort(sdiodev->sdioh, fn);
347 u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_dev *sdiodev)
349 return sdiodev->sbwad;
352 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
354 u32 regs = 0;
355 int ret = 0;
357 sdiodev->sdioh = brcmf_sdioh_attach((void *)0);
358 if (!sdiodev->sdioh) {
359 ret = -ENODEV;
360 goto out;
363 regs = SI_ENUM_BASE;
365 /* Report the BAR, to fix if needed */
366 sdiodev->sbwad = SI_ENUM_BASE;
368 /* try to attach to the target device */
369 sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
370 if (!sdiodev->bus) {
371 BRCMF_ERROR(("%s: device attach failed\n", __func__));
372 ret = -ENODEV;
373 goto out;
376 out:
377 if (ret)
378 brcmf_sdio_remove(sdiodev);
380 return ret;
382 EXPORT_SYMBOL(brcmf_sdio_probe);
384 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
386 if (sdiodev->bus) {
387 brcmf_sdbrcm_disconnect(sdiodev->bus);
388 sdiodev->bus = NULL;
391 if (sdiodev->sdioh) {
392 brcmf_sdioh_detach(sdiodev->sdioh);
393 sdiodev->sdioh = NULL;
396 sdiodev->sbwad = 0;
398 return 0;
400 EXPORT_SYMBOL(brcmf_sdio_remove);
402 int brcmf_sdio_register(void)
404 return brcmf_sdio_function_init();
407 void brcmf_sdio_unregister(void)
409 brcmf_sdio_function_cleanup();
412 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
414 if (enable)
415 brcmf_sdbrcm_wd_timer(sdiodev->bus, brcmf_watchdog_ms);
416 else
417 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);