bcmsdh_sdmmc.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. /*
  2. * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
  3. *
  4. * Copyright (C) 1999-2015, Broadcom Corporation
  5. *
  6. * Unless you and Broadcom execute a separate written software license
  7. * agreement governing use of this software, this software is licensed to you
  8. * under the terms of the GNU General Public License version 2 (the "GPL"),
  9. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  10. * following added to such license:
  11. *
  12. * As a special exception, the copyright holders of this software give you
  13. * permission to link this software with independent modules, and to copy and
  14. * distribute the resulting executable under terms of your choice, provided that
  15. * you also meet, for each linked independent module, the terms and conditions of
  16. * the license of that module. An independent module is a module which is not
  17. * derived from this software. The special exception does not apply to any
  18. * modifications of the software.
  19. *
  20. * Notwithstanding the above, under no circumstances may you combine this
  21. * software in any way with any other Broadcom software provided under a license
  22. * other than the GPL, without Broadcom's express prior written consent.
  23. *
  24. * $Id: bcmsdh_sdmmc.c 591220 2015-10-07 08:12:29Z $
  25. */
  26. #include <typedefs.h>
  27. #include <bcmdevs.h>
  28. #include <bcmendian.h>
  29. #include <bcmutils.h>
  30. #include <osl.h>
  31. #include <sdio.h> /* SDIO Device and Protocol Specs */
  32. #include <sdioh.h> /* Standard SDIO Host Controller Specification */
  33. #include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
  34. #include <sdiovar.h> /* ioctl/iovars */
  35. #include <linux/mmc/core.h>
  36. #include <linux/mmc/host.h>
  37. #include <linux/mmc/card.h>
  38. #include <linux/mmc/sdio_func.h>
  39. #include <linux/mmc/sdio_ids.h>
  40. #include <dngl_stats.h>
  41. #include <dhd.h>
  42. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
  43. #include <linux/suspend.h>
  44. extern volatile bool dhd_mmc_suspend;
  45. #endif
  46. #include "bcmsdh_sdmmc.h"
  47. #ifndef BCMSDH_MODULE
  48. extern int sdio_function_init(void);
  49. extern void sdio_function_cleanup(void);
  50. #endif /* BCMSDH_MODULE */
  51. #if !defined(OOB_INTR_ONLY)
  52. static void IRQHandler(struct sdio_func *func);
  53. static void IRQHandlerF2(struct sdio_func *func);
  54. #endif /* !defined(OOB_INTR_ONLY) */
  55. static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
  56. extern int sdio_reset_comm(struct mmc_card *card);
  57. #define DEFAULT_SDIO_F2_BLKSIZE 512
  58. #ifndef CUSTOM_SDIO_F2_BLKSIZE
  59. #define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE
  60. #endif
  61. #define MAX_IO_RW_EXTENDED_BLK 511
  62. uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
  63. uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
  64. uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
  65. uint sd_power = 1; /* Default to SD Slot powered ON */
  66. uint sd_clock = 1; /* Default to SD Clock turned ON */
  67. uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */
  68. uint sd_msglevel = 0x01;
  69. uint sd_use_dma = TRUE;
  70. #ifndef CUSTOM_RXCHAIN
  71. #define CUSTOM_RXCHAIN 0
  72. #endif
  73. DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
  74. DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
  75. DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
  76. DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
  77. #define DMA_ALIGN_MASK 0x03
  78. #define MMC_SDIO_ABORT_RETRY_LIMIT 5
  79. int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
  80. static int
  81. sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
  82. {
  83. int err_ret;
  84. uint32 fbraddr;
  85. uint8 func;
  86. sd_trace(("%s\n", __FUNCTION__));
  87. /* Get the Card's common CIS address */
  88. sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
  89. sd->func_cis_ptr[0] = sd->com_cis_ptr;
  90. sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
  91. /* Get the Card's function CIS (for each function) */
  92. for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
  93. func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
  94. sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
  95. sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
  96. __FUNCTION__, func, sd->func_cis_ptr[func]));
  97. }
  98. sd->func_cis_ptr[0] = sd->com_cis_ptr;
  99. sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
  100. /* Enable Function 1 */
  101. sdio_claim_host(sd->func[1]);
  102. err_ret = sdio_enable_func(sd->func[1]);
  103. sdio_release_host(sd->func[1]);
  104. if (err_ret) {
  105. sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
  106. }
  107. return FALSE;
  108. }
  109. /*
  110. * Public entry points & extern's
  111. */
  112. extern sdioh_info_t *
  113. sdioh_attach(osl_t *osh, struct sdio_func *func)
  114. {
  115. sdioh_info_t *sd = NULL;
  116. int err_ret;
  117. sd_trace(("%s\n", __FUNCTION__));
  118. if (func == NULL) {
  119. sd_err(("%s: sdio function device is NULL\n", __FUNCTION__));
  120. return NULL;
  121. }
  122. if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
  123. sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
  124. return NULL;
  125. }
  126. bzero((char *)sd, sizeof(sdioh_info_t));
  127. sd->osh = osh;
  128. sd->fake_func0.num = 0;
  129. sd->fake_func0.card = func->card;
  130. sd->func[0] = &sd->fake_func0;
  131. sd->func[1] = func->card->sdio_func[0];
  132. sd->func[2] = func->card->sdio_func[1];
  133. sd->num_funcs = 2;
  134. sd->sd_blockmode = TRUE;
  135. sd->use_client_ints = TRUE;
  136. sd->client_block_size[0] = 64;
  137. sd->use_rxchain = CUSTOM_RXCHAIN;
  138. if (sd->func[1] == NULL || sd->func[2] == NULL) {
  139. sd_err(("%s: func 1 or 2 is null \n", __FUNCTION__));
  140. goto fail;
  141. }
  142. sdio_set_drvdata(sd->func[1], sd);
  143. sdio_claim_host(sd->func[1]);
  144. sd->client_block_size[1] = 64;
  145. err_ret = sdio_set_block_size(sd->func[1], 64);
  146. sdio_release_host(sd->func[1]);
  147. if (err_ret) {
  148. sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize(%d)\n", err_ret));
  149. goto fail;
  150. }
  151. sdio_claim_host(sd->func[2]);
  152. sd->client_block_size[2] = sd_f2_blocksize;
  153. err_ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
  154. sdio_release_host(sd->func[2]);
  155. if (err_ret) {
  156. sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d(%d)\n",
  157. sd_f2_blocksize, err_ret));
  158. goto fail;
  159. }
  160. sdioh_sdmmc_card_enablefuncs(sd);
  161. sd_trace(("%s: Done\n", __FUNCTION__));
  162. return sd;
  163. fail:
  164. MFREE(sd->osh, sd, sizeof(sdioh_info_t));
  165. return NULL;
  166. }
  167. extern SDIOH_API_RC
  168. sdioh_detach(osl_t *osh, sdioh_info_t *sd)
  169. {
  170. sd_trace(("%s\n", __FUNCTION__));
  171. if (sd) {
  172. /* Disable Function 2 */
  173. if (sd->func[2]) {
  174. sdio_claim_host(sd->func[2]);
  175. sdio_disable_func(sd->func[2]);
  176. sdio_release_host(sd->func[2]);
  177. }
  178. /* Disable Function 1 */
  179. if (sd->func[1]) {
  180. sdio_claim_host(sd->func[1]);
  181. sdio_disable_func(sd->func[1]);
  182. sdio_release_host(sd->func[1]);
  183. }
  184. sd->func[1] = NULL;
  185. sd->func[2] = NULL;
  186. MFREE(sd->osh, sd, sizeof(sdioh_info_t));
  187. }
  188. return SDIOH_API_RC_SUCCESS;
  189. }
  190. #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
  191. extern SDIOH_API_RC
  192. sdioh_enable_func_intr(sdioh_info_t *sd)
  193. {
  194. uint8 reg;
  195. int err;
  196. if (sd->func[0] == NULL) {
  197. sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
  198. return SDIOH_API_RC_FAIL;
  199. }
  200. sdio_claim_host(sd->func[0]);
  201. reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
  202. if (err) {
  203. sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
  204. sdio_release_host(sd->func[0]);
  205. return SDIOH_API_RC_FAIL;
  206. }
  207. /* Enable F1 and F2 interrupts, clear master enable */
  208. reg &= ~INTR_CTL_MASTER_EN;
  209. reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
  210. sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
  211. sdio_release_host(sd->func[0]);
  212. if (err) {
  213. sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
  214. return SDIOH_API_RC_FAIL;
  215. }
  216. return SDIOH_API_RC_SUCCESS;
  217. }
  218. extern SDIOH_API_RC
  219. sdioh_disable_func_intr(sdioh_info_t *sd)
  220. {
  221. uint8 reg;
  222. int err;
  223. if (sd->func[0] == NULL) {
  224. sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__));
  225. return SDIOH_API_RC_FAIL;
  226. }
  227. sdio_claim_host(sd->func[0]);
  228. reg = sdio_readb(sd->func[0], SDIOD_CCCR_INTEN, &err);
  229. if (err) {
  230. sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
  231. sdio_release_host(sd->func[0]);
  232. return SDIOH_API_RC_FAIL;
  233. }
  234. reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
  235. /* Disable master interrupt with the last function interrupt */
  236. if (!(reg & 0xFE))
  237. reg = 0;
  238. sdio_writeb(sd->func[0], reg, SDIOD_CCCR_INTEN, &err);
  239. sdio_release_host(sd->func[0]);
  240. if (err) {
  241. sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
  242. return SDIOH_API_RC_FAIL;
  243. }
  244. return SDIOH_API_RC_SUCCESS;
  245. }
  246. #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
  247. /* Configure callback to client when we recieve client interrupt */
  248. extern SDIOH_API_RC
  249. sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
  250. {
  251. sd_trace(("%s: Entering\n", __FUNCTION__));
  252. if (fn == NULL) {
  253. sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
  254. return SDIOH_API_RC_FAIL;
  255. }
  256. #if !defined(OOB_INTR_ONLY)
  257. sd->intr_handler = fn;
  258. sd->intr_handler_arg = argh;
  259. sd->intr_handler_valid = TRUE;
  260. /* register and unmask irq */
  261. if (sd->func[2]) {
  262. sdio_claim_host(sd->func[2]);
  263. sdio_claim_irq(sd->func[2], IRQHandlerF2);
  264. sdio_release_host(sd->func[2]);
  265. }
  266. if (sd->func[1]) {
  267. sdio_claim_host(sd->func[1]);
  268. sdio_claim_irq(sd->func[1], IRQHandler);
  269. sdio_release_host(sd->func[1]);
  270. }
  271. #elif defined(HW_OOB)
  272. sdioh_enable_func_intr(sd);
  273. #endif /* !defined(OOB_INTR_ONLY) */
  274. return SDIOH_API_RC_SUCCESS;
  275. }
  276. extern SDIOH_API_RC
  277. sdioh_interrupt_deregister(sdioh_info_t *sd)
  278. {
  279. sd_trace(("%s: Entering\n", __FUNCTION__));
  280. #if !defined(OOB_INTR_ONLY)
  281. if (sd->func[1]) {
  282. /* register and unmask irq */
  283. sdio_claim_host(sd->func[1]);
  284. sdio_release_irq(sd->func[1]);
  285. sdio_release_host(sd->func[1]);
  286. }
  287. if (sd->func[2]) {
  288. /* Claim host controller F2 */
  289. sdio_claim_host(sd->func[2]);
  290. sdio_release_irq(sd->func[2]);
  291. /* Release host controller F2 */
  292. sdio_release_host(sd->func[2]);
  293. }
  294. sd->intr_handler_valid = FALSE;
  295. sd->intr_handler = NULL;
  296. sd->intr_handler_arg = NULL;
  297. #elif defined(HW_OOB)
  298. sdioh_disable_func_intr(sd);
  299. #endif /* !defined(OOB_INTR_ONLY) */
  300. return SDIOH_API_RC_SUCCESS;
  301. }
  302. extern SDIOH_API_RC
  303. sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
  304. {
  305. sd_trace(("%s: Entering\n", __FUNCTION__));
  306. *onoff = sd->client_intr_enabled;
  307. return SDIOH_API_RC_SUCCESS;
  308. }
  309. #if defined(DHD_DEBUG)
  310. extern bool
  311. sdioh_interrupt_pending(sdioh_info_t *sd)
  312. {
  313. return (0);
  314. }
  315. #endif
  316. uint
  317. sdioh_query_iofnum(sdioh_info_t *sd)
  318. {
  319. return sd->num_funcs;
  320. }
  321. /* IOVar table */
  322. enum {
  323. IOV_MSGLEVEL = 1,
  324. IOV_BLOCKMODE,
  325. IOV_BLOCKSIZE,
  326. IOV_DMA,
  327. IOV_USEINTS,
  328. IOV_NUMINTS,
  329. IOV_NUMLOCALINTS,
  330. IOV_HOSTREG,
  331. IOV_DEVREG,
  332. IOV_DIVISOR,
  333. IOV_SDMODE,
  334. IOV_HISPEED,
  335. IOV_HCIREGS,
  336. IOV_POWER,
  337. IOV_CLOCK,
  338. IOV_RXCHAIN
  339. };
  340. const bcm_iovar_t sdioh_iovars[] = {
  341. {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
  342. {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 },
  343. {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
  344. {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
  345. {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 },
  346. {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 },
  347. {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 },
  348. {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 },
  349. {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 },
  350. {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 },
  351. {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100},
  352. {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0 },
  353. {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0 },
  354. {NULL, 0, 0, 0, 0 }
  355. };
  356. int
  357. sdioh_iovar_op(sdioh_info_t *si, const char *name,
  358. void *params, int plen, void *arg, int len, bool set)
  359. {
  360. const bcm_iovar_t *vi = NULL;
  361. int bcmerror = 0;
  362. int val_size;
  363. int32 int_val = 0;
  364. bool bool_val;
  365. uint32 actionid;
  366. ASSERT(name);
  367. ASSERT(len >= 0);
  368. /* Get must have return space; Set does not take qualifiers */
  369. ASSERT(set || (arg && len));
  370. ASSERT(!set || (!params && !plen));
  371. sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
  372. if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
  373. bcmerror = BCME_UNSUPPORTED;
  374. goto exit;
  375. }
  376. if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
  377. goto exit;
  378. /* Set up params so get and set can share the convenience variables */
  379. if (params == NULL) {
  380. params = arg;
  381. plen = len;
  382. }
  383. if (vi->type == IOVT_VOID)
  384. val_size = 0;
  385. else if (vi->type == IOVT_BUFFER)
  386. val_size = len;
  387. else
  388. val_size = sizeof(int);
  389. if (plen >= (int)sizeof(int_val))
  390. bcopy(params, &int_val, sizeof(int_val));
  391. bool_val = (int_val != 0) ? TRUE : FALSE;
  392. BCM_REFERENCE(bool_val);
  393. actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
  394. switch (actionid) {
  395. case IOV_GVAL(IOV_MSGLEVEL):
  396. int_val = (int32)sd_msglevel;
  397. bcopy(&int_val, arg, val_size);
  398. break;
  399. case IOV_SVAL(IOV_MSGLEVEL):
  400. sd_msglevel = int_val;
  401. break;
  402. case IOV_GVAL(IOV_BLOCKMODE):
  403. int_val = (int32)si->sd_blockmode;
  404. bcopy(&int_val, arg, val_size);
  405. break;
  406. case IOV_SVAL(IOV_BLOCKMODE):
  407. si->sd_blockmode = (bool)int_val;
  408. /* Haven't figured out how to make non-block mode with DMA */
  409. break;
  410. case IOV_GVAL(IOV_BLOCKSIZE):
  411. if ((uint32)int_val > si->num_funcs) {
  412. bcmerror = BCME_BADARG;
  413. break;
  414. }
  415. int_val = (int32)si->client_block_size[int_val];
  416. bcopy(&int_val, arg, val_size);
  417. break;
  418. case IOV_SVAL(IOV_BLOCKSIZE):
  419. {
  420. uint func = ((uint32)int_val >> 16);
  421. uint blksize = (uint16)int_val;
  422. uint maxsize;
  423. if (func > si->num_funcs) {
  424. bcmerror = BCME_BADARG;
  425. break;
  426. }
  427. switch (func) {
  428. case 0: maxsize = 32; break;
  429. case 1: maxsize = BLOCK_SIZE_4318; break;
  430. case 2: maxsize = BLOCK_SIZE_4328; break;
  431. default: maxsize = 0;
  432. }
  433. if (blksize > maxsize) {
  434. bcmerror = BCME_BADARG;
  435. break;
  436. }
  437. if (!blksize) {
  438. blksize = maxsize;
  439. }
  440. /* Now set it */
  441. si->client_block_size[func] = blksize;
  442. #if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE)
  443. if (si->func[func] == NULL) {
  444. sd_err(("%s: SDIO Device not present\n", __FUNCTION__));
  445. bcmerror = BCME_NORESOURCE;
  446. break;
  447. }
  448. sdio_claim_host(si->func[func]);
  449. bcmerror = sdio_set_block_size(si->func[func], blksize);
  450. if (bcmerror)
  451. sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n",
  452. __FUNCTION__, func, blksize, bcmerror));
  453. sdio_release_host(si->func[func]);
  454. #endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */
  455. break;
  456. }
  457. case IOV_GVAL(IOV_RXCHAIN):
  458. int_val = (int32)si->use_rxchain;
  459. bcopy(&int_val, arg, val_size);
  460. break;
  461. case IOV_GVAL(IOV_DMA):
  462. int_val = (int32)si->sd_use_dma;
  463. bcopy(&int_val, arg, val_size);
  464. break;
  465. case IOV_SVAL(IOV_DMA):
  466. si->sd_use_dma = (bool)int_val;
  467. break;
  468. case IOV_GVAL(IOV_USEINTS):
  469. int_val = (int32)si->use_client_ints;
  470. bcopy(&int_val, arg, val_size);
  471. break;
  472. case IOV_SVAL(IOV_USEINTS):
  473. si->use_client_ints = (bool)int_val;
  474. if (si->use_client_ints)
  475. si->intmask |= CLIENT_INTR;
  476. else
  477. si->intmask &= ~CLIENT_INTR;
  478. break;
  479. case IOV_GVAL(IOV_DIVISOR):
  480. int_val = (uint32)sd_divisor;
  481. bcopy(&int_val, arg, val_size);
  482. break;
  483. case IOV_SVAL(IOV_DIVISOR):
  484. sd_divisor = int_val;
  485. break;
  486. case IOV_GVAL(IOV_POWER):
  487. int_val = (uint32)sd_power;
  488. bcopy(&int_val, arg, val_size);
  489. break;
  490. case IOV_SVAL(IOV_POWER):
  491. sd_power = int_val;
  492. break;
  493. case IOV_GVAL(IOV_CLOCK):
  494. int_val = (uint32)sd_clock;
  495. bcopy(&int_val, arg, val_size);
  496. break;
  497. case IOV_SVAL(IOV_CLOCK):
  498. sd_clock = int_val;
  499. break;
  500. case IOV_GVAL(IOV_SDMODE):
  501. int_val = (uint32)sd_sdmode;
  502. bcopy(&int_val, arg, val_size);
  503. break;
  504. case IOV_SVAL(IOV_SDMODE):
  505. sd_sdmode = int_val;
  506. break;
  507. case IOV_GVAL(IOV_HISPEED):
  508. int_val = (uint32)sd_hiok;
  509. bcopy(&int_val, arg, val_size);
  510. break;
  511. case IOV_SVAL(IOV_HISPEED):
  512. sd_hiok = int_val;
  513. break;
  514. case IOV_GVAL(IOV_NUMINTS):
  515. int_val = (int32)si->intrcount;
  516. bcopy(&int_val, arg, val_size);
  517. break;
  518. case IOV_GVAL(IOV_NUMLOCALINTS):
  519. int_val = (int32)0;
  520. bcopy(&int_val, arg, val_size);
  521. break;
  522. default:
  523. bcmerror = BCME_UNSUPPORTED;
  524. break;
  525. }
  526. exit:
  527. return bcmerror;
  528. }
  529. #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
  530. SDIOH_API_RC
  531. sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
  532. {
  533. SDIOH_API_RC status;
  534. uint8 data;
  535. if (enable)
  536. data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI;
  537. else
  538. data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */
  539. status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data);
  540. return status;
  541. }
  542. #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
  543. extern SDIOH_API_RC
  544. sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
  545. {
  546. SDIOH_API_RC status;
  547. /* No lock needed since sdioh_request_byte does locking */
  548. status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
  549. return status;
  550. }
  551. extern SDIOH_API_RC
  552. sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
  553. {
  554. /* No lock needed since sdioh_request_byte does locking */
  555. SDIOH_API_RC status;
  556. status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
  557. return status;
  558. }
  559. static int
  560. sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr)
  561. {
  562. /* read 24 bits and return valid 17 bit addr */
  563. int i;
  564. uint32 scratch, regdata;
  565. uint8 *ptr = (uint8 *)&scratch;
  566. for (i = 0; i < 3; i++) {
  567. if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, &regdata)) != SUCCESS)
  568. sd_err(("%s: Can't read!\n", __FUNCTION__));
  569. *ptr++ = (uint8) regdata;
  570. regaddr++;
  571. }
  572. /* Only the lower 17-bits are valid */
  573. scratch = ltoh32(scratch);
  574. scratch &= 0x0001FFFF;
  575. return (scratch);
  576. }
  577. extern SDIOH_API_RC
  578. sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
  579. {
  580. uint32 count;
  581. int offset;
  582. uint32 foo;
  583. uint8 *cis = cisd;
  584. sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
  585. if (!sd->func_cis_ptr[func]) {
  586. bzero(cis, length);
  587. sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
  588. return SDIOH_API_RC_FAIL;
  589. }
  590. sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
  591. for (count = 0; count < length; count++) {
  592. offset = sd->func_cis_ptr[func] + count;
  593. if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) {
  594. sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
  595. return SDIOH_API_RC_FAIL;
  596. }
  597. *cis = (uint8)(foo & 0xff);
  598. cis++;
  599. }
  600. return SDIOH_API_RC_SUCCESS;
  601. }
  602. extern SDIOH_API_RC
  603. sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
  604. {
  605. int err_ret = 0;
  606. #if defined(MMC_SDIO_ABORT)
  607. int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
  608. #endif
  609. sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
  610. DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
  611. DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
  612. if(rw) { /* CMD52 Write */
  613. if (func == 0) {
  614. /* Can only directly write to some F0 registers. Handle F2 enable
  615. * as a special case.
  616. */
  617. if (regaddr == SDIOD_CCCR_IOEN) {
  618. if (sd->func[2]) {
  619. sdio_claim_host(sd->func[2]);
  620. if (*byte & SDIO_FUNC_ENABLE_2) {
  621. /* Enable Function 2 */
  622. err_ret = sdio_enable_func(sd->func[2]);
  623. if (err_ret) {
  624. sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
  625. err_ret));
  626. }
  627. } else {
  628. /* Disable Function 2 */
  629. err_ret = sdio_disable_func(sd->func[2]);
  630. if (err_ret) {
  631. sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
  632. err_ret));
  633. }
  634. }
  635. sdio_release_host(sd->func[2]);
  636. }
  637. }
  638. #if defined(MMC_SDIO_ABORT)
  639. /* to allow abort command through F1 */
  640. else if (regaddr == SDIOD_CCCR_IOABORT) {
  641. while (sdio_abort_retry--) {
  642. if (sd->func[func]) {
  643. sdio_claim_host(sd->func[func]);
  644. /*
  645. * this sdio_f0_writeb() can be replaced with
  646. * another api depending upon MMC driver change.
  647. * As of this time, this is temporaray one
  648. */
  649. sdio_writeb(sd->func[func],
  650. *byte, regaddr, &err_ret);
  651. sdio_release_host(sd->func[func]);
  652. }
  653. if (!err_ret)
  654. break;
  655. }
  656. }
  657. #endif /* MMC_SDIO_ABORT */
  658. else if (regaddr < 0xF0) {
  659. sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
  660. } else {
  661. /* Claim host controller, perform F0 write, and release */
  662. if (sd->func[func]) {
  663. sdio_claim_host(sd->func[func]);
  664. sdio_f0_writeb(sd->func[func],
  665. *byte, regaddr, &err_ret);
  666. sdio_release_host(sd->func[func]);
  667. }
  668. }
  669. } else {
  670. /* Claim host controller, perform Fn write, and release */
  671. if (sd->func[func]) {
  672. sdio_claim_host(sd->func[func]);
  673. sdio_writeb(sd->func[func], *byte, regaddr, &err_ret);
  674. sdio_release_host(sd->func[func]);
  675. }
  676. }
  677. } else { /* CMD52 Read */
  678. /* Claim host controller, perform Fn read, and release */
  679. if (sd->func[func]) {
  680. sdio_claim_host(sd->func[func]);
  681. if (func == 0) {
  682. *byte = sdio_f0_readb(sd->func[func], regaddr, &err_ret);
  683. } else {
  684. *byte = sdio_readb(sd->func[func], regaddr, &err_ret);
  685. }
  686. sdio_release_host(sd->func[func]);
  687. }
  688. }
  689. if (err_ret) {
  690. if ((regaddr == 0x1001F) && ((err_ret == -ETIMEDOUT) || (err_ret == -EILSEQ))) {
  691. } else {
  692. sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
  693. rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
  694. }
  695. }
  696. return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
  697. }
  698. extern SDIOH_API_RC
  699. sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
  700. uint32 *word, uint nbytes)
  701. {
  702. int err_ret = SDIOH_API_RC_FAIL;
  703. #if defined(MMC_SDIO_ABORT)
  704. int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT;
  705. #endif
  706. if (func == 0) {
  707. sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
  708. return SDIOH_API_RC_FAIL;
  709. }
  710. sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
  711. __FUNCTION__, cmd_type, rw, func, addr, nbytes));
  712. DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
  713. DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
  714. /* Claim host controller */
  715. sdio_claim_host(sd->func[func]);
  716. if(rw) { /* CMD52 Write */
  717. if (nbytes == 4) {
  718. sdio_writel(sd->func[func], *word, addr, &err_ret);
  719. } else if (nbytes == 2) {
  720. sdio_writew(sd->func[func], (*word & 0xFFFF), addr, &err_ret);
  721. } else {
  722. sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
  723. }
  724. } else { /* CMD52 Read */
  725. if (nbytes == 4) {
  726. *word = sdio_readl(sd->func[func], addr, &err_ret);
  727. } else if (nbytes == 2) {
  728. *word = sdio_readw(sd->func[func], addr, &err_ret) & 0xFFFF;
  729. } else {
  730. sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
  731. }
  732. }
  733. /* Release host controller */
  734. sdio_release_host(sd->func[func]);
  735. if (err_ret) {
  736. #if defined(MMC_SDIO_ABORT)
  737. /* Any error on CMD53 transaction should abort that function using function 0. */
  738. while (sdio_abort_retry--) {
  739. if (sd->func[0]) {
  740. sdio_claim_host(sd->func[0]);
  741. /*
  742. * this sdio_f0_writeb() can be replaced with another api
  743. * depending upon MMC driver change.
  744. * As of this time, this is temporaray one
  745. */
  746. sdio_writeb(sd->func[0],
  747. func, SDIOD_CCCR_IOABORT, &err_ret);
  748. sdio_release_host(sd->func[0]);
  749. }
  750. if (!err_ret)
  751. break;
  752. }
  753. if (err_ret)
  754. #endif /* MMC_SDIO_ABORT */
  755. {
  756. sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
  757. rw ? "Write" : "Read", err_ret));
  758. }
  759. }
  760. return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
  761. }
  762. #ifdef BCMSDIOH_TXGLOM
  763. static SDIOH_API_RC
  764. sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
  765. uint addr, void *pkt)
  766. {
  767. bool fifo = (fix_inc == SDIOH_DATA_FIX);
  768. int err_ret = 0;
  769. void *pnext;
  770. uint ttl_len, pkt_offset;
  771. uint blk_num;
  772. uint blk_size;
  773. uint max_blk_count;
  774. uint max_req_size;
  775. struct mmc_request mmc_req;
  776. struct mmc_command mmc_cmd;
  777. struct mmc_data mmc_dat;
  778. uint32 sg_count;
  779. struct sdio_func *sdio_func = sd->func[func];
  780. struct mmc_host *host = sdio_func->card->host;
  781. sd_trace(("%s: Enter\n", __FUNCTION__));
  782. ASSERT(pkt);
  783. DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
  784. DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
  785. blk_size = sd->client_block_size[func];
  786. max_blk_count = min(host->max_blk_count, (uint)MAX_IO_RW_EXTENDED_BLK);
  787. max_req_size = min(max_blk_count * blk_size, host->max_req_size);
  788. pkt_offset = 0;
  789. pnext = pkt;
  790. while (pnext != NULL) {
  791. ttl_len = 0;
  792. sg_count = 0;
  793. memset(&mmc_req, 0, sizeof(struct mmc_request));
  794. memset(&mmc_cmd, 0, sizeof(struct mmc_command));
  795. memset(&mmc_dat, 0, sizeof(struct mmc_data));
  796. sg_init_table(sd->sg_list, ARRAYSIZE(sd->sg_list));
  797. /* Set up scatter-gather DMA descriptors. this loop is to find out the max
  798. * data we can transfer with one command 53. blocks per command is limited by
  799. * host max_req_size and 9-bit max block number. when the total length of this
  800. * packet chain is bigger than max_req_size, use multiple SD_IO_RW_EXTENDED
  801. * commands (each transfer is still block aligned)
  802. */
  803. while (pnext != NULL && ttl_len < max_req_size) {
  804. int pkt_len;
  805. int sg_data_size;
  806. uint8 *pdata = (uint8*)PKTDATA(sd->osh, pnext);
  807. ASSERT(pdata != NULL);
  808. pkt_len = PKTLEN(sd->osh, pnext);
  809. sd_trace(("%s[%d] data=%p, len=%d\n", __FUNCTION__, write, pdata, pkt_len));
  810. /* sg_count is unlikely larger than the array size, and this is
  811. * NOT something we can handle here, but in case it happens, PLEASE put
  812. * a restriction on max tx/glom count (based on host->max_segs).
  813. */
  814. if (sg_count >= ARRAYSIZE(sd->sg_list)) {
  815. sd_err(("%s: sg list entries exceed limit\n", __FUNCTION__));
  816. return (SDIOH_API_RC_FAIL);
  817. }
  818. pdata += pkt_offset;
  819. sg_data_size = pkt_len - pkt_offset;
  820. if (sg_data_size > max_req_size - ttl_len)
  821. sg_data_size = max_req_size - ttl_len;
  822. /* some platforms put a restriction on the data size of each scatter-gather
  823. * DMA descriptor, use multiple sg buffers when xfer_size is bigger than
  824. * max_seg_size
  825. */
  826. if (sg_data_size > host->max_seg_size)
  827. sg_data_size = host->max_seg_size;
  828. sg_set_buf(&sd->sg_list[sg_count++], pdata, sg_data_size);
  829. ttl_len += sg_data_size;
  830. pkt_offset += sg_data_size;
  831. if (pkt_offset == pkt_len) {
  832. pnext = PKTNEXT(sd->osh, pnext);
  833. pkt_offset = 0;
  834. }
  835. }
  836. if (ttl_len % blk_size != 0) {
  837. sd_err(("%s, data length %d not aligned to block size %d\n",
  838. __FUNCTION__, ttl_len, blk_size));
  839. return SDIOH_API_RC_FAIL;
  840. }
  841. blk_num = ttl_len / blk_size;
  842. mmc_dat.sg = sd->sg_list;
  843. mmc_dat.sg_len = sg_count;
  844. mmc_dat.blksz = blk_size;
  845. mmc_dat.blocks = blk_num;
  846. mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
  847. mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */
  848. mmc_cmd.arg = write ? 1<<31 : 0;
  849. mmc_cmd.arg |= (func & 0x7) << 28;
  850. mmc_cmd.arg |= 1<<27;
  851. mmc_cmd.arg |= fifo ? 0 : 1<<26;
  852. mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
  853. mmc_cmd.arg |= blk_num & 0x1FF;
  854. mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
  855. mmc_req.cmd = &mmc_cmd;
  856. mmc_req.data = &mmc_dat;
  857. if (!fifo)
  858. addr += ttl_len;
  859. sdio_claim_host(sdio_func);
  860. mmc_set_data_timeout(&mmc_dat, sdio_func->card);
  861. mmc_wait_for_req(host, &mmc_req);
  862. sdio_release_host(sdio_func);
  863. err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
  864. if (0 != err_ret) {
  865. sd_err(("%s:CMD53 %s failed with code %d\n",
  866. __FUNCTION__, write ? "write" : "read", err_ret));
  867. return SDIOH_API_RC_FAIL;
  868. }
  869. }
  870. sd_trace(("%s: Exit\n", __FUNCTION__));
  871. return SDIOH_API_RC_SUCCESS;
  872. }
  873. #endif /* BCMSDIOH_TXGLOM */
  874. static SDIOH_API_RC
  875. sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
  876. uint addr, uint8 *buf, uint len)
  877. {
  878. bool fifo = (fix_inc == SDIOH_DATA_FIX);
  879. int err_ret = 0;
  880. sd_trace(("%s: Enter\n", __FUNCTION__));
  881. ASSERT(buf);
  882. /* NOTE:
  883. * For all writes, each packet length is aligned to 32 (or 4)
  884. * bytes in dhdsdio_txpkt_preprocess, and for glom the last packet length
  885. * is aligned to block boundary. If you want to align each packet to
  886. * a custom size, please do it in dhdsdio_txpkt_preprocess, NOT here
  887. *
  888. * For reads, the alignment is doen in sdioh_request_buffer.
  889. *
  890. */
  891. sdio_claim_host(sd->func[func]);
  892. if ((write) && (!fifo))
  893. err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
  894. else if (write)
  895. err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, len);
  896. else if (fifo)
  897. err_ret = sdio_readsb(sd->func[func], buf, addr, len);
  898. else
  899. err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, len);
  900. sdio_release_host(sd->func[func]);
  901. if (err_ret)
  902. sd_err(("%s: %s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=%d\n", __FUNCTION__,
  903. (write) ? "TX" : "RX", buf, addr, len, err_ret));
  904. else
  905. sd_trace(("%s: %s xfr'd %p, addr=0x%05x, len=%d\n", __FUNCTION__,
  906. (write) ? "TX" : "RX", buf, addr, len));
  907. sd_trace(("%s: Exit\n", __FUNCTION__));
  908. return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
  909. }
  910. /*
  911. * This function takes a buffer or packet, and fixes everything up so that in the
  912. * end, a DMA-able packet is created.
  913. *
  914. * A buffer does not have an associated packet pointer, and may or may not be aligned.
  915. * A packet may consist of a single packet, or a packet chain. If it is a packet chain,
  916. * then all the packets in the chain must be properly aligned. If the packet data is not
  917. * aligned, then there may only be one packet, and in this case, it is copied to a new
  918. * aligned packet.
  919. *
  920. */
  921. extern SDIOH_API_RC
  922. sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
  923. uint addr, uint reg_width, uint buf_len, uint8 *buffer, void *pkt)
  924. {
  925. SDIOH_API_RC status;
  926. void *tmppkt;
  927. #ifdef SDIO_PADDING_FOR_BLK_TRANS
  928. int blk_size;
  929. int nblk;
  930. #endif /* SDIO_PADDING_FOR_BLK_TRANS */
  931. sd_trace(("%s: Enter\n", __FUNCTION__));
  932. DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
  933. DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
  934. if (pkt) {
  935. #ifdef BCMSDIOH_TXGLOM
  936. /* packet chain, only used for tx/rx glom, all packets length
  937. * are aligned, total length is a block multiple
  938. */
  939. if (PKTNEXT(sd->osh, pkt))
  940. return sdioh_request_packet_chain(sd, fix_inc, write, func, addr, pkt);
  941. #endif /* BCMSDIOH_TXGLOM */
  942. /* non-glom mode, ignore the buffer parameter and use the packet pointer
  943. * (this shouldn't happen)
  944. */
  945. buffer = PKTDATA(sd->osh, pkt);
  946. buf_len = PKTLEN(sd->osh, pkt);
  947. }
  948. ASSERT(buffer);
  949. #ifdef SDIO_PADDING_FOR_BLK_TRANS
  950. blk_size = sd->client_block_size[func];
  951. if (write) {
  952. if (buf_len % blk_size == 0)
  953. return sdioh_buffer_tofrom_bus(sd, fix_inc,
  954. write, func, addr, buffer, buf_len);
  955. } else {
  956. if (((ulong)buffer & DMA_ALIGN_MASK) == 0 && (buf_len & DMA_ALIGN_MASK) == 0)
  957. return sdioh_buffer_tofrom_bus(sd, fix_inc,
  958. write, func, addr, buffer, buf_len);
  959. }
  960. sd_trace(("%s: [%d] doing memory copy buf=%p, len=%d\n",
  961. __FUNCTION__, write, buffer, buf_len));
  962. #else
  963. /* buffer and length are aligned, use it directly so we can avoid memory copy */
  964. if (((ulong)buffer & DMA_ALIGN_MASK) == 0 && (buf_len & DMA_ALIGN_MASK) == 0)
  965. return sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr, buffer, buf_len);
  966. sd_err(("%s: [%d] doing memory copy buf=%p, len=%d\n",
  967. __FUNCTION__, write, buffer, buf_len));
  968. #endif /* SDIO_PADDING_FOR_BLK_TRANS */
  969. /* otherwise, a memory copy is needed as the input buffer is not aligned */
  970. tmppkt = PKTGET_STATIC(sd->osh, buf_len + DEFAULT_SDIO_F2_BLKSIZE, write ? TRUE : FALSE);
  971. if (tmppkt == NULL) {
  972. sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buf_len));
  973. return SDIOH_API_RC_FAIL;
  974. }
  975. if (write)
  976. bcopy(buffer, PKTDATA(sd->osh, tmppkt), buf_len);
  977. #ifdef SDIO_PADDING_FOR_BLK_TRANS
  978. if (write) {
  979. /* nblk : blk_size count for re-padding buf_len */
  980. nblk = (buf_len / blk_size) + 1;
  981. status = sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,
  982. PKTDATA(sd->osh, tmppkt), (blk_size * nblk));
  983. } else
  984. #endif /* SDIO_PADDING_FOR_BLK_TRANS */
  985. {
  986. status = sdioh_buffer_tofrom_bus(sd, fix_inc, write, func, addr,
  987. PKTDATA(sd->osh, tmppkt), ROUNDUP(buf_len, (DMA_ALIGN_MASK+1)));
  988. }
  989. if (!write)
  990. bcopy(PKTDATA(sd->osh, tmppkt), buffer, buf_len);
  991. PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
  992. return status;
  993. }
  994. /* this function performs "abort" for both of host & device */
  995. extern int
  996. sdioh_abort(sdioh_info_t *sd, uint func)
  997. {
  998. #if defined(MMC_SDIO_ABORT)
  999. char t_func = (char) func;
  1000. #endif /* defined(MMC_SDIO_ABORT) */
  1001. sd_trace(("%s: Enter\n", __FUNCTION__));
  1002. #if defined(MMC_SDIO_ABORT)
  1003. /* issue abort cmd52 command through F1 */
  1004. sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
  1005. #endif /* defined(MMC_SDIO_ABORT) */
  1006. sd_trace(("%s: Exit\n", __FUNCTION__));
  1007. return SDIOH_API_RC_SUCCESS;
  1008. }
  1009. /* Reset and re-initialize the device */
  1010. int sdioh_sdio_reset(sdioh_info_t *si)
  1011. {
  1012. sd_trace(("%s: Enter\n", __FUNCTION__));
  1013. sd_trace(("%s: Exit\n", __FUNCTION__));
  1014. return SDIOH_API_RC_SUCCESS;
  1015. }
  1016. /* Disable device interrupt */
  1017. void
  1018. sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
  1019. {
  1020. sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
  1021. sd->intmask &= ~CLIENT_INTR;
  1022. }
  1023. /* Enable device interrupt */
  1024. void
  1025. sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
  1026. {
  1027. sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
  1028. sd->intmask |= CLIENT_INTR;
  1029. }
  1030. /* Read client card reg */
  1031. int
  1032. sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
  1033. {
  1034. if ((func == 0) || (regsize == 1)) {
  1035. uint8 temp = 0;
  1036. sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
  1037. *data = temp;
  1038. *data &= 0xff;
  1039. sd_data(("%s: byte read data=0x%02x\n",
  1040. __FUNCTION__, *data));
  1041. } else {
  1042. sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize);
  1043. if (regsize == 2)
  1044. *data &= 0xffff;
  1045. sd_data(("%s: word read data=0x%08x\n",
  1046. __FUNCTION__, *data));
  1047. }
  1048. return SUCCESS;
  1049. }
  1050. #if !defined(OOB_INTR_ONLY)
  1051. /* bcmsdh_sdmmc interrupt handler */
  1052. static void IRQHandler(struct sdio_func *func)
  1053. {
  1054. sdioh_info_t *sd;
  1055. sd = sdio_get_drvdata(func);
  1056. ASSERT(sd != NULL);
  1057. sdio_release_host(sd->func[0]);
  1058. if (sd->use_client_ints) {
  1059. sd->intrcount++;
  1060. ASSERT(sd->intr_handler);
  1061. ASSERT(sd->intr_handler_arg);
  1062. (sd->intr_handler)(sd->intr_handler_arg);
  1063. } else {
  1064. sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
  1065. sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
  1066. __FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
  1067. }
  1068. sdio_claim_host(sd->func[0]);
  1069. }
  1070. /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
  1071. static void IRQHandlerF2(struct sdio_func *func)
  1072. {
  1073. sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
  1074. }
  1075. #endif /* !defined(OOB_INTR_ONLY) */
  1076. #ifdef NOTUSED
  1077. /* Write client card reg */
  1078. static int
  1079. sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
  1080. {
  1081. if ((func == 0) || (regsize == 1)) {
  1082. uint8 temp;
  1083. temp = data & 0xff;
  1084. sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
  1085. sd_data(("%s: byte write data=0x%02x\n",
  1086. __FUNCTION__, data));
  1087. } else {
  1088. if (regsize == 2)
  1089. data &= 0xffff;
  1090. sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize);
  1091. sd_data(("%s: word write data=0x%08x\n",
  1092. __FUNCTION__, data));
  1093. }
  1094. return SUCCESS;
  1095. }
  1096. #endif /* NOTUSED */
  1097. int
  1098. sdioh_start(sdioh_info_t *sd, int stage)
  1099. {
  1100. int ret;
  1101. if (!sd) {
  1102. sd_err(("%s Failed, sd is NULL\n", __FUNCTION__));
  1103. return (0);
  1104. }
  1105. /* Need to do this stages as we can't enable the interrupt till
  1106. downloading of the firmware is complete, other wise polling
  1107. sdio access will come in way
  1108. */
  1109. if (sd->func[0]) {
  1110. if (stage == 0) {
  1111. /* Since the power to the chip is killed, we will have
  1112. re enumerate the device again. Set the block size
  1113. and enable the fucntion 1 for in preparation for
  1114. downloading the code
  1115. */
  1116. /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
  1117. 2.6.27. The implementation prior to that is buggy, and needs broadcom's
  1118. patch for it
  1119. */
  1120. if ((ret = sdio_reset_comm(sd->func[0]->card))) {
  1121. sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
  1122. return ret;
  1123. }
  1124. else {
  1125. sd->num_funcs = 2;
  1126. sd->sd_blockmode = TRUE;
  1127. sd->use_client_ints = TRUE;
  1128. sd->client_block_size[0] = 64;
  1129. if (sd->func[1]) {
  1130. /* Claim host controller */
  1131. sdio_claim_host(sd->func[1]);
  1132. sd->client_block_size[1] = 64;
  1133. ret = sdio_set_block_size(sd->func[1], 64);
  1134. if (ret) {
  1135. sd_err(("bcmsdh_sdmmc: Failed to set F1 "
  1136. "blocksize(%d)\n", ret));
  1137. }
  1138. /* Release host controller F1 */
  1139. sdio_release_host(sd->func[1]);
  1140. }
  1141. if (sd->func[2]) {
  1142. /* Claim host controller F2 */
  1143. sdio_claim_host(sd->func[2]);
  1144. sd->client_block_size[2] = sd_f2_blocksize;
  1145. ret = sdio_set_block_size(sd->func[2], sd_f2_blocksize);
  1146. if (ret) {
  1147. sd_err(("bcmsdh_sdmmc: Failed to set F2 "
  1148. "blocksize to %d(%d)\n", sd_f2_blocksize, ret));
  1149. }
  1150. /* Release host controller F2 */
  1151. sdio_release_host(sd->func[2]);
  1152. }
  1153. sdioh_sdmmc_card_enablefuncs(sd);
  1154. }
  1155. } else {
  1156. #if !defined(OOB_INTR_ONLY)
  1157. sdio_claim_host(sd->func[0]);
  1158. if (sd->func[2])
  1159. sdio_claim_irq(sd->func[2], IRQHandlerF2);
  1160. if (sd->func[1])
  1161. sdio_claim_irq(sd->func[1], IRQHandler);
  1162. sdio_release_host(sd->func[0]);
  1163. #else /* defined(OOB_INTR_ONLY) */
  1164. #if defined(HW_OOB)
  1165. sdioh_enable_func_intr(sd);
  1166. #endif
  1167. bcmsdh_oob_intr_set(sd->bcmsdh, TRUE);
  1168. #endif /* !defined(OOB_INTR_ONLY) */
  1169. }
  1170. }
  1171. else
  1172. sd_err(("%s Failed\n", __FUNCTION__));
  1173. return (0);
  1174. }
  1175. int
  1176. sdioh_stop(sdioh_info_t *sd)
  1177. {
  1178. /* MSM7201A Android sdio stack has bug with interrupt
  1179. So internaly within SDIO stack they are polling
  1180. which cause issue when device is turned off. So
  1181. unregister interrupt with SDIO stack to stop the
  1182. polling
  1183. */
  1184. if (sd->func[0]) {
  1185. #if !defined(OOB_INTR_ONLY)
  1186. sdio_claim_host(sd->func[0]);
  1187. if (sd->func[1])
  1188. sdio_release_irq(sd->func[1]);
  1189. if (sd->func[2])
  1190. sdio_release_irq(sd->func[2]);
  1191. sdio_release_host(sd->func[0]);
  1192. #else /* defined(OOB_INTR_ONLY) */
  1193. #if defined(HW_OOB)
  1194. sdioh_disable_func_intr(sd);
  1195. #endif
  1196. bcmsdh_oob_intr_set(sd->bcmsdh, FALSE);
  1197. #endif /* !defined(OOB_INTR_ONLY) */
  1198. }
  1199. else
  1200. sd_err(("%s Failed\n", __FUNCTION__));
  1201. return (0);
  1202. }
  1203. int
  1204. sdioh_waitlockfree(sdioh_info_t *sd)
  1205. {
  1206. return (1);
  1207. }
  1208. SDIOH_API_RC
  1209. sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
  1210. {
  1211. return SDIOH_API_RC_FAIL;
  1212. }
  1213. SDIOH_API_RC
  1214. sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
  1215. {
  1216. return SDIOH_API_RC_FAIL;
  1217. }
  1218. bool
  1219. sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
  1220. {
  1221. return FALSE;
  1222. }
  1223. SDIOH_API_RC
  1224. sdioh_gpio_init(sdioh_info_t *sd)
  1225. {
  1226. return SDIOH_API_RC_FAIL;
  1227. }