/drivers/staging/ath6kl/bmi/src/bmi.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t · C · 1010 lines · 724 code · 150 blank · 136 comment · 79 complexity · a99ec6d66cbbd4901f8d529a644639c6 MD5 · raw file

  1. //------------------------------------------------------------------------------
  2. // <copyright file="bmi.c" company="Atheros">
  3. // Copyright (c) 2004-2010 Atheros Corporation. All rights reserved.
  4. //
  5. //
  6. // Permission to use, copy, modify, and/or distribute this software for any
  7. // purpose with or without fee is hereby granted, provided that the above
  8. // copyright notice and this permission notice appear in all copies.
  9. //
  10. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. //
  18. //
  19. //------------------------------------------------------------------------------
  20. //==============================================================================
  21. //
  22. // Author(s): ="Atheros"
  23. //==============================================================================
  24. #ifdef THREAD_X
  25. #include <string.h>
  26. #endif
  27. #include "hif.h"
  28. #include "bmi.h"
  29. #include "htc_api.h"
  30. #include "bmi_internal.h"
  31. #ifdef ATH_DEBUG_MODULE
  32. static struct ath_debug_mask_description bmi_debug_desc[] = {
  33. { ATH_DEBUG_BMI , "BMI Tracing"},
  34. };
  35. ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
  36. "bmi",
  37. "Boot Manager Interface",
  38. ATH_DEBUG_MASK_DEFAULTS,
  39. ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
  40. bmi_debug_desc);
  41. #endif
  42. /*
  43. Although we had envisioned BMI to run on top of HTC, this is not how the
  44. final implementation ended up. On the Target side, BMI is a part of the BSP
  45. and does not use the HTC protocol nor even DMA -- it is intentionally kept
  46. very simple.
  47. */
  48. static bool pendingEventsFuncCheck = false;
  49. static u32 *pBMICmdCredits;
  50. static u8 *pBMICmdBuf;
  51. #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
  52. sizeof(u32) /* cmd */ + \
  53. sizeof(u32) /* addr */ + \
  54. sizeof(u32))/* length */
  55. #define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
  56. /* APIs visible to the driver */
  57. void
  58. BMIInit(void)
  59. {
  60. bmiDone = false;
  61. pendingEventsFuncCheck = false;
  62. /*
  63. * On some platforms, it's not possible to DMA to a static variable
  64. * in a device driver (e.g. Linux loadable driver module).
  65. * So we need to A_MALLOC space for "command credits" and for commands.
  66. *
  67. * Note: implicitly relies on A_MALLOC to provide a buffer that is
  68. * suitable for DMA (or PIO). This buffer will be passed down the
  69. * bus stack.
  70. */
  71. if (!pBMICmdCredits) {
  72. pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
  73. A_ASSERT(pBMICmdCredits);
  74. }
  75. if (!pBMICmdBuf) {
  76. pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
  77. A_ASSERT(pBMICmdBuf);
  78. }
  79. A_REGISTER_MODULE_DEBUG_INFO(bmi);
  80. }
  81. void
  82. BMICleanup(void)
  83. {
  84. if (pBMICmdCredits) {
  85. kfree(pBMICmdCredits);
  86. pBMICmdCredits = NULL;
  87. }
  88. if (pBMICmdBuf) {
  89. kfree(pBMICmdBuf);
  90. pBMICmdBuf = NULL;
  91. }
  92. }
  93. int
  94. BMIDone(struct hif_device *device)
  95. {
  96. int status;
  97. u32 cid;
  98. if (bmiDone) {
  99. AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
  100. return 0;
  101. }
  102. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
  103. bmiDone = true;
  104. cid = BMI_DONE;
  105. status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
  106. if (status) {
  107. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  108. return A_ERROR;
  109. }
  110. if (pBMICmdCredits) {
  111. kfree(pBMICmdCredits);
  112. pBMICmdCredits = NULL;
  113. }
  114. if (pBMICmdBuf) {
  115. kfree(pBMICmdBuf);
  116. pBMICmdBuf = NULL;
  117. }
  118. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
  119. return 0;
  120. }
  121. int
  122. BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
  123. {
  124. int status;
  125. u32 cid;
  126. if (bmiDone) {
  127. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  128. return A_ERROR;
  129. }
  130. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
  131. cid = BMI_GET_TARGET_INFO;
  132. status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
  133. if (status) {
  134. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  135. return A_ERROR;
  136. }
  137. status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
  138. sizeof(targ_info->target_ver), true);
  139. if (status) {
  140. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
  141. return A_ERROR;
  142. }
  143. if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
  144. /* Determine how many bytes are in the Target's targ_info */
  145. status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
  146. sizeof(targ_info->target_info_byte_count), true);
  147. if (status) {
  148. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
  149. return A_ERROR;
  150. }
  151. /*
  152. * The Target's targ_info doesn't match the Host's targ_info.
  153. * We need to do some backwards compatibility work to make this OK.
  154. */
  155. A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
  156. /* Read the remainder of the targ_info */
  157. status = bmiBufferReceive(device,
  158. ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
  159. sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
  160. if (status) {
  161. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
  162. targ_info->target_info_byte_count));
  163. return A_ERROR;
  164. }
  165. }
  166. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
  167. targ_info->target_ver, targ_info->target_type));
  168. return 0;
  169. }
  170. int
  171. BMIReadMemory(struct hif_device *device,
  172. u32 address,
  173. u8 *buffer,
  174. u32 length)
  175. {
  176. u32 cid;
  177. int status;
  178. u32 offset;
  179. u32 remaining, rxlen;
  180. A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
  181. memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
  182. if (bmiDone) {
  183. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  184. return A_ERROR;
  185. }
  186. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  187. ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
  188. device, address, length));
  189. cid = BMI_READ_MEMORY;
  190. remaining = length;
  191. while (remaining)
  192. {
  193. rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
  194. offset = 0;
  195. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  196. offset += sizeof(cid);
  197. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  198. offset += sizeof(address);
  199. memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
  200. offset += sizeof(length);
  201. status = bmiBufferSend(device, pBMICmdBuf, offset);
  202. if (status) {
  203. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  204. return A_ERROR;
  205. }
  206. status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
  207. if (status) {
  208. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
  209. return A_ERROR;
  210. }
  211. memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
  212. remaining -= rxlen; address += rxlen;
  213. }
  214. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
  215. return 0;
  216. }
  217. int
  218. BMIWriteMemory(struct hif_device *device,
  219. u32 address,
  220. u8 *buffer,
  221. u32 length)
  222. {
  223. u32 cid;
  224. int status;
  225. u32 offset;
  226. u32 remaining, txlen;
  227. const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
  228. u8 alignedBuffer[BMI_DATASZ_MAX];
  229. u8 *src;
  230. A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
  231. memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
  232. if (bmiDone) {
  233. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  234. return A_ERROR;
  235. }
  236. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  237. ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
  238. device, address, length));
  239. cid = BMI_WRITE_MEMORY;
  240. remaining = length;
  241. while (remaining)
  242. {
  243. src = &buffer[length - remaining];
  244. if (remaining < (BMI_DATASZ_MAX - header)) {
  245. if (remaining & 3) {
  246. /* align it with 4 bytes */
  247. remaining = remaining + (4 - (remaining & 3));
  248. memcpy(alignedBuffer, src, remaining);
  249. src = alignedBuffer;
  250. }
  251. txlen = remaining;
  252. } else {
  253. txlen = (BMI_DATASZ_MAX - header);
  254. }
  255. offset = 0;
  256. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  257. offset += sizeof(cid);
  258. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  259. offset += sizeof(address);
  260. memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
  261. offset += sizeof(txlen);
  262. memcpy(&(pBMICmdBuf[offset]), src, txlen);
  263. offset += txlen;
  264. status = bmiBufferSend(device, pBMICmdBuf, offset);
  265. if (status) {
  266. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  267. return A_ERROR;
  268. }
  269. remaining -= txlen; address += txlen;
  270. }
  271. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
  272. return 0;
  273. }
  274. int
  275. BMIExecute(struct hif_device *device,
  276. u32 address,
  277. u32 *param)
  278. {
  279. u32 cid;
  280. int status;
  281. u32 offset;
  282. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
  283. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
  284. if (bmiDone) {
  285. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  286. return A_ERROR;
  287. }
  288. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  289. ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
  290. device, address, *param));
  291. cid = BMI_EXECUTE;
  292. offset = 0;
  293. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  294. offset += sizeof(cid);
  295. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  296. offset += sizeof(address);
  297. memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
  298. offset += sizeof(*param);
  299. status = bmiBufferSend(device, pBMICmdBuf, offset);
  300. if (status) {
  301. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  302. return A_ERROR;
  303. }
  304. status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
  305. if (status) {
  306. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
  307. return A_ERROR;
  308. }
  309. memcpy(param, pBMICmdBuf, sizeof(*param));
  310. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
  311. return 0;
  312. }
  313. int
  314. BMISetAppStart(struct hif_device *device,
  315. u32 address)
  316. {
  317. u32 cid;
  318. int status;
  319. u32 offset;
  320. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
  321. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
  322. if (bmiDone) {
  323. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  324. return A_ERROR;
  325. }
  326. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  327. ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
  328. device, address));
  329. cid = BMI_SET_APP_START;
  330. offset = 0;
  331. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  332. offset += sizeof(cid);
  333. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  334. offset += sizeof(address);
  335. status = bmiBufferSend(device, pBMICmdBuf, offset);
  336. if (status) {
  337. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  338. return A_ERROR;
  339. }
  340. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
  341. return 0;
  342. }
  343. int
  344. BMIReadSOCRegister(struct hif_device *device,
  345. u32 address,
  346. u32 *param)
  347. {
  348. u32 cid;
  349. int status;
  350. u32 offset;
  351. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
  352. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
  353. if (bmiDone) {
  354. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  355. return A_ERROR;
  356. }
  357. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  358. ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
  359. device, address));
  360. cid = BMI_READ_SOC_REGISTER;
  361. offset = 0;
  362. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  363. offset += sizeof(cid);
  364. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  365. offset += sizeof(address);
  366. status = bmiBufferSend(device, pBMICmdBuf, offset);
  367. if (status) {
  368. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  369. return A_ERROR;
  370. }
  371. status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
  372. if (status) {
  373. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
  374. return A_ERROR;
  375. }
  376. memcpy(param, pBMICmdBuf, sizeof(*param));
  377. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
  378. return 0;
  379. }
  380. int
  381. BMIWriteSOCRegister(struct hif_device *device,
  382. u32 address,
  383. u32 param)
  384. {
  385. u32 cid;
  386. int status;
  387. u32 offset;
  388. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
  389. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
  390. if (bmiDone) {
  391. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  392. return A_ERROR;
  393. }
  394. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  395. ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
  396. device, address, param));
  397. cid = BMI_WRITE_SOC_REGISTER;
  398. offset = 0;
  399. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  400. offset += sizeof(cid);
  401. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  402. offset += sizeof(address);
  403. memcpy(&(pBMICmdBuf[offset]), &param, sizeof(param));
  404. offset += sizeof(param);
  405. status = bmiBufferSend(device, pBMICmdBuf, offset);
  406. if (status) {
  407. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  408. return A_ERROR;
  409. }
  410. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
  411. return 0;
  412. }
  413. int
  414. BMIrompatchInstall(struct hif_device *device,
  415. u32 ROM_addr,
  416. u32 RAM_addr,
  417. u32 nbytes,
  418. u32 do_activate,
  419. u32 *rompatch_id)
  420. {
  421. u32 cid;
  422. int status;
  423. u32 offset;
  424. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
  425. sizeof(nbytes) + sizeof(do_activate)));
  426. memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
  427. sizeof(nbytes) + sizeof(do_activate));
  428. if (bmiDone) {
  429. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  430. return A_ERROR;
  431. }
  432. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  433. ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
  434. device, ROM_addr, RAM_addr, nbytes, do_activate));
  435. cid = BMI_ROMPATCH_INSTALL;
  436. offset = 0;
  437. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  438. offset += sizeof(cid);
  439. memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
  440. offset += sizeof(ROM_addr);
  441. memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
  442. offset += sizeof(RAM_addr);
  443. memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
  444. offset += sizeof(nbytes);
  445. memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
  446. offset += sizeof(do_activate);
  447. status = bmiBufferSend(device, pBMICmdBuf, offset);
  448. if (status) {
  449. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  450. return A_ERROR;
  451. }
  452. status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
  453. if (status) {
  454. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
  455. return A_ERROR;
  456. }
  457. memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
  458. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
  459. return 0;
  460. }
  461. int
  462. BMIrompatchUninstall(struct hif_device *device,
  463. u32 rompatch_id)
  464. {
  465. u32 cid;
  466. int status;
  467. u32 offset;
  468. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
  469. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
  470. if (bmiDone) {
  471. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  472. return A_ERROR;
  473. }
  474. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  475. ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
  476. device, rompatch_id));
  477. cid = BMI_ROMPATCH_UNINSTALL;
  478. offset = 0;
  479. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  480. offset += sizeof(cid);
  481. memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
  482. offset += sizeof(rompatch_id);
  483. status = bmiBufferSend(device, pBMICmdBuf, offset);
  484. if (status) {
  485. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  486. return A_ERROR;
  487. }
  488. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
  489. return 0;
  490. }
  491. static int
  492. _BMIrompatchChangeActivation(struct hif_device *device,
  493. u32 rompatch_count,
  494. u32 *rompatch_list,
  495. u32 do_activate)
  496. {
  497. u32 cid;
  498. int status;
  499. u32 offset;
  500. u32 length;
  501. A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
  502. memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
  503. if (bmiDone) {
  504. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  505. return A_ERROR;
  506. }
  507. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  508. ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
  509. device, rompatch_count));
  510. cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
  511. offset = 0;
  512. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  513. offset += sizeof(cid);
  514. memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
  515. offset += sizeof(rompatch_count);
  516. length = rompatch_count * sizeof(*rompatch_list);
  517. memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
  518. offset += length;
  519. status = bmiBufferSend(device, pBMICmdBuf, offset);
  520. if (status) {
  521. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  522. return A_ERROR;
  523. }
  524. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
  525. return 0;
  526. }
  527. int
  528. BMIrompatchActivate(struct hif_device *device,
  529. u32 rompatch_count,
  530. u32 *rompatch_list)
  531. {
  532. return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
  533. }
  534. int
  535. BMIrompatchDeactivate(struct hif_device *device,
  536. u32 rompatch_count,
  537. u32 *rompatch_list)
  538. {
  539. return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
  540. }
  541. int
  542. BMILZData(struct hif_device *device,
  543. u8 *buffer,
  544. u32 length)
  545. {
  546. u32 cid;
  547. int status;
  548. u32 offset;
  549. u32 remaining, txlen;
  550. const u32 header = sizeof(cid) + sizeof(length);
  551. A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
  552. memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
  553. if (bmiDone) {
  554. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  555. return A_ERROR;
  556. }
  557. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  558. ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
  559. device, length));
  560. cid = BMI_LZ_DATA;
  561. remaining = length;
  562. while (remaining)
  563. {
  564. txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
  565. remaining : (BMI_DATASZ_MAX - header);
  566. offset = 0;
  567. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  568. offset += sizeof(cid);
  569. memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
  570. offset += sizeof(txlen);
  571. memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
  572. offset += txlen;
  573. status = bmiBufferSend(device, pBMICmdBuf, offset);
  574. if (status) {
  575. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
  576. return A_ERROR;
  577. }
  578. remaining -= txlen;
  579. }
  580. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
  581. return 0;
  582. }
  583. int
  584. BMILZStreamStart(struct hif_device *device,
  585. u32 address)
  586. {
  587. u32 cid;
  588. int status;
  589. u32 offset;
  590. A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
  591. memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
  592. if (bmiDone) {
  593. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
  594. return A_ERROR;
  595. }
  596. AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
  597. ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
  598. device, address));
  599. cid = BMI_LZ_STREAM_START;
  600. offset = 0;
  601. memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
  602. offset += sizeof(cid);
  603. memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
  604. offset += sizeof(address);
  605. status = bmiBufferSend(device, pBMICmdBuf, offset);
  606. if (status) {
  607. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
  608. return A_ERROR;
  609. }
  610. AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
  611. return 0;
  612. }
  613. /* BMI Access routines */
  614. int
  615. bmiBufferSend(struct hif_device *device,
  616. u8 *buffer,
  617. u32 length)
  618. {
  619. int status;
  620. u32 timeout;
  621. u32 address;
  622. u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
  623. HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
  624. &mboxAddress[0], sizeof(mboxAddress));
  625. *pBMICmdCredits = 0;
  626. timeout = BMI_COMMUNICATION_TIMEOUT;
  627. while(timeout-- && !(*pBMICmdCredits)) {
  628. /* Read the counter register to get the command credits */
  629. address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
  630. /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
  631. * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
  632. * make all HIF accesses 4-byte aligned */
  633. status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
  634. HIF_RD_SYNC_BYTE_INC, NULL);
  635. if (status) {
  636. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
  637. return A_ERROR;
  638. }
  639. /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
  640. (*pBMICmdCredits) &= 0xFF;
  641. }
  642. if (*pBMICmdCredits) {
  643. address = mboxAddress[ENDPOINT1];
  644. status = HIFReadWrite(device, address, buffer, length,
  645. HIF_WR_SYNC_BYTE_INC, NULL);
  646. if (status) {
  647. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
  648. return A_ERROR;
  649. }
  650. } else {
  651. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
  652. return A_ERROR;
  653. }
  654. return status;
  655. }
  656. int
  657. bmiBufferReceive(struct hif_device *device,
  658. u8 *buffer,
  659. u32 length,
  660. bool want_timeout)
  661. {
  662. int status;
  663. u32 address;
  664. u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
  665. struct hif_pending_events_info hifPendingEvents;
  666. static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
  667. if (!pendingEventsFuncCheck) {
  668. /* see if the HIF layer implements an alternative function to get pending events
  669. * do this only once! */
  670. HIFConfigureDevice(device,
  671. HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
  672. &getPendingEventsFunc,
  673. sizeof(getPendingEventsFunc));
  674. pendingEventsFuncCheck = true;
  675. }
  676. HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
  677. &mboxAddress[0], sizeof(mboxAddress));
  678. /*
  679. * During normal bootup, small reads may be required.
  680. * Rather than issue an HIF Read and then wait as the Target
  681. * adds successive bytes to the FIFO, we wait here until
  682. * we know that response data is available.
  683. *
  684. * This allows us to cleanly timeout on an unexpected
  685. * Target failure rather than risk problems at the HIF level. In
  686. * particular, this avoids SDIO timeouts and possibly garbage
  687. * data on some host controllers. And on an interconnect
  688. * such as Compact Flash (as well as some SDIO masters) which
  689. * does not provide any indication on data timeout, it avoids
  690. * a potential hang or garbage response.
  691. *
  692. * Synchronization is more difficult for reads larger than the
  693. * size of the MBOX FIFO (128B), because the Target is unable
  694. * to push the 129th byte of data until AFTER the Host posts an
  695. * HIF Read and removes some FIFO data. So for large reads the
  696. * Host proceeds to post an HIF Read BEFORE all the data is
  697. * actually available to read. Fortunately, large BMI reads do
  698. * not occur in practice -- they're supported for debug/development.
  699. *
  700. * So Host/Target BMI synchronization is divided into these cases:
  701. * CASE 1: length < 4
  702. * Should not happen
  703. *
  704. * CASE 2: 4 <= length <= 128
  705. * Wait for first 4 bytes to be in FIFO
  706. * If CONSERVATIVE_BMI_READ is enabled, also wait for
  707. * a BMI command credit, which indicates that the ENTIRE
  708. * response is available in the the FIFO
  709. *
  710. * CASE 3: length > 128
  711. * Wait for the first 4 bytes to be in FIFO
  712. *
  713. * For most uses, a small timeout should be sufficient and we will
  714. * usually see a response quickly; but there may be some unusual
  715. * (debug) cases of BMI_EXECUTE where we want an larger timeout.
  716. * For now, we use an unbounded busy loop while waiting for
  717. * BMI_EXECUTE.
  718. *
  719. * If BMI_EXECUTE ever needs to support longer-latency execution,
  720. * especially in production, this code needs to be enhanced to sleep
  721. * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
  722. * a function of Host processor speed.
  723. */
  724. if (length >= 4) { /* NB: Currently, always true */
  725. /*
  726. * NB: word_available is declared static for esoteric reasons
  727. * having to do with protection on some OSes.
  728. */
  729. static u32 word_available;
  730. u32 timeout;
  731. word_available = 0;
  732. timeout = BMI_COMMUNICATION_TIMEOUT;
  733. while((!want_timeout || timeout--) && !word_available) {
  734. if (getPendingEventsFunc != NULL) {
  735. status = getPendingEventsFunc(device,
  736. &hifPendingEvents,
  737. NULL);
  738. if (status) {
  739. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
  740. break;
  741. }
  742. if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
  743. word_available = 1;
  744. }
  745. continue;
  746. }
  747. status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
  748. sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
  749. if (status) {
  750. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
  751. return A_ERROR;
  752. }
  753. /* We did a 4-byte read to the same register; all we really want is one bit */
  754. word_available &= (1 << ENDPOINT1);
  755. }
  756. if (!word_available) {
  757. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
  758. return A_ERROR;
  759. }
  760. }
  761. #define CONSERVATIVE_BMI_READ 0
  762. #if CONSERVATIVE_BMI_READ
  763. /*
  764. * This is an extra-conservative CREDIT check. It guarantees
  765. * that ALL data is available in the FIFO before we start to
  766. * read from the interconnect.
  767. *
  768. * This credit check is useless when firmware chooses to
  769. * allow multiple outstanding BMI Command Credits, since the next
  770. * credit will already be present. To restrict the Target to one
  771. * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
  772. *
  773. * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
  774. * we cannot wait for the next credit because the Target's FIFO
  775. * will not hold the entire response. So we need the Host to
  776. * start to empty the FIFO sooner. (And again, large reads are
  777. * not used in practice; they are for debug/development only.)
  778. *
  779. * For a more conservative Host implementation (which would be
  780. * safer for a Compact Flash interconnect):
  781. * Set CONSERVATIVE_BMI_READ (above) to 1
  782. * Set HI_OPTION_BMI_CRED_LIMIT and
  783. * reduce BMI_DATASZ_MAX to 32 or 64
  784. */
  785. if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
  786. u32 timeout;
  787. *pBMICmdCredits = 0;
  788. timeout = BMI_COMMUNICATION_TIMEOUT;
  789. while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
  790. /* Read the counter register to get the command credits */
  791. address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
  792. /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
  793. * we can read this counter multiple times using a non-incrementing address mode.
  794. * The rationale here is to make all HIF accesses a multiple of 4 bytes */
  795. status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
  796. HIF_RD_SYNC_BYTE_FIX, NULL);
  797. if (status) {
  798. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
  799. return A_ERROR;
  800. }
  801. /* we did a 4-byte read to the same count register so mask off upper bytes */
  802. (*pBMICmdCredits) &= 0xFF;
  803. }
  804. if (!(*pBMICmdCredits)) {
  805. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
  806. return A_ERROR;
  807. }
  808. }
  809. #endif
  810. address = mboxAddress[ENDPOINT1];
  811. status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
  812. if (status) {
  813. AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
  814. return A_ERROR;
  815. }
  816. return 0;
  817. }
  818. int
  819. BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
  820. {
  821. int status = A_ERROR;
  822. u32 lastWord = 0;
  823. u32 lastWordOffset = length & ~0x3;
  824. u32 unalignedBytes = length & 0x3;
  825. status = BMILZStreamStart (device, address);
  826. if (status) {
  827. return A_ERROR;
  828. }
  829. if (unalignedBytes) {
  830. /* copy the last word into a zero padded buffer */
  831. memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
  832. }
  833. status = BMILZData(device, buffer, lastWordOffset);
  834. if (status) {
  835. return A_ERROR;
  836. }
  837. if (unalignedBytes) {
  838. status = BMILZData(device, (u8 *)&lastWord, 4);
  839. }
  840. if (!status) {
  841. //
  842. // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches.
  843. //
  844. status = BMILZStreamStart (device, 0x00);
  845. if (status) {
  846. return A_ERROR;
  847. }
  848. }
  849. return status;
  850. }
  851. int
  852. BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
  853. {
  854. return bmiBufferSend(device, buffer, length);
  855. }
  856. int
  857. BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
  858. {
  859. return bmiBufferReceive(device, buffer, length, want_timeout);
  860. }