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