14d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* 24d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Broadcom BCMSDH to SPI Protocol Conversion Layer 34d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * 407770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman * Copyright (C) 1999-2010, Broadcom Corporation 54d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * 64d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Unless you and Broadcom execute a separate written software license 74d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * agreement governing use of this software, this software is licensed to you 84d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * under the terms of the GNU General Public License version 2 (the "GPL"), 94d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * available at http://www.broadcom.com/licenses/GPLv2.php, with the 104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * following added to such license: 114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * 124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * As a special exception, the copyright holders of this software give you 134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * permission to link this software with independent modules, and to copy and 144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * distribute the resulting executable under terms of your choice, provided that 154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * you also meet, for each linked independent module, the terms and conditions of 164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * the license of that module. An independent module is a module which is not 174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * derived from this software. The special exception does not apply to any 184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * modifications of the software. 194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * 204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Notwithstanding the above, under no circumstances may you combine this 214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * software in any way with any other Broadcom software provided under a license 224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * other than the GPL, without Broadcom's express prior written consent. 234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * 2407770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman * $Id: bcmsdspi.c,v 1.14.4.2.4.4.6.5 2010/03/10 03:09:48 Exp $ 254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <typedefs.h> 284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmdevs.h> 304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmendian.h> 314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmutils.h> 324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <osl.h> 334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <siutils.h> 344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <sdio.h> /* SDIO Device and Protocol Specs */ 354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <sdioh.h> /* SDIO Host Controller Specification */ 364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */ 374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <sdiovar.h> /* ioctl/iovars */ 384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <pcicfg.h> 404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmsdspi.h> 434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmspi.h> 444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <proto/sdspi.h> 464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define SD_PAGE 4096 484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Globals */ 504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_msglevel = SDH_ERROR_VAL; 524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_hiok = FALSE; /* Use hi-speed mode if available? */ 534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */ 544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_f2_blocksize = 512; /* Default blocksize */ 554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_divisor = 2; /* Default 33MHz/2 = 16MHz for dongle */ 574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_power = 1; /* Default to SD Slot powered ON */ 584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_clock = 1; /* Default to SD Clock turned ON */ 594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_crc = 0; /* Default to SPI CRC Check turned OFF */ 6007770aa679cd45674eaac3d8fb2e01a995068838Greg Goldmanuint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */ 614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint sd_toctl = 7; 634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Prototypes */ 654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic bool sdspi_start_power(sdioh_info_t *sd); 664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_set_highspeed_mode(sdioh_info_t *sd, bool HSMode); 674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_card_enablefuncs(sdioh_info_t *sd); 684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic void sdspi_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count); 694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg, 704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 *data, uint32 datalen); 714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, 724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int regsize, uint32 *data); 734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, 744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int regsize, uint32 data); 754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_driver_init(sdioh_info_t *sd); 764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic bool sdspi_reset(sdioh_info_t *sd, bool host_reset, bool client_reset); 774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, 784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 addr, int nbytes, uint32 *data); 794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_abort(sdioh_info_t *sd, uint func); 804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int set_client_block_size(sdioh_info_t *sd, int func, int blocksize); 824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic uint8 sdspi_crc7(unsigned char* p, uint32 len); 844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic uint16 sdspi_crc16(unsigned char* p, uint32 len); 854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int sdspi_crc_onoff(sdioh_info_t *sd, bool use_crc); 864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* 884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Public entry points & extern's 894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern sdioh_info_t * 914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_attach(osl_t *osh, void *bar0, uint irq) 924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdioh_info_t *sd; 944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s\n", __FUNCTION__)); 964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { 974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); 984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return NULL; 994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bzero((char *)sd, sizeof(sdioh_info_t)); 1014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->osh = osh; 1024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (spi_osinit(sd) != 0) { 1044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: spi_osinit() failed\n", __FUNCTION__)); 1054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt MFREE(sd->osh, sd, sizeof(sdioh_info_t)); 1064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return NULL; 1074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->bar0 = (uintptr)bar0; 1104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->irq = irq; 1114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler = NULL; 1124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_arg = NULL; 1134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_valid = FALSE; 1144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Set defaults */ 1164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->sd_blockmode = FALSE; 1174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->use_client_ints = TRUE; 1184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->sd_use_dma = FALSE; /* DMA Not supported */ 1194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Haven't figured out how to make bytemode work with dma */ 1214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!sd->sd_blockmode) 1224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->sd_use_dma = 0; 1234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!spi_hw_attach(sd)) { 1254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__)); 1264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_osfree(sd); 1274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt MFREE(sd->osh, sd, sizeof(sdioh_info_t)); 1284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return NULL; 1294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_driver_init(sd) != SUCCESS) { 1324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_driver_init(sd) != SUCCESS) { 1334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s:sdspi_driver_init() failed()\n", __FUNCTION__)); 1344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_hw_detach(sd); 1354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_osfree(sd); 1364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt MFREE(sd->osh, sd, sizeof(sdioh_info_t)); 1374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (NULL); 1384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (spi_register_irq(sd, irq) != SUCCESS) { 1424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq)); 1434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_hw_detach(sd); 1444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_osfree(sd); 1454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt MFREE(sd->osh, sd, sizeof(sdioh_info_t)); 1464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (NULL); 1474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Done\n", __FUNCTION__)); 1504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return sd; 1514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 1524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 1544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_detach(osl_t *osh, sdioh_info_t *sd) 1554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 1564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s\n", __FUNCTION__)); 1574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd) { 1594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd->card_init_done) 1604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_reset(sd, 1, 1); 1614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: detaching from hardware\n", __FUNCTION__)); 1634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_free_irq(sd->irq, sd); 1644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_hw_detach(sd); 1654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_osfree(sd); 1664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt MFREE(sd->osh, sd, sizeof(sdioh_info_t)); 1674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 1684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 1704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 1714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Configure callback to client when we recieve client interrupt */ 1734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 1744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) 1754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 1764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Entering\n", __FUNCTION__)); 1774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler = fn; 1794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_arg = argh; 1804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_valid = TRUE; 1814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 1834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 1844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 1864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_interrupt_deregister(sdioh_info_t *sd) 1874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 1884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Entering\n", __FUNCTION__)); 1894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_valid = FALSE; 1914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler = NULL; 1924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->intr_handler_arg = NULL; 1934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 1954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 1964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 1984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) 1994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 2004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Entering\n", __FUNCTION__)); 2014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *onoff = sd->client_intr_enabled; 2034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 2054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 2064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(DHD_DEBUG) 2084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern bool 2094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_interrupt_pending(sdioh_info_t *sd) 2104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 2114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return 0; 2124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 2134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif 2144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint 2164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_query_iofnum(sdioh_info_t *sd) 2174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 2184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return sd->num_funcs; 2194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 2204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* IOVar table */ 2224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtenum { 2234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_MSGLEVEL = 1, 2244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_BLOCKMODE, 2254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_BLOCKSIZE, 2264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_DMA, 2274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_USEINTS, 2284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_NUMINTS, 2294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_NUMLOCALINTS, 2304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_HOSTREG, 2314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_DEVREG, 2324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_DIVISOR, 2334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_SDMODE, 2344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_HISPEED, 2354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_HCIREGS, 2364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_POWER, 2374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_CLOCK, 2384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt IOV_CRC 2394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}; 2404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtconst bcm_iovar_t sdioh_iovars[] = { 2424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, 2434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 }, 2444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ 2454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, 2464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, 2474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, 2484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, 2494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, 2504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, 2514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, 2524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, 2534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, 2544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_crc", IOV_CRC, 0, IOVT_UINT32, 0 }, 2554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, 2564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}, 2574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt {NULL, 0, 0, 0, 0 } 2584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}; 2594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint 2614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_iovar_op(sdioh_info_t *si, const char *name, 2624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt void *params, int plen, void *arg, int len, bool set) 2634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 2644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt const bcm_iovar_t *vi = NULL; 2654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int bcmerror = 0; 2664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int val_size; 2674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int32 int_val = 0; 2684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool bool_val; 2694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 actionid; 2704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(name); 2724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(len >= 0); 2734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Get must have return space; Set does not take qualifiers */ 2754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(set || (arg && len)); 2764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(!set || (!params && !plen)); 2774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name)); 2794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { 2814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_UNSUPPORTED; 2824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt goto exit; 2834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 2844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) 2864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt goto exit; 2874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Set up params so get and set can share the convenience variables */ 2894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (params == NULL) { 2904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt params = arg; 2914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt plen = len; 2924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 2934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 2944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (vi->type == IOVT_VOID) 2954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt val_size = 0; 2964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else if (vi->type == IOVT_BUFFER) 2974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt val_size = len; 2984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else 2994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt val_size = sizeof(int); 3004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (plen >= (int)sizeof(int_val)) 3024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(params, &int_val, sizeof(int_val)); 3034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool_val = (int_val != 0) ? TRUE : FALSE; 3054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); 3074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt switch (actionid) { 3084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_MSGLEVEL): 3094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)sd_msglevel; 3104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_MSGLEVEL): 3144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_msglevel = int_val; 3154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_BLOCKMODE): 3184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->sd_blockmode; 3194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_BLOCKMODE): 3234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt si->sd_blockmode = (bool)int_val; 3244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Haven't figured out how to make non-block mode with DMA */ 3254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!si->sd_blockmode) 3264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt si->sd_use_dma = 0; 3274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_BLOCKSIZE): 3304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((uint32)int_val > si->num_funcs) { 3314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_BADARG; 3324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->client_block_size[int_val]; 3354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_BLOCKSIZE): 3394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt { 3404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint func = ((uint32)int_val >> 16); 3414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint blksize = (uint16)int_val; 3424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint maxsize; 3434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (func > si->num_funcs) { 3454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_BADARG; 3464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt switch (func) { 3504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case 0: maxsize = 32; break; 3514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case 1: maxsize = BLOCK_SIZE_4318; break; 3524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case 2: maxsize = BLOCK_SIZE_4328; break; 3534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt default: maxsize = 0; 3544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (blksize > maxsize) { 3564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_BADARG; 3574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!blksize) { 3604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt blksize = maxsize; 3614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Now set it */ 3644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(si); 3654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = set_client_block_size(si, func, blksize); 3664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(si); 3674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_DMA): 3714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->sd_use_dma; 3724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_DMA): 3764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt si->sd_use_dma = (bool)int_val; 3774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_USEINTS): 3804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->use_client_ints; 3814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_USEINTS): 3854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_DIVISOR): 3884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_divisor; 3894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 3904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 3924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_DIVISOR): 3934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_divisor = int_val; 3944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!spi_start_clock(si, (uint16)sd_divisor)) { 3954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("set clock failed!\n")); 3964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_ERROR; 3974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 3984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 3994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_POWER): 4014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_power; 4024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_POWER): 4064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_power = int_val; 4074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_CLOCK): 4104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_clock; 4114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_CLOCK): 4154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_clock = int_val; 4164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_CRC): 4194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_crc; 4204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_CRC): 4244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Apply new setting, but don't change sd_crc until 4254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * after the CRC-mode is selected in the device. This 4264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * is required because the software must generate a 4274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * correct CRC for the CMD59 in order to be able to 4284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * turn OFF the CRC. 4294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 4304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_crc_onoff(si, int_val ? 1 : 0); 4314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_crc = int_val; 4324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_SDMODE): 4354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_sdmode; 4364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_SDMODE): 4404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_sdmode = int_val; 4414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_HISPEED): 4444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (uint32)sd_hiok; 4454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_HISPEED): 4494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_hiok = int_val; 4504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!sdspi_set_highspeed_mode(si, (bool)sd_hiok)) { 4524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Failed changing highspeed mode to %d.\n", sd_hiok)); 4534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_ERROR; 4544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 4554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 4564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_NUMINTS): 4594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->intrcount; 4604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_NUMLOCALINTS): 4644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int32)si->local_intrcount; 4654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, val_size); 4664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_HOSTREG): 4694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt { 4704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 4724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_HOSTREG): 4744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt { 4754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("IOV_HOSTREG unsupported\n")); 4764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 4784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_GVAL(IOV_DEVREG): 4804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt { 4814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdreg_t *sd_ptr = (sdreg_t *)params; 4824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 data; 4834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { 4854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_SDIO_ERROR; 4864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 4884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int_val = (int)data; 4904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcopy(&int_val, arg, sizeof(int_val)); 4914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 4924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 4934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case IOV_SVAL(IOV_DEVREG): 4954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt { 4964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdreg_t *sd_ptr = (sdreg_t *)params; 4974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 data = (uint8)sd_ptr->value; 4984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 4994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { 5004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_SDIO_ERROR; 5014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 5024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 5044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt default: 5084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bcmerror = BCME_UNSUPPORTED; 5094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 5104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtexit: 5124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return bcmerror; 5144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 5154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 5174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) 5184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 5194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_API_RC status; 5204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* No lock needed since sdioh_request_byte does locking */ 5214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); 5224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 5234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 5244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 5264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) 5274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 5284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* No lock needed since sdioh_request_byte does locking */ 5294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_API_RC status; 5304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); 5314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 5324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 5334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 5354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) 5364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 5374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 count; 5384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int offset; 5394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 foo; 5404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 *cis = cisd; 5414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Func = %d\n", __FUNCTION__, func)); 5434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!sd->func_cis_ptr[func]) { 5454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bzero(cis, length); 5464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_FAIL; 5474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 5504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *cis = 0; 5514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (count = 0; count < length; count++) { 5524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt offset = sd->func_cis_ptr[func] + count; 5534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_card_regread (sd, 0, offset, 1, &foo) < 0) { 5544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__)); 5554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 5564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_FAIL; 5574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *cis = (uint8)(foo & 0xff); 5594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cis++; 5604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 5624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 5634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 5644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 5664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) 5674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 5684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 5694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg; 5704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 rsp5; 5714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 5734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = 0; 5754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); 5764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); 5774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, rw == SDIOH_READ ? 0 : 1); 5784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); 5794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_DATA, rw == SDIOH_READ ? 0 : *byte); 5804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x\n", __FUNCTION__, rw, func, regaddr)); 5824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, 5844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_CMD_52, cmd_arg, NULL, 0)) != SUCCESS) { 5854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 5864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 5874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 5904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rsp5 != 0x00) { 5914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5 flags is 0x%x func=%d\n", 5924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rsp5, func)); 5934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* ASSERT(0); */ 5944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 5954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_FAIL; 5964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 5974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 5984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rw == SDIOH_READ) 5994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *byte = sd->card_rsp_data >> 24; 6004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 6024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 6034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 6044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 6064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, 6074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 *word, uint nbytes) 6084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 6094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 6104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 6124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rw == SDIOH_READ) 6144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt status = sdspi_card_regread(sd, func, addr, nbytes, word); 6154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else 6164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt status = sdspi_card_regwrite(sd, func, addr, nbytes, *word); 6174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 6194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); 6204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 6214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern SDIOH_API_RC 6234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func, 6244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) 6254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 6264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int len; 6274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int buflen = (int)buflen_u; 6284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool fifo = (fix_inc == SDIOH_DATA_FIX); 6294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 6314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(reg_width == 4); 6334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(buflen_u < (1 << 30)); 6344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(sd->client_block_size[func]); 6354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n", 6374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W', 6384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt buflen_u, sd->r_cnt, sd->t_cnt, pkt)); 6394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Break buffer down into blocksize chunks: 6414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Bytemode: 1 block at a time. 6424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 6434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt while (buflen > 0) { 6444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd->sd_blockmode) { 6454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Max xfer is Page size */ 6464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt len = MIN(SD_PAGE, buflen); 6474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Round down to a block boundry */ 6494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (buflen > sd->client_block_size[func]) 6504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt len = (len/sd->client_block_size[func]) * 6514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->client_block_size[func]; 6524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 6534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Byte mode: One block at a time */ 6544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt len = MIN(sd->client_block_size[func], buflen); 6554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 6564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) { 6584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 6594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_FAIL; 6604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 6614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt buffer += len; 6624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt buflen -= len; 6634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!fifo) 6644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt addr += len; 6654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 6664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 6674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SDIOH_API_RC_SUCCESS; 6684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 6694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 6714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_abort(sdioh_info_t *sd, uint func) 6724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 6734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 spi_databuf[] = { 0x74, 0x80, 0x00, 0x0C, 0xFF, 0x95, 0xFF, 0xFF, 6744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 6754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 spi_rspbuf[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 6764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 6774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int err = 0; 6784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Sending SPI Abort to F%d\n", func)); 6804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[4] = func & 0x7; 6814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* write to function 0, addr 6 (IOABORT) func # in 3 LSBs. */ 6824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_sendrecv(sd, spi_databuf, spi_rspbuf, sizeof(spi_databuf)); 6834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return err; 6854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 6864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern int 6884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_abort(sdioh_info_t *sd, uint fnum) 6894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 6904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int ret; 6914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 6934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ret = sdspi_abort(sd, fnum); 6944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 6954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ret; 6974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 6984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 6994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint 7004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_start(sdioh_info_t *sd, int stage) 7014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 7024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 7034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 7044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint 7064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_stop(sdioh_info_t *sd) 7074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 7084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 7094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 7104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* 7134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Private/Static work routines 7144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 7154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic bool 7164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_reset(sdioh_info_t *sd, bool host_reset, bool client_reset) 7174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 7184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!sd) 7194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return TRUE; 7204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_lock(sd); 7224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Reset client card */ 7234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (client_reset && (sd->adapter_slot != -1)) { 7244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_card_regwrite(sd, 0, SDIOD_CCCR_IOABORT, 1, 0x8) != SUCCESS) 7254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Cannot write to card reg 0x%x\n", 7264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, SDIOD_CCCR_IOABORT)); 7274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else 7284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rca = 0; 7294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* The host reset is a NOP in the sd-spi case. */ 7324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (host_reset) { 7334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->sd_mode = SDIOH_MODE_SPI; 7344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_unlock(sd); 7364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return TRUE; 7374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 7384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 7404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_host_init(sdioh_info_t *sd) 7414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 7424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_reset(sd, 1, 0); 7434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Default power on mode is SD1 */ 7454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->sd_mode = SDIOH_MODE_SPI; 7464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->polled_mode = TRUE; 7474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->host_init_done = TRUE; 7484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_init_done = FALSE; 7494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->adapter_slot = 1; 7504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (SUCCESS); 7524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 7534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CMD0_RETRIES 3 7554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CMD5_RETRIES 10 7564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 7584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtget_ocr(sdioh_info_t *sd, uint32 *cmd_arg, uint32 *cmd_rsp) 7594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 7604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 rsp5; 7614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int retries, status; 7624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* First issue a CMD0 to get the card into SPI mode. */ 7644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (retries = 0; retries <= CMD0_RETRIES; retries++) { 7654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, 7664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_CMD_0, *cmd_arg, NULL, 0)) != SUCCESS) { 7674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: No response to CMD0\n", __FUNCTION__)); 7684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt continue; 7694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 7724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(rsp5, SPI_RSP_ILL_CMD)) { 7744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("%s: Card already initialized (continuing)\n", __FUNCTION__); 7754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 7764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(rsp5, SPI_RSP_IDLE)) { 7794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("%s: Card in SPI mode\n", __FUNCTION__); 7804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 7814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (retries > CMD0_RETRIES) { 7854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Too many retries for CMD0\n", __FUNCTION__)); 7864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 7874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Get the Card's Operation Condition. */ 7904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Occasionally the board takes a while to become ready. */ 7914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (retries = 0; retries <= CMD5_RETRIES; retries++) { 7924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, 7934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_CMD_5, *cmd_arg, NULL, 0)) != SUCCESS) { 7944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: No response to CMD5\n", __FUNCTION__)); 7954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt continue; 7964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 7974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 7984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("CMD5 response data was: 0x%08x\n", sd->card_rsp_data); 7994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(sd->card_rsp_data, RSP4_CARD_READY)) { 8014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("%s: Card ready\n", __FUNCTION__); 8024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 8034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (retries > CMD5_RETRIES) { 8074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Too many retries for CMD5\n", __FUNCTION__)); 8084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *cmd_rsp = sd->card_rsp_data; 8124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_crc_onoff(sd, sd_crc ? 1 : 0); 8144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (SUCCESS); 8164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 8174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 8194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_crc_onoff(sdioh_info_t *sd, bool use_crc) 8204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 8214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 args; 8224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 8234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt args = use_crc ? 1 : 0; 8254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, 8264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_CMD_59, args, NULL, 0)) != SUCCESS) { 8274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: No response to CMD59\n", __FUNCTION__)); 8284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("CMD59 response data was: 0x%08x\n", sd->card_rsp_data)); 8314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("SD-SPI CRC turned %s\n", use_crc ? "ON" : "OFF")); 8334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (SUCCESS); 8344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 8354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 8374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_client_init(sdioh_info_t *sd) 8384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 8394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 fn_ints; 8404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot)); 8424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Start at ~400KHz clock rate for initialization */ 8444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!spi_start_clock(sd, 128)) { 8454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("spi_start_clock failed\n")); 8464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!sdspi_start_power(sd)) { 8504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("sdspi_start_power failed\n")); 8514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd->num_funcs == 0) { 8554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: No IO funcs!\n", __FUNCTION__)); 8564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_card_enablefuncs(sd); 8604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt set_client_block_size(sd, 1, BLOCK_SIZE_4318); 8624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt fn_ints = INTR_CTL_FUNC1_EN; 8634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd->num_funcs >= 2) { 8654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt set_client_block_size(sd, 2, sd_f2_blocksize /* BLOCK_SIZE_4328 */); 8664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt fn_ints |= INTR_CTL_FUNC2_EN; 8674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Enable/Disable Client interrupts */ 8704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Turn on here but disable at host controller */ 8714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_card_regwrite(sd, 0, SDIOD_CCCR_INTEN, 1, 8724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt (fn_ints | INTR_CTL_MASTER_EN)) != SUCCESS) { 8734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Could not enable ints in CCCR\n", __FUNCTION__)); 8744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Switch to High-speed clocking mode if both host and device support it */ 8784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_set_highspeed_mode(sd, (bool)sd_hiok); 8794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* After configuring for High-Speed mode, set the desired clock rate. */ 8814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!spi_start_clock(sd, (uint16)sd_divisor)) { 8824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("spi_start_clock failed\n")); 8834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 8844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 8854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_init_done = TRUE; 8874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 8894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 8904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 8924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_set_highspeed_mode(sdioh_info_t *sd, bool HSMode) 8934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 8944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 regdata; 8954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 8964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool hsmode; 8974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 8984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (HSMode == TRUE) { 8994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Attempting to enable High-Speed mode.\n")); 9014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, 9034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1, ®data)) != SUCCESS) { 9044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 9054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (regdata & SDIO_SPEED_SHS) { 9074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Device supports High-Speed mode.\n")); 9084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt regdata |= SDIO_SPEED_EHS; 9104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Writing %08x to Card at %08x\n", 9124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt regdata, SDIOD_CCCR_SPEED_CONTROL)); 9134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, 9144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1, regdata)) != BCME_OK) { 9154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 9164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt hsmode = 1; 9194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("High-speed clocking mode enabled.\n")); 9214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else { 9234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Device does not support High-Speed Mode.\n")); 9244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt hsmode = 0; 9254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 9274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, 9284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1, ®data)) != SUCCESS) { 9294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 9304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt regdata = ~SDIO_SPEED_EHS; 9334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Writing %08x to Card at %08x\n", 9354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt regdata, SDIOD_CCCR_SPEED_CONTROL)); 9364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, 9374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 1, regdata)) != BCME_OK) { 9384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 9394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("Low-speed clocking mode enabled.\n")); 9424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt hsmode = 0; 9434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_controller_highspeed_mode(sd, hsmode); 9464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return TRUE; 9484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 9494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbool 9514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_start_power(sdioh_info_t *sd) 9524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 9534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg; 9544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_rsp; 9554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s\n", __FUNCTION__)); 9574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Get the Card's Operation Condition. Occasionally the board 9594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * takes a while to become ready 9604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 9614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = 0; 9634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (get_ocr(sd, &cmd_arg, &cmd_rsp) != SUCCESS) { 9644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Failed to get OCR; bailing\n", __FUNCTION__)); 9654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return FALSE; 9664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("mem_present = %d\n", GFIELD(cmd_rsp, RSP4_MEM_PRESENT))); 9694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("num_funcs = %d\n", GFIELD(cmd_rsp, RSP4_NUM_FUNCS))); 9704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("card_ready = %d\n", GFIELD(cmd_rsp, RSP4_CARD_READY))); 9714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("OCR = 0x%x\n", GFIELD(cmd_rsp, RSP4_IO_OCR))); 9724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Verify that the card supports I/O mode */ 9744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(cmd_rsp, RSP4_NUM_FUNCS) == 0) { 9754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Card does not support I/O\n", __FUNCTION__)); 9764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 9774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->num_funcs = GFIELD(cmd_rsp, RSP4_NUM_FUNCS); 9804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Examine voltage: Arasan only supports 3.3 volts, 9824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * so look for 3.2-3.3 Volts and also 3.3-3.4 volts. 9834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 9844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((GFIELD(cmd_rsp, RSP4_IO_OCR) & (0x3 << 20)) == 0) { 9864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("This client does not support 3.3 volts!\n")); 9874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 9884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 9894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return TRUE; 9924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 9934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 9954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_driver_init(sdioh_info_t *sd) 9964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 9974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s\n", __FUNCTION__)); 9984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 9994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((sdspi_host_init(sd)) != SUCCESS) { 10004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 10014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 10024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sdspi_client_init(sd) != SUCCESS) { 10044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 10054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 10064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 10084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 10094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 10114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_card_enablefuncs(sdioh_info_t *sd) 10124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 10134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 10144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 regdata; 10154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 regaddr, fbraddr; 10164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 func; 10174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 *ptr; 10184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s\n", __FUNCTION__)); 10204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Get the Card's common CIS address */ 10214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ptr = (uint8 *) &sd->com_cis_ptr; 10224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (regaddr = SDIOD_CCCR_CISPTR_0; regaddr <= SDIOD_CCCR_CISPTR_2; regaddr++) { 10234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regread (sd, 0, regaddr, 1, ®data)) != SUCCESS) 10244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 10254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *ptr++ = (uint8) regdata; 10274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 10284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Only the lower 17-bits are valid */ 10304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->com_cis_ptr &= 0x0001FFFF; 10314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->func_cis_ptr[0] = sd->com_cis_ptr; 10324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); 10334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Get the Card's function CIS (for each function) */ 10354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (fbraddr = SDIOD_FBR_STARTADDR, func = 1; 10364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { 10374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ptr = (uint8 *) &sd->func_cis_ptr[func]; 10384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (regaddr = SDIOD_FBR_CISPTR_0; regaddr <= SDIOD_FBR_CISPTR_2; regaddr++) { 10394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regread (sd, 0, regaddr + fbraddr, 1, ®data)) 10404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt != SUCCESS) 10414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 10424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *ptr++ = (uint8) regdata; 10444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 10454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Only the lower 17-bits are valid */ 10474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->func_cis_ptr[func] &= 0x0001FFFF; 10484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: Function %d CIS Ptr = 0x%x\n", 10494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, func, sd->func_cis_ptr[func])); 10504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 10514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: write ESCI bit\n", __FUNCTION__)); 10534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Enable continuous SPI interrupt (ESCI bit) */ 10544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_card_regwrite(sd, 0, SDIOD_CCCR_BICTRL, 1, 0x60); 10554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: enable f1\n", __FUNCTION__)); 10574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Enable function 1 on the card */ 10584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt regdata = SDIO_FUNC_ENABLE_1; 10594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_IOEN, 1, regdata)) != SUCCESS) 10604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 10614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: done\n", __FUNCTION__)); 10634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 10644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 10654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Read client card reg */ 10674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 10684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) 10694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 10704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 10714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg; 10724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 rsp5; 10734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = 0; 10754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((func == 0) || (regsize == 1)) { 10774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); 10784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); 10794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_READ); 10804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); 10814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_DATA, 0); 10824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg, NULL, 0)) 10844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt != SUCCESS) 10854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 10864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 10884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rsp5 != 0x00) 10904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5 flags is 0x%x\t %d\n", 10914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rsp5, func)); 10924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 10934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *data = sd->card_rsp_data >> 24; 10944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 10954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); 10964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); 10974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); 10984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); 10994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); 11004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); 11014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->data_xfer_count = regsize; 11034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* sdspi_cmd_issue() returns with the command complete bit 11054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * in the ISR already cleared 11064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 11074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg, NULL, 0)) 11084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt != SUCCESS) 11094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 11104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 11124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rsp5 != 0x00) 11144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5 flags is 0x%x\t %d\n", 11154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rsp5, func)); 11164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *data = sd->card_rsp_data; 11184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (regsize == 2) { 11194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *data &= 0xffff; 11204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 11214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: CMD53 func %d, addr 0x%x, size %d, data 0x%08x\n", 11234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, func, regaddr, regsize, *data)); 11244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 11274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 11294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 11304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* write a client register */ 11324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 11334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) 11344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 11354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 11364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg, rsp5, flags; 11374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = 0; 11394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((func == 0) || (regsize == 1)) { 11414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); 11424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); 11434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_WRITE); 11444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); 11454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD52_DATA, data & 0xff); 11464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg, NULL, 0)) 11474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt != SUCCESS) 11484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 11494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 11514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt flags = GFIELD(rsp5, RSP5_FLAGS); 11524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (flags && (flags != 0x10)) 11534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5.rsp5.flags = 0x%x, expecting 0x10\n", 11544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, flags)); 11554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 11564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else { 11574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); 11584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); 11594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); 11604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); 11614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); 11624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); 11634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->data_xfer_count = regsize; 11654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->cmd53_wr_data = data; 11664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("%s: CMD53 func %d, addr 0x%x, size %d, data 0x%08x\n", 11684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, func, regaddr, regsize, data)); 11694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* sdspi_cmd_issue() returns with the command complete bit 11714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * in the ISR already cleared 11724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 11734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg, NULL, 0)) 11744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt != SUCCESS) 11754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 11764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 11784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rsp5 != 0x00) 11804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5 flags = 0x%x, expecting 0x00\n", 11814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rsp5)); 11824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 11844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 11854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 11864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtvoid 11884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count /* num 32 bit words */) 11894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 11904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *rsp_buffer = sd->card_response; 11914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 11924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint max_errors = 0; 11944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define SPI_MAX_PKT_LEN 768 11964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint8 spi_databuf[SPI_MAX_PKT_LEN]; 11974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtuint8 spi_rspbuf[SPI_MAX_PKT_LEN]; 11984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 11994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* datalen is used for CMD53 length only (0 for sd->data_xfer_count) */ 12004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 12014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg, 12024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 *data, uint32 datalen) 12034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 12044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_reg; 12054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg = arg; 12064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 cmd_crc = 0x95; /* correct CRC for CMD0 and don't care for others. */ 12074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint16 dat_crc; 12084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 cmd52data = 0; 12094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 i, j; 12104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 spi_datalen = 0; 12114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 spi_pre_cmd_pad = 0; 12124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 spi_max_response_pad = 128; 12134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = 0; 12154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_DIR, 1); 12164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_CMD_INDEX, cmd); 12174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(cmd_arg, CMD52_RW_FLAG) == 1) { /* Same for CMD52 and CMD53 */ 12194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_RW, 1); 12204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 12214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt switch (cmd) { 12234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_59: /* CRC_ON_OFF (SPI Mode Only) - Response R1 */ 12244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd52data = arg & 0x1; 12254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_0: /* Set Card to Idle State - No Response */ 12264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_5: /* Send Operation condition - Response R4 */ 12274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: CMD%d\n", __FUNCTION__, cmd)); 12284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_datalen = 44; 12294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_pre_cmd_pad = 12; 12304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_max_response_pad = 28; 12314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 12324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_3: /* Ask card to send RCA - Response R6 */ 12344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_7: /* Select card - Response R1 */ 12354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_15: /* Set card to inactive state - Response None */ 12364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: CMD%d is invalid for SPI Mode.\n", __FUNCTION__, cmd)); 12374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 12384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 12394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_52: /* IO R/W Direct (single byte) - Response R5 */ 12414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd52data = GFIELD(cmd_arg, CMD52_DATA); 12424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = arg; 12434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_FUNC, GFIELD(cmd_arg, CMD52_FUNCTION)); 12444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_ADDR, GFIELD(cmd_arg, CMD52_REG_ADDR)); 12454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Display trace for byte write */ 12464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(cmd_arg, CMD52_RW_FLAG) == 1) { 12474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: CMD52: Wr F:%d @0x%04x=%02x\n", 12484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, 12494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD52_FUNCTION), 12504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD52_REG_ADDR), 12514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd52data)); 12524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 12534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_datalen = 32; 12554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_max_response_pad = 28; 12564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 12584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt case SDIOH_CMD_53: /* IO R/W Extended (multiple bytes/blocks) */ 12594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = arg; 12604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_FUNC, GFIELD(cmd_arg, CMD53_FUNCTION)); 12614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_ADDR, GFIELD(cmd_arg, CMD53_REG_ADDR)); 12624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_BLKMODE, 0); 12634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_OPCODE, GFIELD(cmd_arg, CMD53_OP_CODE)); 12644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg = SFIELD(cmd_reg, SPI_STUFF0, (sd->data_xfer_count>>8)); 12654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd52data = (uint8)sd->data_xfer_count; 12664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Set upper bit in byte count if necessary, but don't set it for 512 bytes. */ 12684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((sd->data_xfer_count > 255) && (sd->data_xfer_count < 512)) { 12694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_reg |= 1; 12704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 12714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (GFIELD(cmd_reg, SPI_RW) == 1) { /* Write */ 12734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_max_response_pad = 32; 12744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_datalen = (sd->data_xfer_count + spi_max_response_pad) & 0xFFFC; 12754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { /* Read */ 12764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_max_response_pad = 32; 12784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_datalen = (sd->data_xfer_count + spi_max_response_pad) & 0xFFFC; 12794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 12804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: CMD53: %s F:%d @0x%04x len=0x%02x\n", 12814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, 12824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt (GFIELD(cmd_reg, SPI_RW) == 1 ? "Wr" : "Rd"), 12834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD53_FUNCTION), 12844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD53_REG_ADDR), 12854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd52data)); 12864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 12874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt default: 12894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Unknown command %d\n", __FUNCTION__, cmd)); 12904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 12914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 12924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 12934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Set up and issue the SDIO command */ 12944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt memset(spi_databuf, SDSPI_IDLE_PAD, spi_datalen); 12954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 0] = (cmd_reg & 0xFF000000) >> 24; 12964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 1] = (cmd_reg & 0x00FF0000) >> 16; 12974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 2] = (cmd_reg & 0x0000FF00) >> 8; 12984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 3] = (cmd_reg & 0x000000FF); 12994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 4] = cmd52data; 13004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Generate CRC7 for command, if CRC is enabled, otherwise, a 13024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * default CRC7 of 0x95, which is correct for CMD0, is used. 13034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 13044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd_crc) { 13054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_crc = sdspi_crc7(&spi_databuf[spi_pre_cmd_pad], 5); 13064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 5] = cmd_crc; 13084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define SPI_STOP_TRAN 0xFD 13094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* for CMD53 Write, put the data into the output buffer */ 13114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((cmd == SDIOH_CMD_53) && (GFIELD(cmd_arg, CMD53_RW_FLAG) == 1)) { 13124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (datalen != 0) { 13134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; 13144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; 13154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (i = 0; i < sd->data_xfer_count; i++) { 13174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[i + 11 + spi_pre_cmd_pad] = ((uint8 *)data)[i]; 13184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd_crc) { 13204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], i); 13214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 13224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = 0xAAAA; 13234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[i + 11 + spi_pre_cmd_pad] = (dat_crc >> 8) & 0xFF; 13254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[i + 12 + spi_pre_cmd_pad] = dat_crc & 0xFF; 13264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else if (sd->data_xfer_count == 2) { 13274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; 13284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; 13294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 11] = sd->cmd53_wr_data & 0xFF; 13304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 12] = (sd->cmd53_wr_data & 0x0000FF00) >> 8; 13314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd_crc) { 13324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], 2); 13334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 13344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = 0x22AA; 13354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 13] = (dat_crc >> 8) & 0xFF; 13374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 14] = (dat_crc & 0xFF); 13384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else if (sd->data_xfer_count == 4) { 13394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; 13404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; 13414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 11] = sd->cmd53_wr_data & 0xFF; 13424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 12] = (sd->cmd53_wr_data & 0x0000FF00) >> 8; 13434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 13] = (sd->cmd53_wr_data & 0x00FF0000) >> 16; 13444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 14] = (sd->cmd53_wr_data & 0xFF000000) >> 24; 13454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd_crc) { 13464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], 4); 13474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 13484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = 0x44AA; 13494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 15] = (dat_crc >> 8) & 0xFF; 13514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_databuf[spi_pre_cmd_pad + 16] = (dat_crc & 0xFF); 13524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 13534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("CMD53 Write: size %d unsupported\n", sd->data_xfer_count); 13544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt spi_sendrecv(sd, spi_databuf, spi_rspbuf, spi_datalen); 13584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (i = spi_pre_cmd_pad + SDSPI_COMMAND_LEN; i < spi_max_response_pad; i++) { 13604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((spi_rspbuf[i] & SDSPI_START_BIT_MASK) == 0) { 13614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 13624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (i == spi_max_response_pad) { 13664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Did not get a response for CMD%d\n", __FUNCTION__, cmd)); 13674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 13684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Extract the response. */ 13714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_response = spi_rspbuf[i]; 13724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* for CMD53 Read, find the start of the response data... */ 13744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((cmd == SDIOH_CMD_53) && (GFIELD(cmd_arg, CMD52_RW_FLAG) == 0)) { 13754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (; i < spi_max_response_pad; i++) { 13764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (spi_rspbuf[i] == SDSPI_START_BLOCK) { 13774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt break; 13784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (i == spi_max_response_pad) { 13824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt printf("Did not get a start of data phase for CMD%d\n", cmd); 13834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt max_errors++; 13844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_abort(sd, GFIELD(cmd_arg, CMD53_FUNCTION)); 13854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data = spi_rspbuf[i+1]; 13874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+2] << 8; 13884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+3] << 16; 13894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+4] << 24; 13904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (datalen != 0) { 13924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt i++; 13934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (j = 0; j < sd->data_xfer_count; j++) { 13944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ((uint8 *)data)[j] = spi_rspbuf[i+j]; 13954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 13964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (sd_crc) { 13974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint16 recv_crc; 13984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 13994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt recv_crc = spi_rspbuf[i+j] << 8 | spi_rspbuf[i+j+1]; 14004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt dat_crc = sdspi_crc16((uint8 *)data, datalen); 14014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (dat_crc != recv_crc) { 14024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Incorrect data CRC: expected 0x%04x, " 14034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt "received 0x%04x\n", 14044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, dat_crc, recv_crc)); 14054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 14094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data = spi_rspbuf[i+4]; 14124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+3] << 8; 14134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+2] << 16; 14144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data |= spi_rspbuf[i+1] << 24; 14154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Display trace for byte read */ 14174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((cmd == SDIOH_CMD_52) && (GFIELD(cmd_arg, CMD52_RW_FLAG) == 0)) { 14184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_trace(("%s: CMD52: Rd F:%d @0x%04x=%02x\n", 14194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, 14204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD53_FUNCTION), 14214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt GFIELD(cmd_arg, CMD53_REG_ADDR), 14224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->card_rsp_data >> 24)); 14234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 14264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 14274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* 14294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * On entry: if single-block or non-block, buffer size <= block size. 14304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * If multi-block, buffer size is unlimited. 14314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Question is how to handle the left-overs in either single- or multi-block. 14324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * I think the caller should break the buffer up so this routine will always 14334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * use block size == buffer size to handle the end piece of the buffer 14344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 14354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 14374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int nbytes, uint32 *data) 14384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 14394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int status; 14404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 cmd_arg; 14414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 rsp5; 14424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int num_blocks, blocksize; 14434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool local_blockmode, local_dma; 14444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bool read = rw == SDIOH_READ ? 1 : 0; 14454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt ASSERT(nbytes); 14474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = 0; 14494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_data(("%s: %s 53 func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", 14504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, read ? "Rd" : "Wr", func, fifo ? "FIXED" : "INCR", 14514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt addr, nbytes, sd->r_cnt, sd->t_cnt)); 14524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (read) sd->r_cnt++; else sd->t_cnt++; 14544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt local_blockmode = sd->sd_blockmode; 14564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt local_dma = sd->sd_use_dma; 14574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Don't bother with block mode on small xfers */ 14594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (nbytes < sd->client_block_size[func]) { 14604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_info(("setting local blockmode to false: nbytes (%d) != block_size (%d)\n", 14614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt nbytes, sd->client_block_size[func])); 14624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt local_blockmode = FALSE; 14634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt local_dma = FALSE; 14644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (local_blockmode) { 14674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt blocksize = MIN(sd->client_block_size[func], nbytes); 14684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt num_blocks = nbytes/blocksize; 14694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, num_blocks); 14704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 1); 14714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } else { 14724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt num_blocks = 1; 14734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt blocksize = nbytes; 14744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, nbytes); 14754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); 14764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (fifo) 14794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 0); 14804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else 14814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); 14824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); 14844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, addr); 14854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (read) 14864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); 14874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt else 14884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); 14894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->data_xfer_count = nbytes; 14914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((func == 2) && (fifo == 1)) { 14924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_data(("%s: %s 53 func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", 14934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, read ? "Rd" : "Wr", func, fifo ? "FIXED" : "INCR", 14944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt addr, nbytes, sd->r_cnt, sd->t_cnt)); 14954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 14964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 14974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* sdspi_cmd_issue() returns with the command complete bit 14984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * in the ISR already cleared 14994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 15004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if ((status = sdspi_cmd_issue(sd, local_dma, 15014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt SDIOH_CMD_53, cmd_arg, 15024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt data, nbytes)) != SUCCESS) { 15034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__, (read ? "read" : "write"))); 15044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return status; 15054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sdspi_cmd_getrsp(sd, &rsp5, 1); 15084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (rsp5 != 0x00) { 15104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: rsp5 flags = 0x%x, expecting 0x00\n", 15114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt __FUNCTION__, rsp5)); 15124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return ERROR; 15134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return SUCCESS; 15164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 15174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int 15194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtset_client_block_size(sdioh_info_t *sd, int func, int block_size) 15204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 15214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int base; 15224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt int err = 0; 15234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd_err(("%s: Setting block size %d, func %d\n", __FUNCTION__, block_size, func)); 15254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt sd->client_block_size[func] = block_size; 15264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Set the block size in the SDIO Card register */ 15284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt base = func * SDIOD_FBR_SIZE; 15294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt err = sdspi_card_regwrite(sd, 0, base + SDIOD_CCCR_BLKSIZE_0, 1, block_size & 0xff); 15304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (!err) { 15314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt err = sdspi_card_regwrite(sd, 0, base + SDIOD_CCCR_BLKSIZE_1, 1, 15324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt (block_size >> 8) & 0xff); 15334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* 15364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Do not set the block size in the SDIO Host register; that 15374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * is func dependent and will get done on an individual 15384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * transaction basis. 15394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */ 15404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (err ? BCME_SDIO_ERROR : 0); 15424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 15434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Reset and re-initialize the device */ 15454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint 15464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtsdioh_sdio_reset(sdioh_info_t *si) 15474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 15484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt si->card_init_done = FALSE; 15494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return sdspi_client_init(si); 15504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 15514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CRC7_POLYNOM 0x09 15534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CRC7_CRCHIGHBIT 0x40 15544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic uint8 sdspi_crc7(unsigned char* p, uint32 len) 15564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 15574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint8 c, j, bit, crc = 0; 15584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 i; 15594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (i = 0; i < len; i++) { 15614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt c = *p++; 15624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (j = 0x80; j; j >>= 1) { 15634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bit = crc & CRC7_CRCHIGHBIT; 15644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt crc <<= 1; 15654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (c & j) bit ^= CRC7_CRCHIGHBIT; 15664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (bit) crc ^= CRC7_POLYNOM; 15674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt /* Convert the CRC7 to an 8-bit SD CRC */ 15714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt crc = (crc << 1) | 1; 15724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (crc); 15744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 15754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CRC16_POLYNOM 0x1021 15774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define CRC16_CRCHIGHBIT 0x8000 15784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic uint16 sdspi_crc16(unsigned char* p, uint32 len) 15804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{ 15814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint32 i; 15824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint16 j, c, bit; 15834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt uint16 crc = 0; 15844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (i = 0; i < len; i++) { 15864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt c = *p++; 15874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt for (j = 0x80; j; j >>= 1) { 15884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt bit = crc & CRC16_CRCHIGHBIT; 15894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt crc <<= 1; 15904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (c & j) bit ^= CRC16_CRCHIGHBIT; 15914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt if (bit) crc ^= CRC16_POLYNOM; 15924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt } 15944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt 15954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt return (crc); 15964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt} 1597