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