sdio_chip.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * Copyright (c) 2011 Broadcom Corporation
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /* ***** SDIO interface chip backplane handle functions ***** */
  17. #include <linux/types.h>
  18. #include <linux/netdevice.h>
  19. #include <linux/mmc/card.h>
  20. #include <chipcommon.h>
  21. #include <brcm_hw_ids.h>
  22. #include <brcmu_wifi.h>
  23. #include <brcmu_utils.h>
  24. #include <soc.h>
  25. #include "dhd.h"
  26. #include "dhd_dbg.h"
  27. #include "sdio_host.h"
  28. #include "sdio_chip.h"
  29. /* chip core base & ramsize */
  30. /* bcm4329 */
  31. /* SDIO device core, ID 0x829 */
  32. #define BCM4329_CORE_BUS_BASE 0x18011000
  33. /* internal memory core, ID 0x80e */
  34. #define BCM4329_CORE_SOCRAM_BASE 0x18003000
  35. /* ARM Cortex M3 core, ID 0x82a */
  36. #define BCM4329_CORE_ARM_BASE 0x18002000
  37. #define BCM4329_RAMSIZE 0x48000
  38. /* SB regs */
  39. /* sbidhigh */
  40. #define SBIDH_RC_MASK 0x000f /* revision code */
  41. #define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
  42. #define SBIDH_RCE_SHIFT 8
  43. #define SBCOREREV(sbidh) \
  44. ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
  45. ((sbidh) & SBIDH_RC_MASK))
  46. #define SBIDH_CC_MASK 0x8ff0 /* core code */
  47. #define SBIDH_CC_SHIFT 4
  48. #define SBIDH_VC_MASK 0xffff0000 /* vendor code */
  49. #define SBIDH_VC_SHIFT 16
  50. #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
  51. /* SDIO Pad drive strength to select value mappings */
  52. struct sdiod_drive_str {
  53. u8 strength; /* Pad Drive Strength in mA */
  54. u8 sel; /* Chip-specific select value */
  55. };
  56. /* SDIO Drive Strength to sel value table for PMU Rev 1 */
  57. static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
  58. {
  59. 4, 0x2}, {
  60. 2, 0x3}, {
  61. 1, 0x0}, {
  62. 0, 0x0}
  63. };
  64. /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
  65. static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
  66. {
  67. 12, 0x7}, {
  68. 10, 0x6}, {
  69. 8, 0x5}, {
  70. 6, 0x4}, {
  71. 4, 0x2}, {
  72. 2, 0x1}, {
  73. 0, 0x0}
  74. };
  75. /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
  76. static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
  77. {
  78. 32, 0x7}, {
  79. 26, 0x6}, {
  80. 22, 0x5}, {
  81. 16, 0x4}, {
  82. 12, 0x3}, {
  83. 8, 0x2}, {
  84. 4, 0x1}, {
  85. 0, 0x0}
  86. };
  87. static u32
  88. brcmf_sdio_chip_corerev(struct brcmf_sdio_dev *sdiodev,
  89. u32 corebase)
  90. {
  91. u32 regdata;
  92. regdata = brcmf_sdcard_reg_read(sdiodev,
  93. CORE_SB(corebase, sbidhigh), 4);
  94. return SBCOREREV(regdata);
  95. }
  96. bool
  97. brcmf_sdio_chip_iscoreup(struct brcmf_sdio_dev *sdiodev,
  98. u32 corebase)
  99. {
  100. u32 regdata;
  101. regdata = brcmf_sdcard_reg_read(sdiodev,
  102. CORE_SB(corebase, sbtmstatelow), 4);
  103. regdata &= (SBTML_RESET | SBTML_REJ_MASK |
  104. (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
  105. return ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) == regdata);
  106. }
  107. void
  108. brcmf_sdio_chip_coredisable(struct brcmf_sdio_dev *sdiodev, u32 corebase)
  109. {
  110. u32 regdata;
  111. regdata = brcmf_sdcard_reg_read(sdiodev,
  112. CORE_SB(corebase, sbtmstatelow), 4);
  113. if (regdata & SBTML_RESET)
  114. return;
  115. regdata = brcmf_sdcard_reg_read(sdiodev,
  116. CORE_SB(corebase, sbtmstatelow), 4);
  117. if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
  118. /*
  119. * set target reject and spin until busy is clear
  120. * (preserve core-specific bits)
  121. */
  122. regdata = brcmf_sdcard_reg_read(sdiodev,
  123. CORE_SB(corebase, sbtmstatelow), 4);
  124. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
  125. 4, regdata | SBTML_REJ);
  126. regdata = brcmf_sdcard_reg_read(sdiodev,
  127. CORE_SB(corebase, sbtmstatelow), 4);
  128. udelay(1);
  129. SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
  130. CORE_SB(corebase, sbtmstatehigh), 4) &
  131. SBTMH_BUSY), 100000);
  132. regdata = brcmf_sdcard_reg_read(sdiodev,
  133. CORE_SB(corebase, sbtmstatehigh), 4);
  134. if (regdata & SBTMH_BUSY)
  135. brcmf_dbg(ERROR, "core state still busy\n");
  136. regdata = brcmf_sdcard_reg_read(sdiodev,
  137. CORE_SB(corebase, sbidlow), 4);
  138. if (regdata & SBIDL_INIT) {
  139. regdata = brcmf_sdcard_reg_read(sdiodev,
  140. CORE_SB(corebase, sbimstate), 4) |
  141. SBIM_RJ;
  142. brcmf_sdcard_reg_write(sdiodev,
  143. CORE_SB(corebase, sbimstate), 4,
  144. regdata);
  145. regdata = brcmf_sdcard_reg_read(sdiodev,
  146. CORE_SB(corebase, sbimstate), 4);
  147. udelay(1);
  148. SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
  149. CORE_SB(corebase, sbimstate), 4) &
  150. SBIM_BY), 100000);
  151. }
  152. /* set reset and reject while enabling the clocks */
  153. brcmf_sdcard_reg_write(sdiodev,
  154. CORE_SB(corebase, sbtmstatelow), 4,
  155. (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
  156. SBTML_REJ | SBTML_RESET));
  157. regdata = brcmf_sdcard_reg_read(sdiodev,
  158. CORE_SB(corebase, sbtmstatelow), 4);
  159. udelay(10);
  160. /* clear the initiator reject bit */
  161. regdata = brcmf_sdcard_reg_read(sdiodev,
  162. CORE_SB(corebase, sbidlow), 4);
  163. if (regdata & SBIDL_INIT) {
  164. regdata = brcmf_sdcard_reg_read(sdiodev,
  165. CORE_SB(corebase, sbimstate), 4) &
  166. ~SBIM_RJ;
  167. brcmf_sdcard_reg_write(sdiodev,
  168. CORE_SB(corebase, sbimstate), 4,
  169. regdata);
  170. }
  171. }
  172. /* leave reset and reject asserted */
  173. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
  174. (SBTML_REJ | SBTML_RESET));
  175. udelay(1);
  176. }
  177. void
  178. brcmf_sdio_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
  179. {
  180. u32 regdata;
  181. /*
  182. * Must do the disable sequence first to work for
  183. * arbitrary current core state.
  184. */
  185. brcmf_sdio_chip_coredisable(sdiodev, corebase);
  186. /*
  187. * Now do the initialization sequence.
  188. * set reset while enabling the clock and
  189. * forcing them on throughout the core
  190. */
  191. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
  192. ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
  193. SBTML_RESET);
  194. udelay(1);
  195. regdata = brcmf_sdcard_reg_read(sdiodev,
  196. CORE_SB(corebase, sbtmstatehigh), 4);
  197. if (regdata & SBTMH_SERR)
  198. brcmf_sdcard_reg_write(sdiodev,
  199. CORE_SB(corebase, sbtmstatehigh), 4, 0);
  200. regdata = brcmf_sdcard_reg_read(sdiodev,
  201. CORE_SB(corebase, sbimstate), 4);
  202. if (regdata & (SBIM_IBE | SBIM_TO))
  203. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
  204. regdata & ~(SBIM_IBE | SBIM_TO));
  205. /* clear reset and allow it to propagate throughout the core */
  206. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
  207. (SICF_FGC << SBTML_SICF_SHIFT) |
  208. (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
  209. udelay(1);
  210. /* leave clock enabled */
  211. brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
  212. (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
  213. udelay(1);
  214. }
  215. static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
  216. struct chip_info *ci, u32 regs)
  217. {
  218. u32 regdata;
  219. /*
  220. * Get CC core rev
  221. * Chipid is assume to be at offset 0 from regs arg
  222. * For different chiptypes or old sdio hosts w/o chipcommon,
  223. * other ways of recognition should be added here.
  224. */
  225. ci->cccorebase = regs;
  226. regdata = brcmf_sdcard_reg_read(sdiodev,
  227. CORE_CC_REG(ci->cccorebase, chipid), 4);
  228. ci->chip = regdata & CID_ID_MASK;
  229. ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
  230. brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
  231. /* Address of cores for new chips should be added here */
  232. switch (ci->chip) {
  233. case BCM4329_CHIP_ID:
  234. ci->buscorebase = BCM4329_CORE_BUS_BASE;
  235. ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
  236. ci->armcorebase = BCM4329_CORE_ARM_BASE;
  237. ci->ramsize = BCM4329_RAMSIZE;
  238. break;
  239. default:
  240. brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
  241. return -ENODEV;
  242. }
  243. return 0;
  244. }
  245. static int
  246. brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
  247. {
  248. int err = 0;
  249. u8 clkval, clkset;
  250. /* Try forcing SDIO core to do ALPAvail request only */
  251. clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
  252. brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
  253. SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
  254. if (err) {
  255. brcmf_dbg(ERROR, "error writing for HT off\n");
  256. return err;
  257. }
  258. /* If register supported, wait for ALPAvail and then force ALP */
  259. /* This may take up to 15 milliseconds */
  260. clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
  261. SBSDIO_FUNC1_CHIPCLKCSR, NULL);
  262. if ((clkval & ~SBSDIO_AVBITS) != clkset) {
  263. brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
  264. clkset, clkval);
  265. return -EACCES;
  266. }
  267. SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
  268. SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
  269. !SBSDIO_ALPAV(clkval)),
  270. PMU_MAX_TRANSITION_DLY);
  271. if (!SBSDIO_ALPAV(clkval)) {
  272. brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
  273. clkval);
  274. return -EBUSY;
  275. }
  276. clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
  277. brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
  278. SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
  279. udelay(65);
  280. /* Also, disable the extra SDIO pull-ups */
  281. brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
  282. SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
  283. return 0;
  284. }
  285. static void
  286. brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
  287. struct chip_info *ci)
  288. {
  289. u32 regdata;
  290. /* get chipcommon rev */
  291. ci->ccrev = brcmf_sdio_chip_corerev(sdiodev, ci->cccorebase);
  292. /* get chipcommon capabilites */
  293. ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
  294. CORE_CC_REG(ci->cccorebase, capabilities), 4);
  295. /* get pmu caps & rev */
  296. if (ci->cccaps & CC_CAP_PMU) {
  297. ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
  298. CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
  299. ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
  300. }
  301. ci->buscorerev = brcmf_sdio_chip_corerev(sdiodev, ci->buscorebase);
  302. regdata = brcmf_sdcard_reg_read(sdiodev,
  303. CORE_SB(ci->buscorebase, sbidhigh), 4);
  304. ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
  305. brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
  306. ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
  307. /*
  308. * Make sure any on-chip ARM is off (in case strapping is wrong),
  309. * or downloaded code was already running.
  310. */
  311. brcmf_sdio_chip_coredisable(sdiodev, ci->armcorebase);
  312. }
  313. int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
  314. struct chip_info **ci_ptr, u32 regs)
  315. {
  316. int ret;
  317. struct chip_info *ci;
  318. brcmf_dbg(TRACE, "Enter\n");
  319. /* alloc chip_info_t */
  320. ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
  321. if (!ci)
  322. return -ENOMEM;
  323. ret = brcmf_sdio_chip_buscoreprep(sdiodev);
  324. if (ret != 0)
  325. goto err;
  326. ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
  327. if (ret != 0)
  328. goto err;
  329. brcmf_sdio_chip_buscoresetup(sdiodev, ci);
  330. brcmf_sdcard_reg_write(sdiodev,
  331. CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
  332. brcmf_sdcard_reg_write(sdiodev,
  333. CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
  334. *ci_ptr = ci;
  335. return 0;
  336. err:
  337. kfree(ci);
  338. return ret;
  339. }
  340. void
  341. brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
  342. {
  343. brcmf_dbg(TRACE, "Enter\n");
  344. kfree(*ci_ptr);
  345. *ci_ptr = NULL;
  346. }
  347. static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
  348. {
  349. const char *fmt;
  350. fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
  351. snprintf(buf, len, fmt, chipid);
  352. return buf;
  353. }
  354. void
  355. brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
  356. struct chip_info *ci, u32 drivestrength)
  357. {
  358. struct sdiod_drive_str *str_tab = NULL;
  359. u32 str_mask = 0;
  360. u32 str_shift = 0;
  361. char chn[8];
  362. if (!(ci->cccaps & CC_CAP_PMU))
  363. return;
  364. switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
  365. case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
  366. str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
  367. str_mask = 0x30000000;
  368. str_shift = 28;
  369. break;
  370. case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
  371. case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
  372. str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
  373. str_mask = 0x00003800;
  374. str_shift = 11;
  375. break;
  376. case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
  377. str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
  378. str_mask = 0x00003800;
  379. str_shift = 11;
  380. break;
  381. default:
  382. brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
  383. brcmf_sdio_chip_name(ci->chip, chn, 8),
  384. ci->chiprev, ci->pmurev);
  385. break;
  386. }
  387. if (str_tab != NULL) {
  388. u32 drivestrength_sel = 0;
  389. u32 cc_data_temp;
  390. int i;
  391. for (i = 0; str_tab[i].strength != 0; i++) {
  392. if (drivestrength >= str_tab[i].strength) {
  393. drivestrength_sel = str_tab[i].sel;
  394. break;
  395. }
  396. }
  397. brcmf_sdcard_reg_write(sdiodev,
  398. CORE_CC_REG(ci->cccorebase, chipcontrol_addr),
  399. 4, 1);
  400. cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
  401. CORE_CC_REG(ci->cccorebase, chipcontrol_addr), 4);
  402. cc_data_temp &= ~str_mask;
  403. drivestrength_sel <<= str_shift;
  404. cc_data_temp |= drivestrength_sel;
  405. brcmf_sdcard_reg_write(sdiodev,
  406. CORE_CC_REG(ci->cccorebase, chipcontrol_addr),
  407. 4, cc_data_temp);
  408. brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
  409. drivestrength, cc_data_temp);
  410. }
  411. }