adt3-S dhd_driver source code [1/1]
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.1.579.77.41.1.cn / bcmsdh_sdmmc.c
1 /*
2 * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
3 *
4 * Copyright (C) 1999-2017, Broadcom Corporation
5 *
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
11 *
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
19 *
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
23 *
24 *
25 * <<Broadcom-WL-IPTag/Proprietary,Open:>>
26 *
27 * $Id: bcmsdh_sdmmc.c 710913 2017-07-14 10:17:51Z $
28 */
29 #include <typedefs.h>
30
31 #include <bcmdevs.h>
32 #include <bcmendian.h>
33 #include <bcmutils.h>
34 #include <osl.h>
35 #include <sdio.h> /* SDIO Device and Protocol Specs */
36 #include <sdioh.h> /* Standard SDIO Host Controller Specification */
37 #include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
38 #include <sdiovar.h> /* ioctl/iovars */
39
40 #include <linux/mmc/core.h>
41 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0))
42 #include <drivers/mmc/core/host.h>
43 void
44 mmc_host_clk_hold(struct mmc_host *host)
45 {
46 BCM_REFERENCE(host);
47 return;
48 }
49
50 void
51 mmc_host_clk_release(struct mmc_host *host)
52 {
53 BCM_REFERENCE(host);
54 return;
55 }
56 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8))
57 #include <drivers/mmc/core/host.h>
58 #else
59 #include <linux/mmc/host.h>
60 #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0)) */
61 #include <linux/mmc/card.h>
62 #include <linux/mmc/sdio_func.h>
63 #include <linux/mmc/sdio_ids.h>
64
65 #include <dngl_stats.h>
66 #include <dhd.h>
67 #include <dhd_dbg.h>
68
69 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
70 #include <linux/suspend.h>
71 extern volatile bool dhd_mmc_suspend;
72 #endif
73 #include "bcmsdh_sdmmc.h"
74
75 #ifndef BCMSDH_MODULE
76 extern int sdio_function_init(void);
77 extern void sdio_function_cleanup(void);
78 #endif /* BCMSDH_MODULE */
79
80 #if !defined(OOB_INTR_ONLY)
81 static void IRQHandler(struct sdio_func *func);
82 static void IRQHandlerF2(struct sdio_func *func);
83 #endif /* !defined(OOB_INTR_ONLY) */
84 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
85 #if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
86 extern int sdio_reset_comm(struct mmc_card *card);
87 #else
88 int sdio_reset_comm(struct mmc_card *card)
89 {
90 return 0;
91 }
92 #endif
93 #ifdef GLOBAL_SDMMC_INSTANCE
94 extern PBCMSDH_SDMMC_INSTANCE gInstance;
95 #endif
96
97 #define DEFAULT_SDIO_F2_BLKSIZE 512
98 #ifndef CUSTOM_SDIO_F2_BLKSIZE
99 #define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE
100 #endif
101
102 #define DEFAULT_SDIO_F1_BLKSIZE 64
103 #ifndef CUSTOM_SDIO_F1_BLKSIZE
104 #define CUSTOM_SDIO_F1_BLKSIZE DEFAULT_SDIO_F1_BLKSIZE
105 #endif
106
107 #define MAX_IO_RW_EXTENDED_BLK 511
108
109 uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
110 uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
111 uint sd_f1_blocksize = CUSTOM_SDIO_F1_BLKSIZE;
112
113 #if defined(BT_OVER_SDIO)
114 uint sd_f3_blocksize = 64;
115 #endif /* defined (BT_OVER_SDIO) */
116
117 uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
118
119 uint sd_power = 1; /* Default to SD Slot powered ON */
120 uint sd_clock = 1; /* Default to SD Clock turned ON */
121 uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */
122 uint sd_msglevel = 0x01;
123 uint sd_use_dma = TRUE;
124
125 #ifndef CUSTOM_RXCHAIN
126 #define CUSTOM_RXCHAIN 0
127 #endif
128
129 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
130 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
131 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
132 DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
133
134 #define DMA_ALIGN_MASK 0x03
135 #define MMC_SDIO_ABORT_RETRY_LIMIT 5
136
137 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
138
139 void sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz);
140 uint sdmmc_get_clock_rate(sdioh_info_t *sd);
141 void sdmmc_set_clock_divisor(sdioh_info_t *sd, uint sd_div);
142 #if defined(BT_OVER_SDIO)
143 extern
144 void sdioh_sdmmc_card_enable_func_f3(sdioh_info_t *sd, struct sdio_func *func)
145 {
146 sd->func[3] = func;
147 sd_info(("%s sd->func[3] %p\n", __FUNCTION__, sd->func[3]));
148 }
149 #endif /* defined (BT_OVER_SDIO) */
150
151 static int
152 sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
153 {
154 int err_ret;
155 uint32 fbraddr;
156 uint8 func;
157
158 sd_trace(("%s\n", __FUNCTION__));
159
160 /* Get the Card's common CIS address */
161 sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
162 sd->func_cis_ptr[0] = sd->com_cis_ptr;
163 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
164
165 /* Get the Card's function CIS (for each function) */
166 for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
167 func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
168 sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
169 sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
170 __FUNCTION__, func, sd->func_cis_ptr[func]));
171 }
172
173 sd->func_cis_ptr[0] = sd->com_cis_ptr;
174 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
175
176 /* Enable Function 1 */
177 sdio_claim_host(sd->func[1]);
178 err_ret = sdio_enable_func(sd->func[1]);
179 sdio_release_host(sd->func[1]);
180 if (err_ret) {
181 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x\n", err_ret));
182 }
183
184 return FALSE;
185 }
186
187 /*
188 * Public entry points & extern's
189 */
190 extern sdioh_info_t *
191 sdioh_attach(osl_t *osh, struct sdio_func *func)
192 {
193 sdioh_info_t *sd = NULL;
194 int err_ret;
195
196 sd_trace(("%s\n", __FUNCTION__));
197
198 if (func == NULL) {
199 sd_err(("%s: sdio function device is NULL\n", __FUNCTION__));
200 return NULL;
201 }
202
203 if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
204 sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
205 return NULL;
206 }
207 bzero((char *)sd, sizeof(sdioh_info_t));
208 sd->osh = osh;
209 sd->fake_func0.num = 0;
210 sd->fake_func0.card = func->card;
211 sd->func[0] = &sd->fake_func0;
212 #ifdef GLOBAL_SDMMC_INSTANCE
213 if (func->num == 2)
214 sd->func[1] = gInstance->func[1];
215 #else
216 sd->func[1] = func->card->sdio_func[0];
217 #endif
218 sd->func[2] = func->card->sdio_func[1];
219 #ifdef GLOBAL_SDMMC_INSTANCE
220 sd->func[func->num] = func;
221 #endif
222
223 #if defined(BT_OVER_SDIO)
224 sd->func[3] = NULL;
225 #endif /* defined (BT_OVER_SDIO) */
226
227 sd->num_funcs = 2;
228 sd->sd_blockmode = TRUE;
229 sd->use_client_ints = TRUE;
230 sd->client_block_size[0] = 64;
231 sd->use_rxchain = CUSTOM_RXCHAIN;
232 if (sd->func[1] == NULL || sd->func[2] == NULL) {
233 sd_err(("%s: func 1 or 2 is null \n", __FUNCTION__));
234 goto fail;
235 }
236 sdio_set_drvdata(sd->func[1], sd);
237
238 sdio_claim_host(sd->func[1]);
239 sd->client_block_size[1] = sd_f1_blocksize;
240 err_ret = sdio_set_block_size(sd->func[1], sd_f1_blocksize);
241 sdio_release_host(sd->func[1]);
242 if (err_ret) {
243 sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize(%d)\n", err_ret));
244 goto fail;
245 }
246
247 sdio_claim_host(sd->func[2]);
248 sd->client_block_size[2] = sd_f2_blocksize;
249 printf("%s: set sd_f2_blocksize %d\n", __FUNCTION__, sd_f2_blocksize);
250 err_ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
251 sdio_release_host(sd->func[2]);
252 if (err_ret) {
253 sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d(%d)\n",
254 sd_f2_blocksize, err_ret));
255 goto fail;
256 }
257
258 sd->sd_clk_rate = sdmmc_get_clock_rate(sd);
259 printf("%s: sd clock rate = %u\n", __FUNCTION__, sd->sd_clk_rate);
260 sdioh_sdmmc_card_enablefuncs(sd);
261
262 sd_trace(("%s: Done\n", __FUNCTION__));
263 return sd;
264
265 fail:
266 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
267 return NULL;
268 }
269
270
271 extern SDIOH_API_RC
272 sdioh_detach(osl_t *osh, sdioh_info_t *sd)
273 {
274 sd_trace(("%s\n", __FUNCTION__));
275
276 if (sd) {
277
278 /* Disable Function 2 */
279 if (sd->func[2]) {
280 sdio_claim_host(sd->func[2]);
281 sdio_disable_func(sd->func[2]);
282 sdio_release_host(sd->func[2]);
283 }
284
285 /* Disable Function 1 */
286 if (sd->func[1]) {
287 sdio_claim_host(sd->func[1]);
288 sdio_disable_func(sd->func[1]);
289 sdio_release_host(sd->func[1]);
290 }
291
292 sd->func[1] = NULL;
293 sd->func[2] = NULL;
294
295 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
296 }
297 return SDIOH_API_RC_SUCCESS;
298 }
299
300 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
301
302 extern SDIOH_API_RC
303 sdioh_enable_func_intr(sdioh_info_t *sd)
304 {
305 uint8 reg;
306 int err;
307
308 if (sd->func[0] == NULL) {
309 sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
310 return SDIOH_API_RC_FAIL;
311 }
312
313 sdio_claim_host(sd->func[0]);
314 reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
315 if (err) {
316 sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
317 sdio_release_host(sd->func[0]);
318 return SDIOH_API_RC_FAIL;
319 }
320 /* Enable F1 and F2 interrupts, clear master enable */
321 reg &= ~INTR_CTL_MASTER_EN;
322 reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
323 #if defined(BT_OVER_SDIO)
324 reg |= (INTR_CTL_FUNC3_EN);
325 #endif /* defined (BT_OVER_SDIO) */
326 sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
327 sdio_release_host(sd->func[0]);
328
329 if (err) {
330 sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
331 return SDIOH_API_RC_FAIL;
332 }
333
334 return SDIOH_API_RC_SUCCESS;
335 }
336
337 extern SDIOH_API_RC
338 sdioh_disable_func_intr(sdioh_info_t *sd)
339 {
340 uint8 reg;
341 int err;
342
343 if (sd->func[0] == NULL) {
344 sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
345 return SDIOH_API_RC_FAIL;
346 }
347
348 sdio_claim_host(sd->func[0]);
349 reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
350 if (err) {
351 sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
352 sdio_release_host(sd->func[0]);
353 return SDIOH_API_RC_FAIL;
354 }
355 reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
356 #if defined(BT_OVER_SDIO)
357 reg &= ~INTR_CTL_FUNC3_EN;
358 #endif
359 /* Disable master interrupt with the last function interrupt */
360 if (!(reg & 0xFE))
361 reg = 0;
362 sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
363 sdio_release_host(sd->func[0]);
364
365 if (err) {
366 sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
367 return SDIOH_API_RC_FAIL;
368 }
369
370 return SDIOH_API_RC_SUCCESS;
371 }
372 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
373
374 /* Configure callback to client when we recieve client interrupt */
375 extern SDIOH_API_RC
376 sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
377 {
378 sd_trace(("%s: Entering\n", __FUNCTION__));
379 if (fn == NULL) {
380 sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
381 return SDIOH_API_RC_FAIL;
382 }
383 #if !defined(OOB_INTR_ONLY)
384 sd->intr_handler = fn;
385 sd->intr_handler_arg = argh;
386 sd->intr_handler_valid = TRUE;
387
388 /* register and unmask irq */
389 if (sd->func[2]) {
390 sdio_claim_host(sd->func[2]);
391 sdio_claim_irq(sd->func[2], IRQHandlerF2);
392 sdio_release_host(sd->func[2]);
393 }
394
395 if (sd->func[1]) {
396 sdio_claim_host(sd->func[1]);
397 sdio_claim_irq(sd->func[1], IRQHandler);
398 sdio_release_host(sd->func[1]);
399 }
400 #elif defined(HW_OOB)
401 sdioh_enable_func_intr(sd);
402 #endif /* !defined(OOB_INTR_ONLY) */
403
404 return SDIOH_API_RC_SUCCESS;
405 }
406
407 extern SDIOH_API_RC
408 sdioh_interrupt_deregister(sdioh_info_t *sd)
409 {
410 sd_trace(("%s: Entering\n", __FUNCTION__));
411
412 #if !defined(OOB_INTR_ONLY)
413 if (sd->func[1]) {
414 /* register and unmask irq */
415 sdio_claim_host(sd->func[1]);
416 sdio_release_irq(sd->func[1]);
417 sdio_release_host(sd->func[1]);
418 }
419
420 if (sd->func[2]) {
421 /* Claim host controller F2 */
422 sdio_claim_host(sd->func[2]);
423 sdio_release_irq(sd->func[2]);
424 /* Release host controller F2 */
425 sdio_release_host(sd->func[2]);
426 }
427
428 sd->intr_handler_valid = FALSE;
429 sd->intr_handler = NULL;
430 sd->intr_handler_arg = NULL;
431 #elif defined(HW_OOB)
432 if (dhd_download_fw_on_driverload)
433 sdioh_disable_func_intr(sd);
434 #endif /* !defined(OOB_INTR_ONLY) */
435 return SDIOH_API_RC_SUCCESS;
436 }
437
438 extern SDIOH_API_RC
439 sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
440 {
441 sd_trace(("%s: Entering\n", __FUNCTION__));
442 *onoff = sd->client_intr_enabled;
443 return SDIOH_API_RC_SUCCESS;
444 }
445
446 #if defined(DHD_DEBUG)
447 extern bool
448 sdioh_interrupt_pending(sdioh_info_t *sd)
449 {
450 return (0);
451 }
452 #endif
453
454 uint
455 sdioh_query_iofnum(sdioh_info_t *sd)
456 {
457 return sd->num_funcs;
458 }
459
460 /* IOVar table */
461 enum {
462 IOV_MSGLEVEL = 1,
463 IOV_BLOCKMODE,
464 IOV_BLOCKSIZE,
465 IOV_DMA,
466 IOV_USEINTS,
467 IOV_NUMINTS,
468 IOV_NUMLOCALINTS,
469 IOV_HOSTREG,
470 IOV_DEVREG,
471 IOV_DIVISOR,
472 IOV_SDMODE,
473 IOV_HISPEED,
474 IOV_HCIREGS,
475 IOV_POWER,
476 IOV_CLOCK,
477 IOV_RXCHAIN
478 };
479
480 const bcm_iovar_t sdioh_iovars[] = {
481 {"sd_msglevel", IOV_MSGLEVEL, 0, 0, IOVT_UINT32, 0 },
482 {"sd_blockmode", IOV_BLOCKMODE, 0, 0, IOVT_BOOL, 0 },
483 {"sd_blocksize", IOV_BLOCKSIZE, 0, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
484 {"sd_dma", IOV_DMA, 0, 0, IOVT_BOOL, 0 },
485 {"sd_ints", IOV_USEINTS, 0, 0, IOVT_BOOL, 0 },
486 {"sd_numints", IOV_NUMINTS, 0, 0, IOVT_UINT32, 0 },
487 {"sd_numlocalints", IOV_NUMLOCALINTS, 0, 0, IOVT_UINT32, 0 },
488 {"sd_divisor", IOV_DIVISOR, 0, 0, IOVT_UINT32, 0 },
489 {"sd_power", IOV_POWER, 0, 0, IOVT_UINT32, 0 },
490 {"sd_clock", IOV_CLOCK, 0, 0, IOVT_UINT32, 0 },
491 {"sd_mode", IOV_SDMODE, 0, 0, IOVT_UINT32, 100},
492 {"sd_highspeed", IOV_HISPEED, 0, 0, IOVT_UINT32, 0 },
493 {"sd_rxchain", IOV_RXCHAIN, 0, 0, IOVT_BOOL, 0 },
494 {NULL, 0, 0, 0, 0, 0 }
495 };
496
497 int
498 sdioh_iovar_op(sdioh_info_t *si, const char *name,
499 void *params, int plen, void *arg, int len, bool set)
500 {
501 const bcm_iovar_t *vi = NULL;
502 int bcmerror = 0;
503 int val_size;
504 int32 int_val = 0;
505 bool bool_val;
506 uint32 actionid;
507
508 ASSERT(name);
509 ASSERT(len >= 0);
510
511 /* Get must have return space; Set does not take qualifiers */
512 ASSERT(set || (arg && len));
513 ASSERT(!set || (!params && !plen));
514
515 sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
516
517 if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
518 bcmerror = BCME_UNSUPPORTED;
519 goto exit;
520 }
521
522 if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
523 goto exit;
524
525 /* Set up params so get and set can share the convenience variables */
526 if (params == NULL) {
527 params = arg;
528 plen = len;
529 }
530
531 if (vi->type == IOVT_VOID)
532 val_size = 0;
533 else if (vi->type == IOVT_BUFFER)
534 val_size = len;
535 else
536 val_size = sizeof(int);
537
538 if (plen >= (int)sizeof(int_val))
539 bcopy(params, &int_val, sizeof(int_val));
540
541 bool_val = (int_val != 0) ? TRUE : FALSE;
542 BCM_REFERENCE(bool_val);
543
544 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
545 switch (actionid) {
546 case IOV_GVAL(IOV_MSGLEVEL):
547 int_val = (int32)sd_msglevel;
548 bcopy(&int_val, arg, val_size);
549 break;
550
551 case IOV_SVAL(IOV_MSGLEVEL):
552 sd_msglevel = int_val;
553 break;
554
555 case IOV_GVAL(IOV_BLOCKMODE):
556 int_val = (int32)si->sd_blockmode;
557 bcopy(&int_val, arg, val_size);
558 break;
559
560 case IOV_SVAL(IOV_BLOCKMODE):
561 si->sd_blockmode = (bool)int_val;
562 /* Haven't figured out how to make non-block mode with DMA */
563 break;
564
565 case IOV_GVAL(IOV_BLOCKSIZE):
566 if ((uint32)int_val > si->num_funcs) {
567 bcmerror = BCME_BADARG;
568 break;
569 }
570 int_val = (int32)si->client_block_size[int_val];
571 bcopy(&int_val, arg, val_size);
572 break;
573
574 case IOV_SVAL(IOV_BLOCKSIZE):
575 {
576 uint func = ((uint32)int_val >> 16);
577 uint blksize = (uint16)int_val;
578 uint maxsize;
579
580 if (func > si->num_funcs) {
581 bcmerror = BCME_BADARG;
582 break;
583 }
584
585 switch (func) {
586 case 0: maxsize = 32; break;
587 case 1: maxsize = BLOCK_SIZE_4318; break;
588 case 2: maxsize = BLOCK_SIZE_4328; break;
589 default: maxsize = 0;
590 }
591 if (blksize > maxsize) {
592 bcmerror = BCME_BADARG;
593 break;
594 }
595 if (!blksize) {
596 blksize = maxsize;
597 }
598
599 /* Now set it */
600 si->client_block_size[func] = blksize;
601
602 if (si->func[func] == NULL) {
603 sd_err(("%s: SDIO Device not present\n", __FUNCTION__));
604 bcmerror = BCME_NORESOURCE;
605 break;
606 }
607 sdio_claim_host(si->func[func]);
608 bcmerror = sdio_set_block_size(si->func[func], blksize);
609 if (bcmerror)
610 sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n",
611 __FUNCTION__, func, blksize, bcmerror));
612 sdio_release_host(si->func[func]);
613 break;
614 }
615
616 case IOV_GVAL(IOV_RXCHAIN):
617 int_val = (int32)si->use_rxchain;
618 bcopy(&int_val, arg, val_size);
619 break;
620
621 case IOV_GVAL(IOV_DMA):
622 int_val = (int32)si->sd_use_dma;
623 bcopy(&int_val, arg, val_size);
624 break;
625
626 case IOV_SVAL(IOV_DMA):
627 si->sd_use_dma = (bool)int_val;
628 break;
629
630 case IOV_GVAL(IOV_USEINTS):
631 int_val = (int32)si->use_client_ints;
632 bcopy(&int_val, arg, val_size);
633 break;
634
635 case IOV_SVAL(IOV_USEINTS):
636 si->use_client_ints = (bool)int_val;
637 if (si->use_client_ints)
638 si->intmask |= CLIENT_INTR;
639 else
640 si->intmask &= ~CLIENT_INTR;
641
642 break;
643
644 case IOV_GVAL(IOV_DIVISOR):
645 int_val = (uint32)sd_divisor;
646 bcopy(&int_val, arg, val_size);
647 break;
648
649 case IOV_SVAL(IOV_DIVISOR):
650 /* set the clock to divisor, if value is non-zero & power of 2 */
651 if (int_val && !(int_val & (int_val - 1))) {
652 sd_divisor = int_val;
653 sdmmc_set_clock_divisor(si, sd_divisor);
654 } else {
655 DHD_ERROR(("%s: Invalid sd_divisor value, should be power of 2!\n",
656 __FUNCTION__));
657 }
658 break;
659
660 case IOV_GVAL(IOV_POWER):
661 int_val = (uint32)sd_power;
662 bcopy(&int_val, arg, val_size);
663 break;
664
665 case IOV_SVAL(IOV_POWER):
666 sd_power = int_val;
667 break;
668
669 case IOV_GVAL(IOV_CLOCK):
670 int_val = (uint32)sd_clock;
671 bcopy(&int_val, arg, val_size);
672 break;
673
674 case IOV_SVAL(IOV_CLOCK):
675 sd_clock = int_val;
676 break;
677
678 case IOV_GVAL(IOV_SDMODE):
679 int_val = (uint32)sd_sdmode;
680 bcopy(&int_val, arg, val_size);
681 break;
682
683 case IOV_SVAL(IOV_SDMODE):
684 sd_sdmode = int_val;
685 break;
686
687 case IOV_GVAL(IOV_HISPEED):
688 int_val = (uint32)sd_hiok;
689 bcopy(&int_val, arg, val_size);
690 break;
691
692 case IOV_SVAL(IOV_HISPEED):
693 sd_hiok = int_val;
694 break;
695
696 case IOV_GVAL(IOV_NUMINTS):
697 int_val = (int32)si->intrcount;
698 bcopy(&int_val, arg, val_size);
699 break;
700
701 case IOV_GVAL(IOV_NUMLOCALINTS):
702 int_val = (int32)0;
703 bcopy(&int_val, arg, val_size);
704 break;
705 default:
706 bcmerror = BCME_UNSUPPORTED;
707 break;
708 }
709 exit:
710
711 return bcmerror;
712 }
713
714 #if (defined(OOB_INTR_ONLY) && defined(HW_OOB)) || defined(FORCE_WOWLAN)
715 #ifdef CUSTOMER_HW_AMLOGIC
716 #include <linux/amlogic/aml_gpio_consumer.h>
717 extern int wifi_irq_trigger_level(void);
718 #endif
719 SDIOH_API_RC
720 sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
721 {
722 SDIOH_API_RC status;
723 uint8 data;
724
725 if (enable) {
726 if (wifi_irq_trigger_level() == GPIO_IRQ_LOW)
727 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
728 else
729 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI;
730 }
731 else
732 data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */
733
734 status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data);
735 return status;
736 }
737 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
738
739 extern SDIOH_API_RC
740 sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
741 {
742 SDIOH_API_RC status;
743 /* No lock needed since sdioh_request_byte does locking */
744 status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
745 return status;
746 }
747
748 extern SDIOH_API_RC
749 sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
750 {
751 /* No lock needed since sdioh_request_byte does locking */
752 SDIOH_API_RC status;
753 status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
754 return status;
755 }
756
757 static int
758 sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr)
759 {
760 /* read 24 bits and return valid 17 bit addr */
761 int i;
762 uint32 scratch, regdata;
763 uint8 *ptr = (uint8 *)&scratch;
764 for (i = 0; i < 3; i++) {
765 if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, &regdata)) != SUCCESS)
766 sd_err(("%s: Can't read!\n", __FUNCTION__));
767
768 *ptr++ = (uint8) regdata;
769 regaddr++;
770 }
771
772 /* Only the lower 17-bits are valid */
773 scratch = ltoh32(scratch);
774 scratch &= 0x0001FFFF;
775 return (scratch);
776 }
777
778 extern SDIOH_API_RC
779 sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
780 {
781 uint32 count;
782 int offset;
783 uint32 foo;
784 uint8 *cis = cisd;
785
786 sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
787
788 if (!sd->func_cis_ptr[func]) {
789 bzero(cis, length);
790 sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
791 return SDIOH_API_RC_FAIL;
792 }
793
794 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
795
796 for (count = 0; count < length; count++) {
797 offset = sd->func_cis_ptr[func] + count;
798 if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) {
799 sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
800 return SDIOH_API_RC_FAIL;
801 }
802
803 *cis = (uint8)(foo & 0xff);
804 cis++;
805 }
806
807 return SDIOH_API_RC_SUCCESS;
808 }
809
810 extern SDIOH_API_RC
811 sdioh_cisaddr_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 offset)
812 {
813 uint32 foo;
814
815 sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
816
817 if (!sd->func_cis_ptr[func]) {
818 sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
819 return SDIOH_API_RC_FAIL;
820 }
821
822 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
823
824 if (sdioh_sdmmc_card_regread (sd, 0, sd->func_cis_ptr[func]+offset, 1, &foo) < 0) {
825 sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
826 return SDIOH_API_RC_FAIL;
827 }
828
829 *cisd = (uint8)(foo & 0xff);
830
831 return SDIOH_API_RC_SUCCESS;
832 }
833
834 extern SDIOH_API_RC
835 sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
836 {
837 int err_ret = 0;
838 #if defined(MMC_SDIO_ABORT)
839 int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
840 #endif
841 struct timespec now, before;
842
843 if (sd_msglevel & SDH_COST_VAL)
844 getnstimeofday(&before);
845
846 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
847
848 DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
849 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
850 if(rw) { /* CMD52 Write */
851 if (func == 0) {
852 /* Can only directly write to some F0 registers. Handle F2 enable
853 * as a special case.
854 */
855 if (regaddr == SDIOD_CCCR_IOEN) {
856 #if defined(BT_OVER_SDIO)
857 do {
858 if (sd->func[3]) {
859 sd_info(("bcmsdh_sdmmc F3: *byte 0x%x\n", *byte));
860
861 if (*byte & SDIO_FUNC_ENABLE_3) {
862 sdio_claim_host(sd->func[3]);
863
864 /* Set Function 3 Block Size */
865 err_ret = sdio_set_block_size(sd->func[3],
866 sd_f3_blocksize);
867 if (err_ret) {
868 sd_err(("F3 blocksize set err%d\n",
869 err_ret));
870 }
871
872 /* Enable Function 3 */
873 sd_info(("bcmsdh_sdmmc F3: enable F3 fn %p\n",
874 sd->func[3]));
875 err_ret = sdio_enable_func(sd->func[3]);
876 if (err_ret) {
877 sd_err(("bcmsdh_sdmmc: enable F3 err:%d\n",
878 err_ret));
879 }
880
881 sdio_release_host(sd->func[3]);
882
883 break;
884 } else if (*byte & SDIO_FUNC_DISABLE_3) {
885 sdio_claim_host(sd->func[3]);
886
887 /* Disable Function 3 */
888 sd_info(("bcmsdh_sdmmc F3: disable F3 fn %p\n",
889 sd->func[3]));
890 err_ret = sdio_disable_func(sd->func[3]);
891 if (err_ret) {
892 sd_err(("bcmsdh_sdmmc: Disable F3 err:%d\n",
893 err_ret));
894 }
895 sdio_release_host(sd->func[3]);
896 sd->func[3] = NULL;
897
898 break;
899 }
900 }
901 #endif /* defined (BT_OVER_SDIO) */
902 if (sd->func[2]) {
903 sdio_claim_host(sd->func[2]);
904 if (*byte & SDIO_FUNC_ENABLE_2) {
905 /* Enable Function 2 */
906 err_ret = sdio_enable_func(sd->func[2]);
907 if (err_ret) {
908 sd_err(("bcmsdh_sdmmc: enable F2 failed:%d\n",
909 err_ret));
910 }
911 } else {
912 /* Disable Function 2 */
913 err_ret = sdio_disable_func(sd->func[2]);
914 if (err_ret) {
915 sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d\n",
916 err_ret));
917 }
918 }
919 sdio_release_host(sd->func[2]);
920 }
921 #if defined(BT_OVER_SDIO)
922 } while (0);
923 #endif /* defined (BT_OVER_SDIO) */
924 }
925 #if defined(MMC_SDIO_ABORT)
926 /* to allow abort command through F1 */
927 else if (regaddr == SDIOD_CCCR_IOABORT) {
928 while (sdio_abort_retry--) {
929 if (sd->func[func]) {
930 sdio_claim_host(sd->func[func]);
931 /*
932 * this sdio_f0_writeb() can be replaced with
933 * another api depending upon MMC driver change.
934 * As of this time, this is temporaray one
935 */
936 sdio_writeb(sd->func[func],
937 *byte, regaddr, &err_ret);
938 sdio_release_host(sd->func[func]);
939 }
940 if (!err_ret)
941 break;
942 }
943 }
944 #endif /* MMC_SDIO_ABORT */
945 else if (regaddr < 0xF0) {
946 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
947 } else {
948 /* Claim host controller, perform F0 write, and release */
949 if (sd->func[func]) {
950 sdio_claim_host(sd->func[func]);
951 sdio_f0_writeb(sd->func[func],
952 *byte, regaddr, &err_ret);
953 sdio_release_host(sd->func[func]);
954 }
955 }
956 } else {
957 /* Claim host controller, perform Fn write, and release */
958 if (sd->func[func]) {
959 sdio_claim_host(sd->func[func]);
960 sdio_writeb(sd->func[func], *byte, regaddr, &err_ret);
961 sdio_release_host(sd->func[func]);
962 }
963 }
964 } else { /* CMD52 Read */
965 /* Claim host controller, perform Fn read, and release */
966 if (sd->func[func]) {
967 sdio_claim_host(sd->func[func]);
968 if (func == 0) {
969 *byte = sdio_f0_readb(sd->func[func], regaddr, &err_ret);
970 } else {
971 *byte = sdio_readb(sd->func[func], regaddr, &err_ret);
972 }
973 sdio_release_host(sd->func[func]);
974 }
975 }
976
977 if (err_ret) {
978 if ((regaddr == 0x1001F) && ((err_ret == -ETIMEDOUT) || (err_ret == -EILSEQ)
979 || (err_ret == -EIO))) {
980 } else {
981 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
982 rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
983 }
984 }
985
986 if (sd_msglevel & SDH_COST_VAL) {
987 getnstimeofday(&now);
988 sd_cost(("%s: rw=%d len=1 cost=%lds %luus\n", __FUNCTION__,
989 rw, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
990 }
991
992 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
993 }
994
995 uint
996 sdioh_set_mode(sdioh_info_t *sd, uint mode)
997 {
998 if (mode == SDPCM_TXGLOM_CPY)
999 sd->txglom_mode = mode;
1000 else if (mode == SDPCM_TXGLOM_MDESC)
1001 sd->txglom_mode = mode;
1002
1003 return (sd->txglom_mode);
1004 }
1005
1006 extern SDIOH_API_RC
1007 sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
1008 uint32 *word, uint nbytes)
1009 {
1010 int err_ret = SDIOH_API_RC_FAIL;
1011 int err_ret2 = SDIOH_API_RC_SUCCESS; // terence 20130621: prevent dhd_dpc in dead lock
1012 #if defined(MMC_SDIO_ABORT)
1013 int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
1014 #endif
1015 struct timespec now, before;
1016
1017 if (sd_msglevel & SDH_COST_VAL)
1018 getnstimeofday(&before);
1019
1020 if (func == 0) {
1021 sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
1022 return SDIOH_API_RC_FAIL;
1023 }
1024
1025 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
1026 __FUNCTION__, cmd_type, rw, func, addr, nbytes));
1027
1028 DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
1029 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
1030 /* Claim host controller */
1031 sdio_claim_host(sd->func[func]);
1032
1033 if(rw) { /* CMD52 Write */
1034 if (nbytes == 4) {
1035 sdio_writel(sd->func[func], *word, addr, &err_ret);
1036 } else if (nbytes == 2) {
1037 sdio_writew(sd->func[func], (*word & 0xFFFF), addr, &err_ret);
1038 } else {
1039 sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
1040 }
1041 } else { /* CMD52 Read */
1042 if (nbytes == 4) {
1043 *word = sdio_readl(sd->func[func], addr, &err_ret);
1044 } else if (nbytes == 2) {
1045 *word = sdio_readw(sd->func[func], addr, &err_ret) & 0xFFFF;
1046 } else {
1047 sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
1048 }
1049 }
1050
1051 /* Release host controller */
1052 sdio_release_host(sd->func[func]);
1053
1054 if (err_ret) {
1055 #if defined(MMC_SDIO_ABORT)
1056 /* Any error on CMD53 transaction should abort that function using function 0. */
1057 while (sdio_abort_retry--) {
1058 if (sd->func[0]) {
1059 sdio_claim_host(sd->func[0]);
1060 /*
1061 * this sdio_f0_writeb() can be replaced with another api
1062 * depending upon MMC driver change.
1063 * As of this time, this is temporaray one
1064 */
1065 sdio_writeb(sd->func[0],
1066 func, SDIOD_CCCR_IOABORT, &err_ret2);
1067 sdio_release_host(sd->func[0]);
1068 }
1069 if (!err_ret2)
1070 break;
1071 }
1072 if (err_ret)
1073 #endif /* MMC_SDIO_ABORT */
1074 {
1075 sd_err(("bcmsdh_sdmmc: Failed to %s word F%d:@0x%05x=%02x, Err: 0x%08x\n",
1076 rw ? "Write" : "Read", func, addr, *word, err_ret));
1077 }
1078 }
1079
1080 if (sd_msglevel & SDH_COST_VAL) {
1081 getnstimeofday(&now);
1082 sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
1083 rw, nbytes, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
1084 }
1085
1086 return (((err_ret == 0)&&(err_ret2 == 0)) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
1087 }
1088
1089 #ifdef BCMSDIOH_TXGLOM
1090 static SDIOH_API_RC
1091 sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
1092 uint addr, void *pkt)
1093 {
1094 bool fifo = (fix_inc == SDIOH_DATA_FIX);
1095 int err_ret = 0;
1096 void *pnext;
1097 uint ttl_len, pkt_offset;
1098 uint blk_num;
1099 uint blk_size;
1100 uint max_blk_count;
1101 uint max_req_size;
1102 struct mmc_request mmc_req;
1103 struct mmc_command mmc_cmd;
1104 struct mmc_data mmc_dat;
1105 uint32 sg_count;
1106 struct sdio_func *sdio_func = sd->func[func];
1107 struct mmc_host *host = sdio_func->card->host;
1108 uint8 *localbuf = NULL;
1109 uint local_plen = 0;
1110 uint pkt_len = 0;
1111 struct timespec now, before;
1112
1113 sd_trace(("%s: Enter\n", __FUNCTION__));
1114 ASSERT(pkt);
1115 DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
1116 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
1117
1118 if (sd_msglevel & SDH_COST_VAL)
1119 getnstimeofday(&before);
1120
1121 blk_size = sd->client_block_size[func];
1122 max_blk_count = min(host->max_blk_count, (uint)MAX_IO_RW_EXTENDED_BLK);
1123 max_req_size = min(max_blk_count * blk_size, host->max_req_size);
1124
1125 pkt_offset = 0;
1126 pnext = pkt;
1127
1128 ttl_len = 0;
1129 sg_count = 0;
1130 if(sd->txglom_mode == SDPCM_TXGLOM_MDESC) {
1131 while (pnext != NULL) {
1132 ttl_len = 0;
1133 sg_count = 0;
1134 memset(&mmc_req, 0, sizeof(struct mmc_request));
1135 memset(&mmc_cmd, 0, sizeof(struct mmc_command));
1136 memset(&mmc_dat, 0, sizeof(struct mmc_data));
1137 sg_init_table(sd->sg_list, ARRAYSIZE(sd->sg_list));
1138
1139 /* Set up scatter-gather DMA descriptors. this loop is to find out the max
1140 * data we can transfer with one command 53. blocks per command is limited by
1141 * host max_req_size and 9-bit max block number. when the total length of this
1142 * packet chain is bigger than max_req_size, use multiple SD_IO_RW_EXTENDED
1143 * commands (each transfer is still block aligned)
1144 */
1145 while (pnext != NULL && ttl_len < max_req_size) {
1146 int pkt_len;
1147 int sg_data_size;
1148 uint8 *pdata = (uint8*)PKTDATA(sd->osh, pnext);
1149
1150 ASSERT(pdata != NULL);
1151 pkt_len = PKTLEN(sd->osh, pnext);
1152 sd_trace(("%s[%d] data=%p, len=%d\n", __FUNCTION__, write, pdata, pkt_len));
1153 /* sg_count is unlikely larger than the array size, and this is
1154 * NOT something we can handle here, but in case it happens, PLEASE put
1155 * a restriction on max tx/glom count (based on host->max_segs).
1156 */
1157 if (sg_count >= ARRAYSIZE(sd->sg_list)) {
1158 sd_err(("%s: sg list entries exceed limit %d\n", __FUNCTION__, sg_count));
1159 return (SDIOH_API_RC_FAIL);
1160 }
1161 pdata += pkt_offset;
1162
1163 sg_data_size = pkt_len - pkt_offset;
1164 if (sg_data_size > max_req_size - ttl_len)
1165 sg_data_size = max_req_size - ttl_len;
1166 /* some platforms put a restriction on the data size of each scatter-gather
1167 * DMA descriptor, use multiple sg buffers when xfer_size is bigger than
1168 * max_seg_size
1169 */
1170 if (sg_data_size > host->max_seg_size)
1171 sg_data_size = host->max_seg_size;
1172 sg_set_buf(&sd->sg_list[sg_count++], pdata, sg_data_size);
1173
1174 ttl_len += sg_data_size;
1175 pkt_offset += sg_data_size;
1176 if (pkt_offset == pkt_len) {
1177 pnext = PKTNEXT(sd->osh, pnext);
1178 pkt_offset = 0;
1179 }
1180 }
1181
1182 if (ttl_len % blk_size != 0) {
1183 sd_err(("%s, data length %d not aligned to block size %d\n",
1184 __FUNCTION__, ttl_len, blk_size));
1185 return SDIOH_API_RC_FAIL;
1186 }
1187 blk_num = ttl_len / blk_size;
1188 mmc_dat.sg = sd->sg_list;
1189 mmc_dat.sg_len = sg_count;
1190 mmc_dat.blksz = blk_size;
1191 mmc_dat.blocks = blk_num;
1192 mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1193 mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */
1194 mmc_cmd.arg = write ? 1<<31 : 0;
1195 mmc_cmd.arg |= (func & 0x7) << 28;
1196 mmc_cmd.arg |= 1<<27;
1197 mmc_cmd.arg |= fifo ? 0 : 1<<26;
1198 mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
1199 mmc_cmd.arg |= blk_num & 0x1FF;
1200 mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1201 mmc_req.cmd = &mmc_cmd;
1202 mmc_req.data = &mmc_dat;
1203 if (!fifo)
1204 addr += ttl_len;
1205
1206 sdio_claim_host(sdio_func);
1207 mmc_set_data_timeout(&mmc_dat, sdio_func->card);
1208 mmc_wait_for_req(host, &mmc_req);
1209 sdio_release_host(sdio_func);
1210
1211 err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
1212 if (0 != err_ret) {
1213 sd_err(("%s:CMD53 %s failed with code %d\n",
1214 __FUNCTION__, write ? "write" : "read", err_ret));
1215 return SDIOH_API_RC_FAIL;
1216 }
1217 }
1218 } else if(sd->txglom_mode == SDPCM_TXGLOM_CPY) {
1219 for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
1220 ttl_len += PKTLEN(sd->osh, pnext);
1221 }
1222 /* Claim host controller */
1223 sdio_claim_host(sd->func[func]);
1224 for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
1225 uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext);
1226 pkt_len = PKTLEN(sd->osh, pnext);
1227
1228 if (!localbuf) {
1229 localbuf = (uint8 *)MALLOC(sd->osh, ttl_len);
1230 if (localbuf == NULL) {
1231 sd_err(("%s: %s TXGLOM: localbuf malloc FAILED\n",
1232 __FUNCTION__, (write) ? "TX" : "RX"));
1233 goto txglomfail;
1234 }
1235 }
1236
1237 bcopy(buf, (localbuf + local_plen), pkt_len);
1238 local_plen += pkt_len;
1239 if (PKTNEXT(sd->osh, pnext))
1240 continue;
1241
1242 buf = localbuf;
1243 pkt_len = local_plen;
1244 txglomfail:
1245 /* Align Patch */
1246 if (!write || pkt_len < 32)
1247 pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
1248 else if (pkt_len % blk_size)
1249 pkt_len += blk_size - (pkt_len % blk_size);
1250
1251 if ((write) && (!fifo))
1252 err_ret = sdio_memcpy_toio(
1253 sd->func[func],
1254 addr, buf, pkt_len);
1255 else if (write)
1256 err_ret = sdio_memcpy_toio(
1257 sd->func[func],
1258 addr, buf, pkt_len);
1259 else if (fifo)
1260 err_ret = sdio_readsb(
1261 sd->func[func],
1262 buf, addr, pkt_len);
1263 else
1264 err_ret = sdio_memcpy_fromio(
1265 sd->func[func],
1266 buf, addr, pkt_len);
1267
1268 if (err_ret)
1269 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
1270 __FUNCTION__,
1271 (write) ? "TX" : "RX",
1272 pnext, sg_count, addr, pkt_len, err_ret));
1273 else
1274 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
1275 __FUNCTION__,
1276 (write) ? "TX" : "RX",
1277 pnext, sg_count, addr, pkt_len));
1278
1279 if (!fifo)
1280 addr += pkt_len;
1281 sg_count ++;
1282 }
1283 sdio_release_host(sd->func[func]);
1284 } else {
1285 sd_err(("%s: set to wrong glom mode %d\n", __FUNCTION__, sd->txglom_mode));
1286 return SDIOH_API_RC_FAIL;
1287 }
1288
1289 if (localbuf)
1290 MFREE(sd->osh, localbuf, ttl_len);
1291
1292 if (sd_msglevel & SDH_COST_VAL) {
1293 getnstimeofday(&now);
1294 sd_cost(("%s: rw=%d, ttl_len=%d, cost=%lds %luus\n", __FUNCTION__,
1295 write, ttl_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
1296 }
1297
1298 sd_trace(("%s: Exit\n", __FUNCTION__));
1299 return SDIOH_API_RC_SUCCESS;
1300 }
1301 #endif /* BCMSDIOH_TXGLOM */
1302
1303 static SDIOH_API_RC
1304 sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
1305 uint addr, uint8 *buf, uint len)
1306 {
1307 bool fifo = (fix_inc == SDIOH_DATA_FIX);
1308 int err_ret = 0;
1309 struct timespec now, before;
1310
1311 sd_trace(("%s: Enter\n", __FUNCTION__));
1312 ASSERT(buf);
1313
1314 if (sd_msglevel & SDH_COST_VAL)
1315 getnstimeofday(&before);
1316
1317 /* NOTE:
1318 * For all writes, each packet length is aligned to 32 (or 4)
1319 * bytes in dhdsdio_txpkt_preprocess, and for glom the last packet length
1320 * is aligned to block boundary. If you want to align each packet to
1321 * a custom size, please do it in dhdsdio_txpkt_preprocess, NOT here
1322 *
1323 * For reads, the alignment is doen in sdioh_request_buffer.
1324 *
1325 */
1326 sdio_claim_host(sd->func[func]);
1327
1328 if ((write) && (!fifo))
1329 err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
1330 else if (write)
1331 err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
1332 else if (fifo)
1333 err_ret = sdio_readsb(sd->func[func], buf, addr, len);
1334 else
1335 err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, len);
1336
1337 sdio_release_host(sd->func[func]);
1338
1339 if (err_ret)
1340 sd_err(("%s: %s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=%d\n", __FUNCTION__,
1341 (write) ? "TX" : "RX", buf, addr, len, err_ret));
1342 else
1343 sd_trace(("%s: %s xfr'd %p, addr=0x%05x, len=%d\n", __FUNCTION__,
1344 (write) ? "TX" : "RX", buf, addr, len));
1345
1346 sd_trace(("%s: Exit\n", __FUNCTION__));
1347
1348 if (sd_msglevel & SDH_COST_VAL) {
1349 getnstimeofday(&now);
1350 sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
1351 write, len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
1352 }
1353
1354 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
1355 }
1356
1357
1358 /*
1359 * This function takes a buffer or packet, and fixes everything up so that in the
1360 * end, a DMA-able packet is created.
1361 *
1362 * A buffer does not have an associated packet pointer, and may or may not be aligned.
1363 * A packet may consist of a single packet, or a packet chain. If it is a packet chain,
1364 * then all the packets in the chain must be properly aligned. If the packet data is not
1365 * aligned, then there may only be one packet, and in this case, it is copied to a new
1366 * aligned packet.
1367 *
1368 */
1369 extern SDIOH_API_RC
1370 sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
1371 uint addr, uint reg_width, uint buf_len, uint8 *buffer, void *pkt)
1372 {
1373 SDIOH_API_RC status;
1374 void *tmppkt;
1375 struct timespec now, before;
1376
1377 sd_trace(("%s: Enter\n", __FUNCTION__));
1378 DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
1379 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
1380
1381 if (sd_msglevel & SDH_COST_VAL)
1382 getnstimeofday(&before);
1383
1384 if (pkt) {
1385 #ifdef BCMSDIOH_TXGLOM
1386 /* packet chain, only used for tx/rx glom, all packets length
1387 * are aligned, total length is a block multiple
1388 */
1389 if (PKTNEXT(sd->osh, pkt))
1390 return sdioh_request_packet_chain(sd, fix_inc, write, func, addr, pkt);
1391 #endif /* BCMSDIOH_TXGLOM */
1392 /* non-glom mode, ignore the buffer parameter and use the packet pointer
1393 * (this shouldn't happen)
1394 */
1395 buffer = PKTDATA(sd->osh, pkt);
1396 buf_len = PKTLEN(sd->osh, pkt);
1397 }
1398
1399 ASSERT(buffer);
1400
1401 /* buffer and length are aligned, use it directly so we can avoid memory copy */
1402 if (((ulong)buffer & DMA_ALIGN_MASK) == 0 && (buf_len & DMA_ALIGN_MASK) == 0)
1403 return sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr, buffer, buf_len);
1404
1405 sd_trace(("%s: [%d] doing memory copy buf=%p, len=%d\n",
1406 __FUNCTION__, write, buffer, buf_len));
1407
1408 /* otherwise, a memory copy is needed as the input buffer is not aligned */
1409 tmppkt = PKTGET_STATIC(sd->osh, buf_len + DEFAULT_SDIO_F2_BLKSIZE, write ? TRUE : FALSE);
1410 if (tmppkt == NULL) {
1411 sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buf_len));
1412 return SDIOH_API_RC_FAIL;
1413 }
1414
1415 if (write)
1416 bcopy(buffer, PKTDATA(sd->osh, tmppkt), buf_len);
1417
1418 status = sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,
1419 PKTDATA(sd->osh, tmppkt), ROUNDUP(buf_len, (DMA_ALIGN_MASK+1)));
1420
1421 if (!write)
1422 bcopy(PKTDATA(sd->osh, tmppkt), buffer, buf_len);
1423
1424 PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
1425
1426 if (sd_msglevel & SDH_COST_VAL) {
1427 getnstimeofday(&now);
1428 sd_cost(("%s: len=%d cost=%lds %luus\n", __FUNCTION__,
1429 buf_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
1430 }
1431
1432 return status;
1433 }
1434
1435 /* this function performs "abort" for both of host & device */
1436 extern int
1437 sdioh_abort(sdioh_info_t *sd, uint func)
1438 {
1439 #if defined(MMC_SDIO_ABORT)
1440 char t_func = (char) func;
1441 #endif /* defined(MMC_SDIO_ABORT) */
1442 sd_trace(("%s: Enter\n", __FUNCTION__));
1443
1444 #if defined(MMC_SDIO_ABORT)
1445 /* issue abort cmd52 command through F1 */
1446 sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
1447 #endif /* defined(MMC_SDIO_ABORT) */
1448
1449 sd_trace(("%s: Exit\n", __FUNCTION__));
1450 return SDIOH_API_RC_SUCCESS;
1451 }
1452
1453 /* Reset and re-initialize the device */
1454 int sdioh_sdio_reset(sdioh_info_t *si)
1455 {
1456 sd_trace(("%s: Enter\n", __FUNCTION__));
1457 sd_trace(("%s: Exit\n", __FUNCTION__));
1458 return SDIOH_API_RC_SUCCESS;
1459 }
1460
1461 /* Disable device interrupt */
1462 void
1463 sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
1464 {
1465 sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
1466 sd->intmask &= ~CLIENT_INTR;
1467 }
1468
1469 /* Enable device interrupt */
1470 void
1471 sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
1472 {
1473 sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
1474 sd->intmask |= CLIENT_INTR;
1475 }
1476
1477 /* Read client card reg */
1478 int
1479 sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
1480 {
1481
1482 if ((func == 0) || (regsize == 1)) {
1483 uint8 temp = 0;
1484
1485 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1486 *data = temp;
1487 *data &= 0xff;
1488 sd_data(("%s: byte read data=0x%02x\n",
1489 __FUNCTION__, *data));
1490 } else {
1491 if (sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize)) {
1492 return BCME_SDIO_ERROR;
1493 }
1494
1495 if (regsize == 2)
1496 *data &= 0xffff;
1497
1498 sd_data(("%s: word read data=0x%08x\n",
1499 __FUNCTION__, *data));
1500 }
1501
1502 return SUCCESS;
1503 }
1504
1505 #if !defined(OOB_INTR_ONLY)
1506 /* bcmsdh_sdmmc interrupt handler */
1507 static void IRQHandler(struct sdio_func *func)
1508 {
1509 sdioh_info_t *sd;
1510
1511 sd = sdio_get_drvdata(func);
1512
1513 ASSERT(sd != NULL);
1514 sdio_release_host(sd->func[0]);
1515
1516 if (sd->use_client_ints) {
1517 sd->intrcount++;
1518 ASSERT(sd->intr_handler);
1519 ASSERT(sd->intr_handler_arg);
1520 (sd->intr_handler)(sd->intr_handler_arg);
1521 } else {
1522 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
1523
1524 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
1525 __FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
1526 }
1527
1528 sdio_claim_host(sd->func[0]);
1529 }
1530
1531 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
1532 static void IRQHandlerF2(struct sdio_func *func)
1533 {
1534 sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
1535 }
1536 #endif /* !defined(OOB_INTR_ONLY) */
1537
1538 #ifdef NOTUSED
1539 /* Write client card reg */
1540 static int
1541 sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
1542 {
1543
1544 if ((func == 0) || (regsize == 1)) {
1545 uint8 temp;
1546
1547 temp = data & 0xff;
1548 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1549 sd_data(("%s: byte write data=0x%02x\n",
1550 __FUNCTION__, data));
1551 } else {
1552 if (regsize == 2)
1553 data &= 0xffff;
1554
1555 sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize);
1556
1557 sd_data(("%s: word write data=0x%08x\n",
1558 __FUNCTION__, data));
1559 }
1560
1561 return SUCCESS;
1562 }
1563 #endif /* NOTUSED */
1564
1565 int
1566 sdioh_start(sdioh_info_t *sd, int stage)
1567 {
1568 int ret;
1569
1570 if (!sd) {
1571 sd_err(("%s Failed, sd is NULL\n", __FUNCTION__));
1572 return (0);
1573 }
1574
1575 /* Need to do this stages as we can't enable the interrupt till
1576 downloading of the firmware is complete, other wise polling
1577 sdio access will come in way
1578 */
1579 if (sd->func[0]) {
1580 if (stage == 0) {
1581 /* Since the power to the chip is killed, we will have
1582 re enumerate the device again. Set the block size
1583 and enable the fucntion 1 for in preparation for
1584 downloading the code
1585 */
1586 /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
1587 2.6.27. The implementation prior to that is buggy, and needs broadcom's
1588 patch for it
1589 */
1590 if ((ret = sdio_reset_comm(sd->func[0]->card))) {
1591 sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
1592 return ret;
1593 }
1594 else {
1595 sd->num_funcs = 2;
1596 sd->sd_blockmode = TRUE;
1597 sd->use_client_ints = TRUE;
1598 sd->client_block_size[0] = 64;
1599
1600 if (sd->func[1]) {
1601 /* Claim host controller */
1602 sdio_claim_host(sd->func[1]);
1603
1604 sd->client_block_size[1] = 64;
1605 ret = sdio_set_block_size(sd->func[1], 64);
1606 if (ret) {
1607 sd_err(("bcmsdh_sdmmc: Failed to set F1 "
1608 "blocksize(%d)\n", ret));
1609 }
1610
1611 /* Release host controller F1 */
1612 sdio_release_host(sd->func[1]);
1613 }
1614
1615 if (sd->func[2]) {
1616 /* Claim host controller F2 */
1617 sdio_claim_host(sd->func[2]);
1618
1619 sd->client_block_size[2] = sd_f2_blocksize;
1620 printf("%s: set sd_f2_blocksize %d\n", __FUNCTION__, sd_f2_blocksize);
1621 ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
1622 if (ret) {
1623 sd_err(("bcmsdh_sdmmc: Failed to set F2 "
1624 "blocksize to %d(%d)\n", sd_f2_blocksize, ret));
1625 }
1626
1627 /* Release host controller F2 */
1628 sdio_release_host(sd->func[2]);
1629 }
1630
1631 sdioh_sdmmc_card_enablefuncs(sd);
1632 }
1633 } else {
1634 #if !defined(OOB_INTR_ONLY)
1635 sdio_claim_host(sd->func[0]);
1636 if (sd->func[2])
1637 sdio_claim_irq(sd->func[2], IRQHandlerF2);
1638 if (sd->func[1])
1639 sdio_claim_irq(sd->func[1], IRQHandler);
1640 sdio_release_host(sd->func[0]);
1641 #else /* defined(OOB_INTR_ONLY) */
1642 #if defined(HW_OOB)
1643 sdioh_enable_func_intr(sd);
1644 #endif
1645 bcmsdh_oob_intr_set(sd->bcmsdh, TRUE);
1646 #endif /* !defined(OOB_INTR_ONLY) */
1647 }
1648 }
1649 else
1650 sd_err(("%s Failed\n", __FUNCTION__));
1651
1652 return (0);
1653 }
1654
1655 int
1656 sdioh_stop(sdioh_info_t *sd)
1657 {
1658 /* MSM7201A Android sdio stack has bug with interrupt
1659 So internaly within SDIO stack they are polling
1660 which cause issue when device is turned off. So
1661 unregister interrupt with SDIO stack to stop the
1662 polling
1663 */
1664 if (sd->func[0]) {
1665 #if !defined(OOB_INTR_ONLY)
1666 sdio_claim_host(sd->func[0]);
1667 if (sd->func[1])
1668 sdio_release_irq(sd->func[1]);
1669 if (sd->func[2])
1670 sdio_release_irq(sd->func[2]);
1671 sdio_release_host(sd->func[0]);
1672 #else /* defined(OOB_INTR_ONLY) */
1673 #if defined(HW_OOB)
1674 sdioh_disable_func_intr(sd);
1675 #endif
1676 bcmsdh_oob_intr_set(sd->bcmsdh, FALSE);
1677 #endif /* !defined(OOB_INTR_ONLY) */
1678 }
1679 else
1680 sd_err(("%s Failed\n", __FUNCTION__));
1681 return (0);
1682 }
1683
1684 int
1685 sdioh_waitlockfree(sdioh_info_t *sd)
1686 {
1687 return (1);
1688 }
1689
1690
1691 SDIOH_API_RC
1692 sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
1693 {
1694 return SDIOH_API_RC_FAIL;
1695 }
1696
1697 SDIOH_API_RC
1698 sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
1699 {
1700 return SDIOH_API_RC_FAIL;
1701 }
1702
1703 bool
1704 sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
1705 {
1706 return FALSE;
1707 }
1708
1709 SDIOH_API_RC
1710 sdioh_gpio_init(sdioh_info_t *sd)
1711 {
1712 return SDIOH_API_RC_FAIL;
1713 }
1714
1715 uint
1716 sdmmc_get_clock_rate(sdioh_info_t *sd)
1717 {
1718 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1719 return 0;
1720 #else
1721 struct sdio_func *sdio_func = sd->func[0];
1722 struct mmc_host *host = sdio_func->card->host;
1723 return mmc_host_clk_rate(host);
1724 #endif
1725 }
1726
1727
1728 void
1729 sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz)
1730 {
1731 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1732 return;
1733 #else
1734 struct sdio_func *sdio_func = sd->func[0];
1735 struct mmc_host *host = sdio_func->card->host;
1736 struct mmc_ios *ios = &host->ios;
1737
1738 mmc_host_clk_hold(host);
1739 DHD_INFO(("%s: Before change: sd clock rate is %u\n", __FUNCTION__, ios->clock));
1740 if (hz < host->f_min) {
1741 DHD_ERROR(("%s: Intended rate is below min rate, setting to min\n", __FUNCTION__));
1742 hz = host->f_min;
1743 }
1744
1745 if (hz > host->f_max) {
1746 DHD_ERROR(("%s: Intended rate exceeds max rate, setting to max\n", __FUNCTION__));
1747 hz = host->f_max;
1748 }
1749 ios->clock = hz;
1750 host->ops->set_ios(host, ios);
1751 DHD_ERROR(("%s: After change: sd clock rate is %u\n", __FUNCTION__, ios->clock));
1752 mmc_host_clk_release(host);
1753 #endif
1754 }
1755
1756 void
1757 sdmmc_set_clock_divisor(sdioh_info_t *sd, uint sd_div)
1758 {
1759 uint hz;
1760 uint old_div = sdmmc_get_clock_rate(sd);
1761 if (old_div == sd_div) {
1762 return;
1763 }
1764
1765 hz = sd->sd_clk_rate / sd_div;
1766 sdmmc_set_clock_rate(sd, hz);
1767 }