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