blob: 0f131a40f4b8eb12a5cb7758dea622dbc5ea0e6d [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Broadcom BCMSDH to gSPI Protocol Conversion Layer
3 *
4 * Copyright (C) 2010, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
11 *
12 * $Id: bcmspibrcm.c,v 1.11.2.10.2.9.6.11 2009/05/21 13:21:57 Exp $
13 */
14
15#define HSMODE
16
17#include <typedefs.h>
18
19#include <bcmdevs.h>
20#include <bcmendian.h>
21#include <bcmutils.h>
22#include <osl.h>
23#include <hndsoc.h>
24#include <siutils.h>
25#include <sbchipc.h>
26#include <sbsdio.h>
27#include <spid.h>
28
29#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
30#include <sdiovar.h> /* ioctl/iovars */
31#include <sdio.h>
32
33#include <pcicfg.h>
34
35
36#include <bcmspibrcm.h>
37#include <bcmspi.h>
38
39#define F0_RESPONSE_DELAY 16
40#define F1_RESPONSE_DELAY 16
41#define F2_RESPONSE_DELAY F0_RESPONSE_DELAY
42
43#define CMDLEN 4
44
45#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE)
46
47/* Globals */
48uint sd_msglevel = 0;
49
50uint sd_hiok = FALSE; /* Use hi-speed mode if available? */
51uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */
52uint sd_f2_blocksize = 64; /* Default blocksize */
53
54
55uint sd_divisor = 2;
56uint sd_power = 1; /* Default to SD Slot powered ON */
57uint sd_clock = 1; /* Default to SD Clock turned ON */
58uint sd_crc = 0; /* Default to SPI CRC Check turned OFF */
59
60uint8 spi_outbuf[SPI_MAX_PKT_LEN];
61uint8 spi_inbuf[SPI_MAX_PKT_LEN];
62
63/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits
64 * assuming we will not exceed F0 response delay > 100 bytes at 48MHz.
65 */
66#define BUF2_PKT_LEN 128
67uint8 spi_outbuf2[BUF2_PKT_LEN];
68uint8 spi_inbuf2[BUF2_PKT_LEN];
69
70/* Prototypes */
71static bool bcmspi_test_card(sdioh_info_t *sd);
72static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd);
73static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode);
74static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
75 uint32 *data, uint32 datalen);
76static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr,
77 int regsize, uint32 *data);
78static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr,
79 int regsize, uint32 data);
80static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr,
81 uint8 *data);
82static int bcmspi_driver_init(sdioh_info_t *sd);
83static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
84 uint32 addr, int nbytes, uint32 *data);
85static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize,
86 uint32 *data);
87static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer);
88static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg);
89
90/*
91 * Public entry points & extern's
92 */
93extern sdioh_info_t *
94sdioh_attach(osl_t *osh, void *bar0, uint irq)
95{
96 sdioh_info_t *sd;
97
98 sd_trace(("%s\n", __FUNCTION__));
99 if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
100 sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh)));
101 return NULL;
102 }
103 bzero((char *)sd, sizeof(sdioh_info_t));
104 sd->osh = osh;
105 if (spi_osinit(sd) != 0) {
106 sd_err(("%s: spi_osinit() failed\n", __FUNCTION__));
107 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
108 return NULL;
109 }
110
111 sd->bar0 = bar0;
112 sd->irq = irq;
113 sd->intr_handler = NULL;
114 sd->intr_handler_arg = NULL;
115 sd->intr_handler_valid = FALSE;
116
117 /* Set defaults */
118 sd->use_client_ints = TRUE;
119 sd->sd_use_dma = FALSE; /* DMA Not supported */
120
121 /* Spi device default is 16bit mode, change to 4 when device is changed to 32bit
122 * mode
123 */
124 sd->wordlen = 2;
125
126 if (!spi_hw_attach(sd)) {
127 sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__));
128 spi_osfree(sd);
129 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
130 return (NULL);
131 }
132
133 if (bcmspi_driver_init(sd) != SUCCESS) {
134 sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__));
135 spi_hw_detach(sd);
136 spi_osfree(sd);
137 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
138 return (NULL);
139 }
140
141 if (spi_register_irq(sd, irq) != SUCCESS) {
142 sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
143 spi_hw_detach(sd);
144 spi_osfree(sd);
145 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
146 return (NULL);
147 }
148
149 sd_trace(("%s: Done\n", __FUNCTION__));
150
151 return sd;
152}
153
154extern SDIOH_API_RC
155sdioh_detach(osl_t *osh, sdioh_info_t *sd)
156{
157 sd_trace(("%s\n", __FUNCTION__));
158 if (sd) {
159 sd_err(("%s: detaching from hardware\n", __FUNCTION__));
160 spi_free_irq(sd->irq, sd);
161 spi_hw_detach(sd);
162 spi_osfree(sd);
163 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
164 }
165 return SDIOH_API_RC_SUCCESS;
166}
167
168/* Configure callback to client when we recieve client interrupt */
169extern SDIOH_API_RC
170sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
171{
172 sd_trace(("%s: Entering\n", __FUNCTION__));
173 sd->intr_handler = fn;
174 sd->intr_handler_arg = argh;
175 sd->intr_handler_valid = TRUE;
176 return SDIOH_API_RC_SUCCESS;
177}
178
179extern SDIOH_API_RC
180sdioh_interrupt_deregister(sdioh_info_t *sd)
181{
182 sd_trace(("%s: Entering\n", __FUNCTION__));
183 sd->intr_handler_valid = FALSE;
184 sd->intr_handler = NULL;
185 sd->intr_handler_arg = NULL;
186 return SDIOH_API_RC_SUCCESS;
187}
188
189extern SDIOH_API_RC
190sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
191{
192 sd_trace(("%s: Entering\n", __FUNCTION__));
193 *onoff = sd->client_intr_enabled;
194 return SDIOH_API_RC_SUCCESS;
195}
196
197#if defined(DHD_DEBUG)
198extern bool
199sdioh_interrupt_pending(sdioh_info_t *sd)
200{
201 return 0;
202}
203#endif
204
205extern SDIOH_API_RC
206sdioh_query_device(sdioh_info_t *sd)
207{
208 /* Return a BRCM ID appropriate to the dongle class */
209 return (sd->num_funcs > 1) ? BCM4329_D11NDUAL_ID : BCM4318_D11G_ID;
210}
211
212/* Provide dstatus bits of spi-transaction for dhd layers. */
213extern uint32
214sdioh_get_dstatus(sdioh_info_t *sd)
215{
216 return sd->card_dstatus;
217}
218
219extern void
220sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev)
221{
222 sd->chip = chip;
223 sd->chiprev = chiprev;
224}
225
226extern void
227sdioh_dwordmode(sdioh_info_t *sd, bool set)
228{
229 uint8 reg = 0;
230 int status;
231
232 if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
233 SUCCESS) {
234 sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
235 return;
236 }
237
238 if (set) {
239 reg |= DWORD_PKT_LEN_EN;
240 sd->dwordmode = TRUE;
241 sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */
242 } else {
243 reg &= ~DWORD_PKT_LEN_EN;
244 sd->dwordmode = FALSE;
245 sd->client_block_size[SPI_FUNC_2] = 2048;
246 }
247
248 if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
249 SUCCESS) {
250 sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
251 return;
252 }
253}
254
255
256uint
257sdioh_query_iofnum(sdioh_info_t *sd)
258{
259 return sd->num_funcs;
260}
261
262/* IOVar table */
263enum {
264 IOV_MSGLEVEL = 1,
265 IOV_BLOCKMODE,
266 IOV_BLOCKSIZE,
267 IOV_DMA,
268 IOV_USEINTS,
269 IOV_NUMINTS,
270 IOV_NUMLOCALINTS,
271 IOV_HOSTREG,
272 IOV_DEVREG,
273 IOV_DIVISOR,
274 IOV_SDMODE,
275 IOV_HISPEED,
276 IOV_HCIREGS,
277 IOV_POWER,
278 IOV_CLOCK,
279 IOV_SPIERRSTATS,
280 IOV_RESP_DELAY_ALL
281};
282
283const bcm_iovar_t sdioh_iovars[] = {
284 {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
285 {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
286 {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
287 {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 },
288 {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 },
289 {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 },
290 {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
291 {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
292 {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 },
293 {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 },
294 {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 },
295 {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100},
296 {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0},
297 {"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) },
298 {"spi_respdelay", IOV_RESP_DELAY_ALL, 0, IOVT_BOOL, 0 },
299 {NULL, 0, 0, 0, 0 }
300};
301
302int
303sdioh_iovar_op(sdioh_info_t *si, const char *name,
304 void *params, int plen, void *arg, int len, bool set)
305{
306 const bcm_iovar_t *vi = NULL;
307 int bcmerror = 0;
308 int val_size;
309 int32 int_val = 0;
310 bool bool_val;
311 uint32 actionid;
312/*
313 sdioh_regs_t *regs;
314*/
315
316 ASSERT(name);
317 ASSERT(len >= 0);
318
319 /* Get must have return space; Set does not take qualifiers */
320 ASSERT(set || (arg && len));
321 ASSERT(!set || (!params && !plen));
322
323 sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
324
325 if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
326 bcmerror = BCME_UNSUPPORTED;
327 goto exit;
328 }
329
330 if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
331 goto exit;
332
333 /* Set up params so get and set can share the convenience variables */
334 if (params == NULL) {
335 params = arg;
336 plen = len;
337 }
338
339 if (vi->type == IOVT_VOID)
340 val_size = 0;
341 else if (vi->type == IOVT_BUFFER)
342 val_size = len;
343 else
344 val_size = sizeof(int);
345
346 if (plen >= (int)sizeof(int_val))
347 bcopy(params, &int_val, sizeof(int_val));
348
349 bool_val = (int_val != 0) ? TRUE : FALSE;
350
351 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
352 switch (actionid) {
353 case IOV_GVAL(IOV_MSGLEVEL):
354 int_val = (int32)sd_msglevel;
355 bcopy(&int_val, arg, val_size);
356 break;
357
358 case IOV_SVAL(IOV_MSGLEVEL):
359 sd_msglevel = int_val;
360 break;
361
362 case IOV_GVAL(IOV_BLOCKSIZE):
363 if ((uint32)int_val > si->num_funcs) {
364 bcmerror = BCME_BADARG;
365 break;
366 }
367 int_val = (int32)si->client_block_size[int_val];
368 bcopy(&int_val, arg, val_size);
369 break;
370
371 case IOV_GVAL(IOV_DMA):
372 int_val = (int32)si->sd_use_dma;
373 bcopy(&int_val, arg, val_size);
374 break;
375
376 case IOV_SVAL(IOV_DMA):
377 si->sd_use_dma = (bool)int_val;
378 break;
379
380 case IOV_GVAL(IOV_USEINTS):
381 int_val = (int32)si->use_client_ints;
382 bcopy(&int_val, arg, val_size);
383 break;
384
385 case IOV_SVAL(IOV_USEINTS):
386 break;
387
388 case IOV_GVAL(IOV_DIVISOR):
389 int_val = (uint32)sd_divisor;
390 bcopy(&int_val, arg, val_size);
391 break;
392
393 case IOV_SVAL(IOV_DIVISOR):
394 sd_divisor = int_val;
395 if (!spi_start_clock(si, (uint16)sd_divisor)) {
396 sd_err(("%s: set clock failed\n", __FUNCTION__));
397 bcmerror = BCME_ERROR;
398 }
399 break;
400
401 case IOV_GVAL(IOV_POWER):
402 int_val = (uint32)sd_power;
403 bcopy(&int_val, arg, val_size);
404 break;
405
406 case IOV_SVAL(IOV_POWER):
407 sd_power = int_val;
408 break;
409
410 case IOV_GVAL(IOV_CLOCK):
411 int_val = (uint32)sd_clock;
412 bcopy(&int_val, arg, val_size);
413 break;
414
415 case IOV_SVAL(IOV_CLOCK):
416 sd_clock = int_val;
417 break;
418
419 case IOV_GVAL(IOV_SDMODE):
420 int_val = (uint32)sd_sdmode;
421 bcopy(&int_val, arg, val_size);
422 break;
423
424 case IOV_SVAL(IOV_SDMODE):
425 sd_sdmode = int_val;
426 break;
427
428 case IOV_GVAL(IOV_HISPEED):
429 int_val = (uint32)sd_hiok;
430 bcopy(&int_val, arg, val_size);
431 break;
432
433 case IOV_SVAL(IOV_HISPEED):
434 sd_hiok = int_val;
435
436 if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) {
437 sd_err(("%s: Failed changing highspeed mode to %d.\n",
438 __FUNCTION__, sd_hiok));
439 bcmerror = BCME_ERROR;
440 return ERROR;
441 }
442 break;
443
444 case IOV_GVAL(IOV_NUMINTS):
445 int_val = (int32)si->intrcount;
446 bcopy(&int_val, arg, val_size);
447 break;
448
449 case IOV_GVAL(IOV_NUMLOCALINTS):
450 int_val = (int32)si->local_intrcount;
451 bcopy(&int_val, arg, val_size);
452 break;
453 case IOV_GVAL(IOV_DEVREG):
454 {
455 sdreg_t *sd_ptr = (sdreg_t *)params;
456 uint8 data;
457
458 if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
459 bcmerror = BCME_SDIO_ERROR;
460 break;
461 }
462
463 int_val = (int)data;
464 bcopy(&int_val, arg, sizeof(int_val));
465 break;
466 }
467
468 case IOV_SVAL(IOV_DEVREG):
469 {
470 sdreg_t *sd_ptr = (sdreg_t *)params;
471 uint8 data = (uint8)sd_ptr->value;
472
473 if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
474 bcmerror = BCME_SDIO_ERROR;
475 break;
476 }
477 break;
478 }
479
480
481 case IOV_GVAL(IOV_SPIERRSTATS):
482 {
483 bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t));
484 break;
485 }
486
487 case IOV_SVAL(IOV_SPIERRSTATS):
488 {
489 bzero(&si->spierrstats, sizeof(struct spierrstats_t));
490 break;
491 }
492
493 case IOV_GVAL(IOV_RESP_DELAY_ALL):
494 int_val = (int32)si->resp_delay_all;
495 bcopy(&int_val, arg, val_size);
496 break;
497
498 case IOV_SVAL(IOV_RESP_DELAY_ALL):
499 si->resp_delay_all = (bool)int_val;
500 int_val = STATUS_ENABLE|INTR_WITH_STATUS;
501 if (si->resp_delay_all)
502 int_val |= RESP_DELAY_ALL;
503 else {
504 if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1,
505 F1_RESPONSE_DELAY) != SUCCESS) {
506 sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
507 bcmerror = BCME_SDIO_ERROR;
508 break;
509 }
510 }
511
512 if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val)
513 != SUCCESS) {
514 sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
515 bcmerror = BCME_SDIO_ERROR;
516 break;
517 }
518 break;
519
520 default:
521 bcmerror = BCME_UNSUPPORTED;
522 break;
523 }
524exit:
525
526 return bcmerror;
527}
528
529extern SDIOH_API_RC
530sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
531{
532 SDIOH_API_RC status;
533 /* No lock needed since sdioh_request_byte does locking */
534 status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
535 return status;
536}
537
538extern SDIOH_API_RC
539sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
540{
541 /* No lock needed since sdioh_request_byte does locking */
542 SDIOH_API_RC status;
543
544 if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) {
545 uint8 dummy_data;
546 status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data);
547 if (status) {
548 sd_err(("sdioh_cfg_read() failed.\n"));
549 return status;
550 }
551 }
552
553 status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
554 return status;
555}
556
557extern SDIOH_API_RC
558sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
559{
560 uint32 count;
561 int offset;
562 uint32 cis_byte;
563 uint16 *cis = (uint16 *)cisd;
564 uint bar0 = SI_ENUM_BASE;
565 int status;
566 uint8 data;
567
568 sd_trace(("%s: Func %d\n", __FUNCTION__, func));
569
570 spi_lock(sd);
571
572 /* Set sb window address to 0x18000000 */
573 data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK;
574 status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data);
575 if (status == SUCCESS) {
576 data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK;
577 status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data);
578 } else {
579 sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
580 spi_unlock(sd);
581 return (BCME_ERROR);
582 }
583 if (status == SUCCESS) {
584 data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK;
585 status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data);
586 } else {
587 sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
588 spi_unlock(sd);
589 return (BCME_ERROR);
590 }
591
592 offset = CC_OTP; /* OTP offset in chipcommon. */
593 for (count = 0; count < length/2; count++) {
594 if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) {
595 sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
596 spi_unlock(sd);
597 return (BCME_ERROR);
598 }
599
600 *cis = (uint16)cis_byte;
601 cis++;
602 offset += 2;
603 }
604
605 spi_unlock(sd);
606
607 return (BCME_OK);
608}
609
610extern SDIOH_API_RC
611sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
612{
613 int status;
614 uint32 cmd_arg;
615 uint32 dstatus;
616 uint32 data = (uint32)(*byte);
617
618 spi_lock(sd);
619
620 cmd_arg = 0;
621 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
622 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
623 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
624 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1);
625 cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
626
627 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
628 sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, rw, func,
629 regaddr, data));
630
631 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
632 cmd_arg, &data, 1)) != SUCCESS) {
633 spi_unlock(sd);
634 return status;
635 }
636
637 if (rw == SDIOH_READ)
638 *byte = (uint8)data;
639
640 bcmspi_cmd_getdstatus(sd, &dstatus);
641 if (dstatus)
642 sd_trace(("dstatus =0x%x\n", dstatus));
643
644 spi_unlock(sd);
645 return SDIOH_API_RC_SUCCESS;
646}
647
648extern SDIOH_API_RC
649sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
650 uint32 *word, uint nbytes)
651{
652 int status;
653
654 spi_lock(sd);
655
656 if (rw == SDIOH_READ)
657 status = bcmspi_card_regread(sd, func, addr, nbytes, word);
658 else
659 status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word);
660
661 spi_unlock(sd);
662 return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
663}
664
665extern SDIOH_API_RC
666sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func,
667 uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
668{
669 int len;
670 int buflen = (int)buflen_u;
671 bool fifo = (fix_inc == SDIOH_DATA_FIX);
672
673 spi_lock(sd);
674
675 ASSERT(reg_width == 4);
676 ASSERT(buflen_u < (1 << 30));
677 ASSERT(sd->client_block_size[func]);
678
679 sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n",
680 __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W',
681 buflen_u, sd->r_cnt, sd->t_cnt, pkt));
682
683 /* Break buffer down into blocksize chunks. */
684 while (buflen > 0) {
685 len = MIN(sd->client_block_size[func], buflen);
686 if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) {
687 sd_err(("%s: bcmspi_card_buf %s failed\n",
688 __FUNCTION__, rw == SDIOH_READ ? "Read" : "Write"));
689 spi_unlock(sd);
690 return SDIOH_API_RC_FAIL;
691 }
692 buffer += len;
693 buflen -= len;
694 if (!fifo)
695 addr += len;
696 }
697 spi_unlock(sd);
698 return SDIOH_API_RC_SUCCESS;
699}
700
701/* This function allows write to gspi bus when another rd/wr function is deep down the call stack.
702 * Its main aim is to have simpler spi writes rather than recursive writes.
703 * e.g. When there is a need to program response delay on the fly after detecting the SPI-func
704 * this call will allow to program the response delay.
705 */
706static int
707bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte)
708{
709 uint32 cmd_arg;
710 uint32 datalen = 1;
711 uint32 hostlen;
712
713 cmd_arg = 0;
714
715 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
716 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
717 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
718 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
719 cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen);
720
721 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
722
723
724 /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
725 * according to the wordlen mode(16/32bit) the device is in.
726 */
727 ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
728 datalen = ROUNDUP(datalen, sd->wordlen);
729
730 /* Start by copying command in the spi-outbuffer */
731 if (sd->wordlen == 4) { /* 32bit spid */
732 *(uint32 *)spi_outbuf2 = bcmswap32(cmd_arg);
733 if (datalen & 0x3)
734 datalen += (4 - (datalen & 0x3));
735 } else if (sd->wordlen == 2) { /* 16bit spid */
736 *(uint16 *)spi_outbuf2 = bcmswap16(cmd_arg & 0xffff);
737 *(uint16 *)&spi_outbuf2[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
738 if (datalen & 0x1)
739 datalen++;
740 } else {
741 sd_err(("%s: Host is %d bit spid, could not create SPI command.\n",
742 __FUNCTION__, 8 * sd->wordlen));
743 return ERROR;
744 }
745
746 /* for Write, put the data into the output buffer */
747 if (datalen != 0) {
748 if (sd->wordlen == 4) { /* 32bit spid */
749 *(uint32 *)&spi_outbuf2[CMDLEN] = bcmswap32(byte);
750 } else if (sd->wordlen == 2) { /* 16bit spid */
751 *(uint16 *)&spi_outbuf2[CMDLEN] = bcmswap16(byte & 0xffff);
752 *(uint16 *)&spi_outbuf2[CMDLEN + 2] =
753 bcmswap16((byte & 0xffff0000) >> 16);
754 }
755 }
756
757 /* +4 for cmd, +4 for dstatus */
758 hostlen = datalen + 8;
759 hostlen += (4 - (hostlen & 0x3));
760 spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen);
761
762 /* Last 4bytes are dstatus. Device is configured to return status bits. */
763 if (sd->wordlen == 4) { /* 32bit spid */
764 sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
765 } else if (sd->wordlen == 2) { /* 16bit spid */
766 sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
767 (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
768 } else {
769 sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
770 __FUNCTION__, 8 * sd->wordlen));
771 return ERROR;
772 }
773
774 if (sd->card_dstatus)
775 sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus));
776
777 return (BCME_OK);
778}
779
780/* Program the response delay corresponding to the spi function */
781static int
782bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay)
783{
784 if (sd->resp_delay_all == FALSE)
785 return (BCME_OK);
786
787 if (sd->prev_fun == func)
788 return (BCME_OK);
789
790 if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY)
791 return (BCME_OK);
792
793 bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay);
794
795 /* Remember function for which to avoid reprogramming resp-delay in next iteration */
796 sd->prev_fun = func;
797
798 return (BCME_OK);
799
800}
801
802#define GSPI_RESYNC_PATTERN 0x0
803
804/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI.
805 * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is
806 * synchronised and all queued resuests are cancelled.
807 */
808static int
809bcmspi_resync_f1(sdioh_info_t *sd)
810{
811 uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0;
812
813
814 /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
815 * according to the wordlen mode(16/32bit) the device is in.
816 */
817 ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
818 datalen = ROUNDUP(datalen, sd->wordlen);
819
820 /* Start by copying command in the spi-outbuffer */
821 *(uint32 *)spi_outbuf2 = cmd_arg;
822
823 /* for Write, put the data into the output buffer */
824 *(uint32 *)&spi_outbuf2[CMDLEN] = data;
825
826 /* +4 for cmd, +4 for dstatus */
827 spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8);
828
829 /* Last 4bytes are dstatus. Device is configured to return status bits. */
830 if (sd->wordlen == 4) { /* 32bit spid */
831 sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
832 } else if (sd->wordlen == 2) { /* 16bit spid */
833 sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
834 (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
835 } else {
836 sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
837 __FUNCTION__, 8 * sd->wordlen));
838 return ERROR;
839 }
840
841 if (sd->card_dstatus)
842 sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus));
843
844 return (BCME_OK);
845}
846
847uint32 dstatus_count = 0;
848
849static int
850bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg)
851{
852 uint32 dstatus = sd->card_dstatus;
853 struct spierrstats_t *spierrstats = &sd->spierrstats;
854 int err = SUCCESS;
855
856 sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus));
857
858 /* Store dstatus of last few gSPI transactions */
859 spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus;
860 spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg;
861 dstatus_count++;
862
863 if (sd->card_init_done == FALSE)
864 return err;
865
866 if (dstatus & STATUS_DATA_NOT_AVAILABLE) {
867 spierrstats->dna++;
868 sd_trace(("Read data not available on F1 addr = 0x%x\n",
869 GFIELD(cmd_arg, SPI_REG_ADDR)));
870 /* Clear dna bit */
871 bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE);
872 }
873
874 if (dstatus & STATUS_UNDERFLOW) {
875 spierrstats->rdunderflow++;
876 sd_err(("FIFO underflow happened due to current F2 read command.\n"));
877 }
878
879 if (dstatus & STATUS_OVERFLOW) {
880 spierrstats->wroverflow++;
881 sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n"));
882 if ((sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 0)) {
883 bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW);
884 bcmspi_resync_f1(sd);
885 sd_err(("Recovering from F1 FIFO overflow.\n"));
886 } else {
887 err = ERROR_OF;
888 }
889 }
890
891 if (dstatus & STATUS_F2_INTR) {
892 spierrstats->f2interrupt++;
893 sd_trace(("Interrupt from F2. SW should clear corresponding IntStatus bits\n"));
894 }
895
896 if (dstatus & STATUS_F3_INTR) {
897 spierrstats->f3interrupt++;
898 sd_err(("Interrupt from F3. SW should clear corresponding IntStatus bits\n"));
899 }
900
901 if (dstatus & STATUS_HOST_CMD_DATA_ERR) {
902 spierrstats->hostcmddataerr++;
903 sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n"));
904 }
905
906 if (dstatus & STATUS_F2_PKT_AVAILABLE) {
907 spierrstats->f2pktavailable++;
908 sd_trace(("Packet is available/ready in F2 TX FIFO\n"));
909 sd_trace(("Packet length = %d\n", sd->dwordmode ?
910 ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) :
911 ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT)));
912 }
913
914 if (dstatus & STATUS_F3_PKT_AVAILABLE) {
915 spierrstats->f3pktavailable++;
916 sd_err(("Packet is available/ready in F3 TX FIFO\n"));
917 sd_err(("Packet length = %d\n",
918 (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT));
919 }
920
921 return err;
922}
923
924extern int
925sdioh_abort(sdioh_info_t *sd, uint func)
926{
927 return 0;
928}
929
930int
931sdioh_start(sdioh_info_t *sd, int stage)
932{
933 return SUCCESS;
934}
935
936int
937sdioh_stop(sdioh_info_t *sd)
938{
939 return SUCCESS;
940}
941
942
943
944/*
945 * Private/Static work routines
946 */
947static int
948bcmspi_host_init(sdioh_info_t *sd)
949{
950
951 /* Default power on mode */
952 sd->sd_mode = SDIOH_MODE_SPI;
953 sd->polled_mode = TRUE;
954 sd->host_init_done = TRUE;
955 sd->card_init_done = FALSE;
956 sd->adapter_slot = 1;
957
958 return (SUCCESS);
959}
960
961static int
962get_client_blocksize(sdioh_info_t *sd)
963{
964 uint32 regdata[2];
965 int status;
966
967 /* Find F1/F2/F3 max packet size */
968 if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG,
969 8, regdata)) != SUCCESS) {
970 return status;
971 }
972
973 sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n",
974 regdata[0], regdata[1]));
975
976 sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2;
977 sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1]));
978 ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1);
979
980 sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2;
981 sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2]));
982 ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2);
983
984 sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2;
985 sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3]));
986 ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3);
987
988 return 0;
989}
990
991static int
992bcmspi_client_init(sdioh_info_t *sd)
993{
994 uint32 status_en_reg = 0;
995 sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot));
996
997#ifdef HSMODE
998 if (!spi_start_clock(sd, (uint16)sd_divisor)) {
999 sd_err(("spi_start_clock failed\n"));
1000 return ERROR;
1001 }
1002#else
1003 /* Start at ~400KHz clock rate for initialization */
1004 if (!spi_start_clock(sd, 128)) {
1005 sd_err(("spi_start_clock failed\n"));
1006 return ERROR;
1007 }
1008#endif /* HSMODE */
1009
1010 if (!bcmspi_host_device_init_adapt(sd)) {
1011 sd_err(("bcmspi_host_device_init_adapt failed\n"));
1012 return ERROR;
1013 }
1014
1015 if (!bcmspi_test_card(sd)) {
1016 sd_err(("bcmspi_test_card failed\n"));
1017 return ERROR;
1018 }
1019
1020 sd->num_funcs = SPI_MAX_IOFUNCS;
1021
1022 get_client_blocksize(sd);
1023
1024 /* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */
1025 bcmspi_resync_f1(sd);
1026
1027 sd->dwordmode = FALSE;
1028
1029 bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg);
1030
1031 sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__));
1032 status_en_reg |= INTR_WITH_STATUS;
1033
1034
1035 if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1,
1036 status_en_reg & 0xff) != SUCCESS) {
1037 sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__));
1038 return ERROR;
1039 }
1040
1041
1042#ifndef HSMODE
1043 /* After configuring for High-Speed mode, set the desired clock rate. */
1044 if (!spi_start_clock(sd, 4)) {
1045 sd_err(("spi_start_clock failed\n"));
1046 return ERROR;
1047 }
1048#endif /* HSMODE */
1049
1050 sd->card_init_done = TRUE;
1051
1052
1053 return SUCCESS;
1054}
1055
1056static int
1057bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode)
1058{
1059 uint32 regdata;
1060 int status;
1061
1062 if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG,
1063 4, &regdata)) != SUCCESS)
1064 return status;
1065
1066 sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata));
1067
1068
1069 if (hsmode == TRUE) {
1070 sd_trace(("Attempting to enable High-Speed mode.\n"));
1071
1072 if (regdata & HIGH_SPEED_MODE) {
1073 sd_trace(("Device is already in High-Speed mode.\n"));
1074 return status;
1075 } else {
1076 regdata |= HIGH_SPEED_MODE;
1077 sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
1078 if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
1079 4, regdata)) != SUCCESS) {
1080 return status;
1081 }
1082 }
1083 } else {
1084 sd_trace(("Attempting to disable High-Speed mode.\n"));
1085
1086 if (regdata & HIGH_SPEED_MODE) {
1087 regdata &= ~HIGH_SPEED_MODE;
1088 sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
1089 if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
1090 4, regdata)) != SUCCESS)
1091 return status;
1092 }
1093 else {
1094 sd_trace(("Device is already in Low-Speed mode.\n"));
1095 return status;
1096 }
1097 }
1098
1099 spi_controller_highspeed_mode(sd, hsmode);
1100
1101 return TRUE;
1102}
1103
1104#define bcmspi_find_curr_mode(sd) { \
1105 sd->wordlen = 2; \
1106 status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
1107 regdata &= 0xff; \
1108 if ((regdata == 0xad) || (regdata == 0x5b) || \
1109 (regdata == 0x5d) || (regdata == 0x5a)) \
1110 break; \
1111 sd->wordlen = 4; \
1112 status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
1113 regdata &= 0xff; \
1114 if ((regdata == 0xad) || (regdata == 0x5b) || \
1115 (regdata == 0x5d) || (regdata == 0x5a)) \
1116 break; \
1117 sd_trace(("Silicon testability issue: regdata = 0x%x." \
1118 " Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata)); \
1119 OSL_DELAY(100000); \
1120}
1121
1122#define INIT_ADAPT_LOOP 100
1123
1124/* Adapt clock-phase-speed-bitwidth between host and device */
1125static bool
1126bcmspi_host_device_init_adapt(sdioh_info_t *sd)
1127{
1128 uint32 wrregdata, regdata = 0;
1129 int status;
1130 int i;
1131
1132 /* Due to a silicon testability issue, the first command from the Host
1133 * to the device will get corrupted (first bit will be lost). So the
1134 * Host should poll the device with a safe read request. ie: The Host
1135 * should try to read F0 addr 0x14 using the Fixed address mode
1136 * (This will prevent a unintended write command to be detected by device)
1137 */
1138 for (i = 0; i < INIT_ADAPT_LOOP; i++) {
1139 /* If device was not power-cycled it will stay in 32bit mode with
1140 * response-delay-all bit set. Alternate the iteration so that
1141 * read either with or without response-delay for F0 to succeed.
1142 */
1143 bcmspi_find_curr_mode(sd);
1144 sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE;
1145
1146 bcmspi_find_curr_mode(sd);
1147 sd->dwordmode = TRUE;
1148
1149 bcmspi_find_curr_mode(sd);
1150 sd->dwordmode = FALSE;
1151 }
1152
1153 /* Bail out, device not detected */
1154 if (i == INIT_ADAPT_LOOP)
1155 return FALSE;
1156
1157 /* Softreset the spid logic */
1158 if ((sd->dwordmode) || (sd->wordlen == 4)) {
1159 bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI);
1160 bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, &regdata);
1161 sd_trace(("reset reg read = 0x%x\n", regdata));
1162 sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode,
1163 sd->wordlen, sd->resp_delay_all));
1164 /* Restore default state after softreset */
1165 sd->wordlen = 2;
1166 sd->dwordmode = FALSE;
1167 }
1168
1169 if (sd->wordlen == 4) {
1170 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) !=
1171 SUCCESS)
1172 return FALSE;
1173 if (regdata == TEST_RO_DATA_32BIT_LE) {
1174 sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n",
1175 regdata));
1176 sd_trace(("Spid power was left on.\n"));
1177 } else {
1178 sd_err(("Spid power was left on but signature read failed."
1179 " Value read = 0x%x\n", regdata));
1180 return FALSE;
1181 }
1182 } else {
1183 sd->wordlen = 2;
1184
1185#define CTRL_REG_DEFAULT 0x00010430 /* according to the host m/c */
1186
1187 wrregdata = (CTRL_REG_DEFAULT);
1188 sd->resp_delay_all = TRUE;
1189 if (sd->resp_delay_all == TRUE) {
1190 /* Enable response delay for all */
1191 wrregdata |= (RESP_DELAY_ALL << 16);
1192 /* Program response delay value */
1193 wrregdata &= 0xffff00ff;
1194 wrregdata |= (F1_RESPONSE_DELAY << 8);
1195 sd->prev_fun = SPI_FUNC_1;
1196 bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
1197 }
1198
1199 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
1200 return FALSE;
1201 sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata));
1202
1203#ifndef HSMODE
1204 wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY);
1205 wrregdata &= ~HIGH_SPEED_MODE;
1206 bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
1207#endif /* HSMODE */
1208
1209 for (i = 0; i < INIT_ADAPT_LOOP; i++) {
1210 if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) {
1211 sd_trace(("0xfeedbead was leftshifted by 1-bit.\n"));
1212 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4,
1213 &regdata)) != SUCCESS)
1214 return FALSE;
1215 }
1216 OSL_DELAY(1000);
1217 }
1218
1219
1220 /* Change to host controller intr-polarity of active-low */
1221 wrregdata &= ~INTR_POLARITY;
1222 sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n",
1223 wrregdata));
1224 /* Change to 32bit mode */
1225 wrregdata |= WORD_LENGTH_32;
1226 bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
1227
1228 /* Change command/data packaging in 32bit LE mode */
1229 sd->wordlen = 4;
1230
1231 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
1232 return FALSE;
1233
1234 if (regdata == TEST_RO_DATA_32BIT_LE) {
1235 sd_trace(("Read spid passed. Value read = 0x%x\n", regdata));
1236 sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n"));
1237 } else {
1238 sd_err(("Stale spid reg values read as it was kept powered. Value read ="
1239 "0x%x\n", regdata));
1240 return FALSE;
1241 }
1242 }
1243
1244
1245 return TRUE;
1246}
1247
1248static bool
1249bcmspi_test_card(sdioh_info_t *sd)
1250{
1251 uint32 regdata;
1252 int status;
1253
1254 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
1255 return FALSE;
1256
1257 if (regdata == (TEST_RO_DATA_32BIT_LE))
1258 sd_trace(("32bit LE regdata = 0x%x\n", regdata));
1259 else {
1260 sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata));
1261 return FALSE;
1262 }
1263
1264
1265#define RW_PATTERN1 0xA0A1A2A3
1266#define RW_PATTERN2 0x4B5B6B7B
1267
1268 regdata = RW_PATTERN1;
1269 if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
1270 return FALSE;
1271 regdata = 0;
1272 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
1273 return FALSE;
1274 if (regdata != RW_PATTERN1) {
1275 sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
1276 RW_PATTERN1, regdata));
1277 return FALSE;
1278 } else
1279 sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
1280
1281 regdata = RW_PATTERN2;
1282 if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
1283 return FALSE;
1284 regdata = 0;
1285 if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
1286 return FALSE;
1287 if (regdata != RW_PATTERN2) {
1288 sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
1289 RW_PATTERN2, regdata));
1290 return FALSE;
1291 } else
1292 sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
1293
1294 return TRUE;
1295}
1296
1297static int
1298bcmspi_driver_init(sdioh_info_t *sd)
1299{
1300 sd_trace(("%s\n", __FUNCTION__));
1301 if ((bcmspi_host_init(sd)) != SUCCESS) {
1302 return ERROR;
1303 }
1304
1305 if (bcmspi_client_init(sd) != SUCCESS) {
1306 return ERROR;
1307 }
1308
1309 return SUCCESS;
1310}
1311
1312/* Read device reg */
1313static int
1314bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
1315{
1316 int status;
1317 uint32 cmd_arg, dstatus;
1318
1319 ASSERT(regsize);
1320
1321 if (func == 2)
1322 sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
1323
1324 cmd_arg = 0;
1325 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
1326 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
1327 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
1328 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
1329 cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
1330
1331 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
1332 sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
1333 regaddr, *data));
1334
1335 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
1336 != SUCCESS)
1337 return status;
1338
1339 bcmspi_cmd_getdstatus(sd, &dstatus);
1340 if (dstatus)
1341 sd_trace(("dstatus =0x%x\n", dstatus));
1342
1343 return SUCCESS;
1344}
1345
1346static int
1347bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
1348{
1349
1350 int status;
1351 uint32 cmd_arg;
1352 uint32 dstatus;
1353
1354 ASSERT(regsize);
1355
1356 if (func == 2)
1357 sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
1358
1359 cmd_arg = 0;
1360 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
1361 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0); /* Fixed access */
1362 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
1363 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
1364 cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize);
1365
1366 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
1367
1368 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
1369 != SUCCESS)
1370 return status;
1371
1372 sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
1373 regaddr, *data));
1374
1375 bcmspi_cmd_getdstatus(sd, &dstatus);
1376 sd_trace(("dstatus =0x%x\n", dstatus));
1377 return SUCCESS;
1378}
1379
1380/* write a device register */
1381static int
1382bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
1383{
1384 int status;
1385 uint32 cmd_arg, dstatus;
1386
1387 ASSERT(regsize);
1388
1389 cmd_arg = 0;
1390
1391 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
1392 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
1393 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
1394 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
1395 cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
1396
1397 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
1398 sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 1, func,
1399 regaddr, data));
1400
1401
1402 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize))
1403 != SUCCESS)
1404 return status;
1405
1406 bcmspi_cmd_getdstatus(sd, &dstatus);
1407 if (dstatus)
1408 sd_trace(("dstatus =0x%x\n", dstatus));
1409
1410 return SUCCESS;
1411}
1412
1413/* write a device register - 1 byte */
1414static int
1415bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte)
1416{
1417 int status;
1418 uint32 cmd_arg;
1419 uint32 dstatus;
1420 uint32 data = (uint32)(*byte);
1421
1422 cmd_arg = 0;
1423 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
1424 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
1425 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
1426 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
1427 cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
1428
1429 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
1430 sd_trace(("%s: func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, func,
1431 regaddr, data));
1432
1433 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
1434 cmd_arg, &data, 1)) != SUCCESS) {
1435 return status;
1436 }
1437
1438 bcmspi_cmd_getdstatus(sd, &dstatus);
1439 if (dstatus)
1440 sd_trace(("dstatus =0x%x\n", dstatus));
1441
1442 return SUCCESS;
1443}
1444
1445void
1446bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer)
1447{
1448 *dstatus_buffer = sd->card_dstatus;
1449}
1450
1451/* 'data' is of type uint32 whereas other buffers are of type uint8 */
1452static int
1453bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
1454 uint32 *data, uint32 datalen)
1455{
1456 uint32 i, j;
1457 uint8 resp_delay = 0;
1458 int err = SUCCESS;
1459 uint32 hostlen;
1460 uint32 spilen = 0;
1461 uint32 dstatus_idx = 0;
1462 uint16 templen, buslen, len, *ptr = NULL;
1463
1464 sd_trace(("spi cmd = 0x%x\n", cmd_arg));
1465
1466 if (DWORDMODE_ON) {
1467 spilen = GFIELD(cmd_arg, SPI_LEN);
1468 if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) ||
1469 (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1))
1470 dstatus_idx = spilen * 3;
1471
1472 if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
1473 (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
1474 spilen = spilen << 2;
1475 dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0;
1476 /* convert len to mod16 size */
1477 spilen = ROUNDUP(spilen, 16);
1478 cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
1479 }
1480 }
1481
1482 /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
1483 * according to the wordlen mode(16/32bit) the device is in.
1484 */
1485 if (sd->wordlen == 4) { /* 32bit spid */
1486 *(uint32 *)spi_outbuf = bcmswap32(cmd_arg);
1487 if (datalen & 0x3)
1488 datalen += (4 - (datalen & 0x3));
1489 } else if (sd->wordlen == 2) { /* 16bit spid */
1490 *(uint16 *)spi_outbuf = bcmswap16(cmd_arg & 0xffff);
1491 *(uint16 *)&spi_outbuf[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
1492 if (datalen & 0x1)
1493 datalen++;
1494 if (datalen < 4)
1495 datalen = ROUNDUP(datalen, 4);
1496 } else {
1497 sd_err(("Host is %d bit spid, could not create SPI command.\n",
1498 8 * sd->wordlen));
1499 return ERROR;
1500 }
1501
1502 /* for Write, put the data into the output buffer */
1503 if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) {
1504 /* We send len field of hw-header always a mod16 size, both from host and dongle */
1505 if (DWORDMODE_ON) {
1506 if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) {
1507 ptr = (uint16 *)&data[0];
1508 templen = *ptr;
1509 /* ASSERT(*ptr == ~*(ptr + 1)); */
1510 templen = ROUNDUP(templen, 16);
1511 *ptr = templen;
1512 sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1))));
1513 }
1514 }
1515
1516 if (datalen != 0) {
1517 for (i = 0; i < datalen/4; i++) {
1518 if (sd->wordlen == 4) { /* 32bit spid */
1519 *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
1520 bcmswap32(data[i]);
1521 } else if (sd->wordlen == 2) { /* 16bit spid */
1522 *(uint16 *)&spi_outbuf[i * 4 + CMDLEN] =
1523 bcmswap16(data[i] & 0xffff);
1524 *(uint16 *)&spi_outbuf[i * 4 + CMDLEN + 2] =
1525 bcmswap16((data[i] & 0xffff0000) >> 16);
1526 }
1527 }
1528 }
1529 }
1530
1531 /* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */
1532 if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) {
1533 int func = GFIELD(cmd_arg, SPI_FUNCTION);
1534 switch (func) {
1535 case 0:
1536 resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0;
1537 break;
1538 case 1:
1539 resp_delay = F1_RESPONSE_DELAY;
1540 break;
1541 case 2:
1542 resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0;
1543 break;
1544 default:
1545 ASSERT(0);
1546 break;
1547 }
1548 /* Program response delay */
1549 bcmspi_prog_resp_delay(sd, func, resp_delay);
1550 }
1551
1552 /* +4 for cmd and +4 for dstatus */
1553 hostlen = datalen + 8 + resp_delay;
1554 hostlen += dstatus_idx;
1555 hostlen += (4 - (hostlen & 0x3));
1556 spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen);
1557
1558 /* for Read, get the data into the input buffer */
1559 if (datalen != 0) {
1560 if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */
1561 for (j = 0; j < datalen/4; j++) {
1562 if (sd->wordlen == 4) { /* 32bit spid */
1563 data[j] = bcmswap32(*(uint32 *)&spi_inbuf[j * 4 +
1564 CMDLEN + resp_delay]);
1565 } else if (sd->wordlen == 2) { /* 16bit spid */
1566 data[j] = (bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
1567 CMDLEN + resp_delay])) |
1568 ((bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
1569 CMDLEN + resp_delay + 2])) << 16);
1570 }
1571 }
1572
1573 if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
1574 ptr = (uint16 *)&data[0];
1575 templen = *ptr;
1576 buslen = len = ~(*(ptr + 1));
1577 buslen = ROUNDUP(buslen, 16);
1578 /* populate actual len in hw-header */
1579 if (templen == buslen)
1580 *ptr = len;
1581 }
1582 }
1583 }
1584
1585 /* Restore back the len field of the hw header */
1586 if (DWORDMODE_ON) {
1587 if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
1588 (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
1589 ptr = (uint16 *)&data[0];
1590 *ptr = (uint16)(~*(ptr+1));
1591 }
1592 }
1593
1594 dstatus_idx += (datalen + CMDLEN + resp_delay);
1595 /* Last 4bytes are dstatus. Device is configured to return status bits. */
1596 if (sd->wordlen == 4) { /* 32bit spid */
1597 sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf[dstatus_idx]);
1598 } else if (sd->wordlen == 2) { /* 16bit spid */
1599 sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx]) |
1600 (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx + 2]) << 16));
1601 } else {
1602 sd_err(("Host is %d bit machine, could not read SPI dstatus.\n",
1603 8 * sd->wordlen));
1604 return ERROR;
1605 }
1606 if (sd->card_dstatus == 0xffffffff) {
1607 sd_err(("looks like not a GSPI device or device is not powered.\n"));
1608 }
1609
1610 err = bcmspi_update_stats(sd, cmd_arg);
1611
1612 return err;
1613
1614}
1615
1616static int
1617bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
1618 uint32 addr, int nbytes, uint32 *data)
1619{
1620 int status;
1621 uint32 cmd_arg;
1622 bool write = rw == SDIOH_READ ? 0 : 1;
1623 uint retries = 0;
1624
1625 bool enable;
1626 uint32 spilen;
1627
1628 cmd_arg = 0;
1629
1630 ASSERT(nbytes);
1631 ASSERT(nbytes <= sd->client_block_size[func]);
1632
1633 if (write) sd->t_cnt++; else sd->r_cnt++;
1634
1635 if (func == 2) {
1636 /* Frame len check limited by gSPI. */
1637 if ((nbytes > 2000) && write) {
1638 sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes));
1639 }
1640 /* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */
1641 /* If F2 fifo on device is not ready to receive data, don't do F2 transfer */
1642 if (write) {
1643 uint32 dstatus;
1644 /* check F2 ready with cached one */
1645 bcmspi_cmd_getdstatus(sd, &dstatus);
1646 if ((dstatus & STATUS_F2_RX_READY) == 0) {
1647 retries = WAIT_F2RXFIFORDY;
1648 enable = 0;
1649 while (retries-- && !enable) {
1650 OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000);
1651 bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4,
1652 &dstatus);
1653 if (dstatus & STATUS_F2_RX_READY)
1654 enable = TRUE;
1655 }
1656 if (!enable) {
1657 struct spierrstats_t *spierrstats = &sd->spierrstats;
1658 spierrstats->f2rxnotready++;
1659 sd_err(("F2 FIFO is not ready to receive data.\n"));
1660 return ERROR;
1661 }
1662 sd_trace(("No of retries on F2 ready %d\n",
1663 (WAIT_F2RXFIFORDY - retries)));
1664 }
1665 }
1666 }
1667
1668 /* F2 transfers happen on 0 addr */
1669 addr = (func == 2) ? 0 : addr;
1670
1671 /* In pio mode buffer is read using fixed address fifo in func 1 */
1672 if ((func == 1) && (fifo))
1673 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);
1674 else
1675 cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);
1676
1677 cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
1678 cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr);
1679 cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write);
1680 spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes);
1681 if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
1682 /* convert len to mod4 size */
1683 spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0);
1684 cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
1685 } else
1686 cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen);
1687
1688 if ((func == 2) && (fifo == 1)) {
1689 sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
1690 __FUNCTION__, write ? "Wr" : "Rd", func, "INCR",
1691 addr, nbytes, sd->r_cnt, sd->t_cnt));
1692 }
1693
1694 sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
1695 sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
1696 __FUNCTION__, write ? "Wd" : "Rd", func, "INCR",
1697 addr, nbytes, sd->r_cnt, sd->t_cnt));
1698
1699
1700 if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg,
1701 data, nbytes)) != SUCCESS) {
1702 sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__,
1703 (write ? "write" : "read")));
1704 return status;
1705 }
1706
1707 /* gSPI expects that hw-header-len is equal to spi-command-len */
1708 if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) {
1709 ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff));
1710 ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16)));
1711 }
1712
1713 if ((nbytes > 2000) && !write) {
1714 sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes));
1715 }
1716
1717 return SUCCESS;
1718}
1719
1720/* Reset and re-initialize the device */
1721int
1722sdioh_sdio_reset(sdioh_info_t *si)
1723{
1724 si->card_init_done = FALSE;
1725 return bcmspi_client_init(si);
1726}