sdio_chip.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  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 <linux/mmc/sdio_func.h>
  21. #include <linux/mmc/sdio_ids.h>
  22. #include <linux/ssb/ssb_regs.h>
  23. #include <linux/bcma/bcma.h>
  24. #include <chipcommon.h>
  25. #include <brcm_hw_ids.h>
  26. #include <brcmu_wifi.h>
  27. #include <brcmu_utils.h>
  28. #include <soc.h>
  29. #include "dhd_dbg.h"
  30. #include "sdio_host.h"
  31. #include "sdio_chip.h"
  32. /* chip core base & ramsize */
  33. /* bcm4329 */
  34. /* SDIO device core, ID 0x829 */
  35. #define BCM4329_CORE_BUS_BASE 0x18011000
  36. /* internal memory core, ID 0x80e */
  37. #define BCM4329_CORE_SOCRAM_BASE 0x18003000
  38. /* ARM Cortex M3 core, ID 0x82a */
  39. #define BCM4329_CORE_ARM_BASE 0x18002000
  40. #define BCM4329_RAMSIZE 0x48000
  41. /* bcm43143 */
  42. /* SDIO device core */
  43. #define BCM43143_CORE_BUS_BASE 0x18002000
  44. /* internal memory core */
  45. #define BCM43143_CORE_SOCRAM_BASE 0x18004000
  46. /* ARM Cortex M3 core, ID 0x82a */
  47. #define BCM43143_CORE_ARM_BASE 0x18003000
  48. #define BCM43143_RAMSIZE 0x70000
  49. /* All D11 cores, ID 0x812 */
  50. #define BCM43xx_CORE_D11_BASE 0x18001000
  51. #define SBCOREREV(sbidh) \
  52. ((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
  53. ((sbidh) & SSB_IDHIGH_RCLO))
  54. /* SOC Interconnect types (aka chip types) */
  55. #define SOCI_SB 0
  56. #define SOCI_AI 1
  57. /* EROM CompIdentB */
  58. #define CIB_REV_MASK 0xff000000
  59. #define CIB_REV_SHIFT 24
  60. /* ARM CR4 core specific control flag bits */
  61. #define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
  62. /* D11 core specific control flag bits */
  63. #define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
  64. #define D11_BCMA_IOCTL_PHYRESET 0x0008
  65. #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
  66. /* SDIO Pad drive strength to select value mappings */
  67. struct sdiod_drive_str {
  68. u8 strength; /* Pad Drive Strength in mA */
  69. u8 sel; /* Chip-specific select value */
  70. };
  71. /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
  72. static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
  73. {32, 0x6},
  74. {26, 0x7},
  75. {22, 0x4},
  76. {16, 0x5},
  77. {12, 0x2},
  78. {8, 0x3},
  79. {4, 0x0},
  80. {0, 0x1}
  81. };
  82. /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
  83. static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
  84. {6, 0x7},
  85. {5, 0x6},
  86. {4, 0x5},
  87. {3, 0x4},
  88. {2, 0x2},
  89. {1, 0x1},
  90. {0, 0x0}
  91. };
  92. /* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
  93. static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
  94. {3, 0x3},
  95. {2, 0x2},
  96. {1, 0x1},
  97. {0, 0x0} };
  98. /* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
  99. static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
  100. {16, 0x7},
  101. {12, 0x5},
  102. {8, 0x3},
  103. {4, 0x1}
  104. };
  105. u8
  106. brcmf_sdio_chip_getinfidx(struct brcmf_chip *ci, u16 coreid)
  107. {
  108. u8 idx;
  109. for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
  110. if (coreid == ci->c_inf[idx].id)
  111. return idx;
  112. return BRCMF_MAX_CORENUM;
  113. }
  114. static u32
  115. brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
  116. struct brcmf_chip *ci, u16 coreid)
  117. {
  118. u32 regdata;
  119. u8 idx;
  120. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  121. regdata = brcmf_sdiod_regrl(sdiodev,
  122. CORE_SB(ci->c_inf[idx].base, sbidhigh),
  123. NULL);
  124. return SBCOREREV(regdata);
  125. }
  126. static u32
  127. brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
  128. struct brcmf_chip *ci, u16 coreid)
  129. {
  130. u8 idx;
  131. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  132. return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
  133. }
  134. static bool
  135. brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
  136. struct brcmf_chip *ci, u16 coreid)
  137. {
  138. u32 regdata;
  139. u8 idx;
  140. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  141. if (idx == BRCMF_MAX_CORENUM)
  142. return false;
  143. regdata = brcmf_sdiod_regrl(sdiodev,
  144. CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  145. NULL);
  146. regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
  147. SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
  148. return (SSB_TMSLOW_CLOCK == regdata);
  149. }
  150. static bool
  151. brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
  152. struct brcmf_chip *ci, u16 coreid)
  153. {
  154. u32 regdata;
  155. u8 idx;
  156. bool ret;
  157. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  158. if (idx == BRCMF_MAX_CORENUM)
  159. return false;
  160. regdata = brcmf_sdiod_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
  161. NULL);
  162. ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
  163. regdata = brcmf_sdiod_regrl(sdiodev,
  164. ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
  165. NULL);
  166. ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
  167. return ret;
  168. }
  169. static void
  170. brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
  171. struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
  172. u32 in_resetbits)
  173. {
  174. u32 regdata, base;
  175. u8 idx;
  176. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  177. base = ci->c_inf[idx].base;
  178. regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
  179. if (regdata & SSB_TMSLOW_RESET)
  180. return;
  181. regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL);
  182. if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
  183. /*
  184. * set target reject and spin until busy is clear
  185. * (preserve core-specific bits)
  186. */
  187. regdata = brcmf_sdiod_regrl(sdiodev,
  188. CORE_SB(base, sbtmstatelow), NULL);
  189. brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
  190. regdata | SSB_TMSLOW_REJECT, NULL);
  191. regdata = brcmf_sdiod_regrl(sdiodev,
  192. CORE_SB(base, sbtmstatelow), NULL);
  193. udelay(1);
  194. SPINWAIT((brcmf_sdiod_regrl(sdiodev,
  195. CORE_SB(base, sbtmstatehigh),
  196. NULL) &
  197. SSB_TMSHIGH_BUSY), 100000);
  198. regdata = brcmf_sdiod_regrl(sdiodev,
  199. CORE_SB(base, sbtmstatehigh),
  200. NULL);
  201. if (regdata & SSB_TMSHIGH_BUSY)
  202. brcmf_err("core state still busy\n");
  203. regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
  204. NULL);
  205. if (regdata & SSB_IDLOW_INITIATOR) {
  206. regdata = brcmf_sdiod_regrl(sdiodev,
  207. CORE_SB(base, sbimstate),
  208. NULL);
  209. regdata |= SSB_IMSTATE_REJECT;
  210. brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
  211. regdata, NULL);
  212. regdata = brcmf_sdiod_regrl(sdiodev,
  213. CORE_SB(base, sbimstate),
  214. NULL);
  215. udelay(1);
  216. SPINWAIT((brcmf_sdiod_regrl(sdiodev,
  217. CORE_SB(base, sbimstate),
  218. NULL) &
  219. SSB_IMSTATE_BUSY), 100000);
  220. }
  221. /* set reset and reject while enabling the clocks */
  222. regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
  223. SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
  224. brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
  225. regdata, NULL);
  226. regdata = brcmf_sdiod_regrl(sdiodev,
  227. CORE_SB(base, sbtmstatelow), NULL);
  228. udelay(10);
  229. /* clear the initiator reject bit */
  230. regdata = brcmf_sdiod_regrl(sdiodev, CORE_SB(base, sbidlow),
  231. NULL);
  232. if (regdata & SSB_IDLOW_INITIATOR) {
  233. regdata = brcmf_sdiod_regrl(sdiodev,
  234. CORE_SB(base, sbimstate),
  235. NULL);
  236. regdata &= ~SSB_IMSTATE_REJECT;
  237. brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbimstate),
  238. regdata, NULL);
  239. }
  240. }
  241. /* leave reset and reject asserted */
  242. brcmf_sdiod_regwl(sdiodev, CORE_SB(base, sbtmstatelow),
  243. (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL);
  244. udelay(1);
  245. }
  246. static void
  247. brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
  248. struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
  249. u32 in_resetbits)
  250. {
  251. u8 idx;
  252. u32 regdata;
  253. u32 wrapbase;
  254. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  255. if (idx == BRCMF_MAX_CORENUM)
  256. return;
  257. wrapbase = ci->c_inf[idx].wrapbase;
  258. /* if core is already in reset, just return */
  259. regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL);
  260. if ((regdata & BCMA_RESET_CTL_RESET) != 0)
  261. return;
  262. /* configure reset */
  263. brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
  264. BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
  265. regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
  266. /* put in reset */
  267. brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL,
  268. BCMA_RESET_CTL_RESET, NULL);
  269. usleep_range(10, 20);
  270. /* wait till reset is 1 */
  271. SPINWAIT(brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) !=
  272. BCMA_RESET_CTL_RESET, 300);
  273. /* post reset configure */
  274. brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, pre_resetbits |
  275. BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
  276. regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
  277. }
  278. static void
  279. brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
  280. struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
  281. u32 in_resetbits, u32 post_resetbits)
  282. {
  283. u32 regdata;
  284. u8 idx;
  285. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  286. if (idx == BRCMF_MAX_CORENUM)
  287. return;
  288. /*
  289. * Must do the disable sequence first to work for
  290. * arbitrary current core state.
  291. */
  292. brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, pre_resetbits,
  293. in_resetbits);
  294. /*
  295. * Now do the initialization sequence.
  296. * set reset while enabling the clock and
  297. * forcing them on throughout the core
  298. */
  299. brcmf_sdiod_regwl(sdiodev,
  300. CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  301. SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET,
  302. NULL);
  303. regdata = brcmf_sdiod_regrl(sdiodev,
  304. CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  305. NULL);
  306. udelay(1);
  307. /* clear any serror */
  308. regdata = brcmf_sdiod_regrl(sdiodev,
  309. CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
  310. NULL);
  311. if (regdata & SSB_TMSHIGH_SERR)
  312. brcmf_sdiod_regwl(sdiodev,
  313. CORE_SB(ci->c_inf[idx].base, sbtmstatehigh),
  314. 0, NULL);
  315. regdata = brcmf_sdiod_regrl(sdiodev,
  316. CORE_SB(ci->c_inf[idx].base, sbimstate),
  317. NULL);
  318. if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
  319. brcmf_sdiod_regwl(sdiodev,
  320. CORE_SB(ci->c_inf[idx].base, sbimstate),
  321. regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO),
  322. NULL);
  323. /* clear reset and allow it to propagate throughout the core */
  324. brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  325. SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL);
  326. regdata = brcmf_sdiod_regrl(sdiodev,
  327. CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  328. NULL);
  329. udelay(1);
  330. /* leave clock enabled */
  331. brcmf_sdiod_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  332. SSB_TMSLOW_CLOCK, NULL);
  333. regdata = brcmf_sdiod_regrl(sdiodev,
  334. CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
  335. NULL);
  336. udelay(1);
  337. }
  338. static void
  339. brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
  340. struct brcmf_chip *ci, u16 coreid, u32 pre_resetbits,
  341. u32 in_resetbits, u32 post_resetbits)
  342. {
  343. u8 idx;
  344. u32 regdata;
  345. u32 wrapbase;
  346. idx = brcmf_sdio_chip_getinfidx(ci, coreid);
  347. if (idx == BRCMF_MAX_CORENUM)
  348. return;
  349. wrapbase = ci->c_inf[idx].wrapbase;
  350. /* must disable first to work for arbitrary current core state */
  351. brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, pre_resetbits,
  352. in_resetbits);
  353. while (brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_RESET_CTL, NULL) &
  354. BCMA_RESET_CTL_RESET) {
  355. brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_RESET_CTL, 0, NULL);
  356. usleep_range(40, 60);
  357. }
  358. brcmf_sdiod_regwl(sdiodev, wrapbase + BCMA_IOCTL, post_resetbits |
  359. BCMA_IOCTL_CLK, NULL);
  360. regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
  361. }
  362. #ifdef DEBUG
  363. /* safety check for chipinfo */
  364. static int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
  365. {
  366. u8 core_idx;
  367. /* check RAM core presence for ARM CM3 core */
  368. core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
  369. if (BRCMF_MAX_CORENUM != core_idx) {
  370. core_idx = brcmf_sdio_chip_getinfidx(ci,
  371. BCMA_CORE_INTERNAL_MEM);
  372. if (BRCMF_MAX_CORENUM == core_idx) {
  373. brcmf_err("RAM core not provided with ARM CM3 core\n");
  374. return -ENODEV;
  375. }
  376. }
  377. /* check RAM base for ARM CR4 core */
  378. core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
  379. if (BRCMF_MAX_CORENUM != core_idx) {
  380. if (ci->rambase == 0) {
  381. brcmf_err("RAM base not provided with ARM CR4 core\n");
  382. return -ENOMEM;
  383. }
  384. }
  385. return 0;
  386. }
  387. #else /* DEBUG */
  388. static inline int brcmf_sdio_chip_cichk(struct brcmf_chip *ci)
  389. {
  390. return 0;
  391. }
  392. #endif
  393. static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
  394. struct brcmf_chip *ci)
  395. {
  396. u32 regdata;
  397. u32 socitype;
  398. /* Get CC core rev
  399. * Chipid is assume to be at offset 0 from SI_ENUM_BASE
  400. * For different chiptypes or old sdio hosts w/o chipcommon,
  401. * other ways of recognition should be added here.
  402. */
  403. regdata = brcmf_sdiod_regrl(sdiodev,
  404. CORE_CC_REG(SI_ENUM_BASE, chipid),
  405. NULL);
  406. ci->chip = regdata & CID_ID_MASK;
  407. ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
  408. if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
  409. ci->chiprev >= 2)
  410. ci->chip = BCM4339_CHIP_ID;
  411. socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
  412. brcmf_dbg(INFO, "found %s chip: id=0x%x, rev=%d\n",
  413. socitype == SOCI_SB ? "SB" : "AXI", ci->chip, ci->chiprev);
  414. if (socitype == SOCI_SB) {
  415. if (ci->chip != BCM4329_CHIP_ID) {
  416. brcmf_err("SB chip is not supported\n");
  417. return -ENODEV;
  418. }
  419. ci->iscoreup = brcmf_sdio_sb_iscoreup;
  420. ci->corerev = brcmf_sdio_sb_corerev;
  421. ci->coredisable = brcmf_sdio_sb_coredisable;
  422. ci->resetcore = brcmf_sdio_sb_resetcore;
  423. ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
  424. ci->c_inf[0].base = SI_ENUM_BASE;
  425. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  426. ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
  427. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  428. ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
  429. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  430. ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
  431. ci->c_inf[4].id = BCMA_CORE_80211;
  432. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  433. ci->ramsize = BCM4329_RAMSIZE;
  434. } else if (socitype == SOCI_AI) {
  435. ci->iscoreup = brcmf_sdio_ai_iscoreup;
  436. ci->corerev = brcmf_sdio_ai_corerev;
  437. ci->coredisable = brcmf_sdio_ai_coredisable;
  438. ci->resetcore = brcmf_sdio_ai_resetcore;
  439. ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
  440. ci->c_inf[0].base = SI_ENUM_BASE;
  441. /* Address of cores for new chips should be added here */
  442. switch (ci->chip) {
  443. case BCM43143_CHIP_ID:
  444. ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
  445. ci->c_inf[0].cib = 0x2b000000;
  446. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  447. ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
  448. ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
  449. ci->c_inf[1].cib = 0x18000000;
  450. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  451. ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
  452. ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
  453. ci->c_inf[2].cib = 0x14000000;
  454. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  455. ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
  456. ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
  457. ci->c_inf[3].cib = 0x07000000;
  458. ci->c_inf[4].id = BCMA_CORE_80211;
  459. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  460. ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
  461. ci->ramsize = BCM43143_RAMSIZE;
  462. break;
  463. case BCM43241_CHIP_ID:
  464. ci->c_inf[0].wrapbase = 0x18100000;
  465. ci->c_inf[0].cib = 0x2a084411;
  466. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  467. ci->c_inf[1].base = 0x18002000;
  468. ci->c_inf[1].wrapbase = 0x18102000;
  469. ci->c_inf[1].cib = 0x0e004211;
  470. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  471. ci->c_inf[2].base = 0x18004000;
  472. ci->c_inf[2].wrapbase = 0x18104000;
  473. ci->c_inf[2].cib = 0x14080401;
  474. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  475. ci->c_inf[3].base = 0x18003000;
  476. ci->c_inf[3].wrapbase = 0x18103000;
  477. ci->c_inf[3].cib = 0x07004211;
  478. ci->c_inf[4].id = BCMA_CORE_80211;
  479. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  480. ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
  481. ci->ramsize = 0x90000;
  482. break;
  483. case BCM4330_CHIP_ID:
  484. ci->c_inf[0].wrapbase = 0x18100000;
  485. ci->c_inf[0].cib = 0x27004211;
  486. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  487. ci->c_inf[1].base = 0x18002000;
  488. ci->c_inf[1].wrapbase = 0x18102000;
  489. ci->c_inf[1].cib = 0x07004211;
  490. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  491. ci->c_inf[2].base = 0x18004000;
  492. ci->c_inf[2].wrapbase = 0x18104000;
  493. ci->c_inf[2].cib = 0x0d080401;
  494. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  495. ci->c_inf[3].base = 0x18003000;
  496. ci->c_inf[3].wrapbase = 0x18103000;
  497. ci->c_inf[3].cib = 0x03004211;
  498. ci->c_inf[4].id = BCMA_CORE_80211;
  499. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  500. ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
  501. ci->ramsize = 0x48000;
  502. break;
  503. case BCM4334_CHIP_ID:
  504. ci->c_inf[0].wrapbase = 0x18100000;
  505. ci->c_inf[0].cib = 0x29004211;
  506. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  507. ci->c_inf[1].base = 0x18002000;
  508. ci->c_inf[1].wrapbase = 0x18102000;
  509. ci->c_inf[1].cib = 0x0d004211;
  510. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  511. ci->c_inf[2].base = 0x18004000;
  512. ci->c_inf[2].wrapbase = 0x18104000;
  513. ci->c_inf[2].cib = 0x13080401;
  514. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  515. ci->c_inf[3].base = 0x18003000;
  516. ci->c_inf[3].wrapbase = 0x18103000;
  517. ci->c_inf[3].cib = 0x07004211;
  518. ci->c_inf[4].id = BCMA_CORE_80211;
  519. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  520. ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
  521. ci->ramsize = 0x80000;
  522. break;
  523. case BCM4335_CHIP_ID:
  524. ci->c_inf[0].wrapbase = 0x18100000;
  525. ci->c_inf[0].cib = 0x2b084411;
  526. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  527. ci->c_inf[1].base = 0x18005000;
  528. ci->c_inf[1].wrapbase = 0x18105000;
  529. ci->c_inf[1].cib = 0x0f004211;
  530. ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
  531. ci->c_inf[2].base = 0x18002000;
  532. ci->c_inf[2].wrapbase = 0x18102000;
  533. ci->c_inf[2].cib = 0x01084411;
  534. ci->c_inf[3].id = BCMA_CORE_80211;
  535. ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
  536. ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
  537. ci->ramsize = 0xc0000;
  538. ci->rambase = 0x180000;
  539. break;
  540. case BCM43362_CHIP_ID:
  541. ci->c_inf[0].wrapbase = 0x18100000;
  542. ci->c_inf[0].cib = 0x27004211;
  543. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  544. ci->c_inf[1].base = 0x18002000;
  545. ci->c_inf[1].wrapbase = 0x18102000;
  546. ci->c_inf[1].cib = 0x0a004211;
  547. ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
  548. ci->c_inf[2].base = 0x18004000;
  549. ci->c_inf[2].wrapbase = 0x18104000;
  550. ci->c_inf[2].cib = 0x08080401;
  551. ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
  552. ci->c_inf[3].base = 0x18003000;
  553. ci->c_inf[3].wrapbase = 0x18103000;
  554. ci->c_inf[3].cib = 0x03004211;
  555. ci->c_inf[4].id = BCMA_CORE_80211;
  556. ci->c_inf[4].base = BCM43xx_CORE_D11_BASE;
  557. ci->c_inf[4].wrapbase = ci->c_inf[4].base + 0x00100000;
  558. ci->ramsize = 0x3C000;
  559. break;
  560. case BCM4339_CHIP_ID:
  561. ci->c_inf[0].wrapbase = 0x18100000;
  562. ci->c_inf[0].cib = 0x2e084411;
  563. ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
  564. ci->c_inf[1].base = 0x18005000;
  565. ci->c_inf[1].wrapbase = 0x18105000;
  566. ci->c_inf[1].cib = 0x15004211;
  567. ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
  568. ci->c_inf[2].base = 0x18002000;
  569. ci->c_inf[2].wrapbase = 0x18102000;
  570. ci->c_inf[2].cib = 0x04084411;
  571. ci->c_inf[3].id = BCMA_CORE_80211;
  572. ci->c_inf[3].base = BCM43xx_CORE_D11_BASE;
  573. ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
  574. ci->ramsize = 0xc0000;
  575. ci->rambase = 0x180000;
  576. break;
  577. default:
  578. brcmf_err("AXI chip is not supported\n");
  579. return -ENODEV;
  580. }
  581. } else {
  582. brcmf_err("chip backplane type %u is not supported\n",
  583. socitype);
  584. return -ENODEV;
  585. }
  586. return brcmf_sdio_chip_cichk(ci);
  587. }
  588. static int
  589. brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
  590. {
  591. int err = 0;
  592. u8 clkval, clkset;
  593. /* Try forcing SDIO core to do ALPAvail request only */
  594. clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
  595. brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
  596. if (err) {
  597. brcmf_err("error writing for HT off\n");
  598. return err;
  599. }
  600. /* If register supported, wait for ALPAvail and then force ALP */
  601. /* This may take up to 15 milliseconds */
  602. clkval = brcmf_sdiod_regrb(sdiodev,
  603. SBSDIO_FUNC1_CHIPCLKCSR, NULL);
  604. if ((clkval & ~SBSDIO_AVBITS) != clkset) {
  605. brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
  606. clkset, clkval);
  607. return -EACCES;
  608. }
  609. SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
  610. SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
  611. !SBSDIO_ALPAV(clkval)),
  612. PMU_MAX_TRANSITION_DLY);
  613. if (!SBSDIO_ALPAV(clkval)) {
  614. brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
  615. clkval);
  616. return -EBUSY;
  617. }
  618. clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
  619. brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
  620. udelay(65);
  621. /* Also, disable the extra SDIO pull-ups */
  622. brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
  623. return 0;
  624. }
  625. static void
  626. brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
  627. struct brcmf_chip *ci)
  628. {
  629. u32 base = ci->c_inf[0].base;
  630. /* get chipcommon rev */
  631. ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
  632. /* get chipcommon capabilites */
  633. ci->c_inf[0].caps = brcmf_sdiod_regrl(sdiodev,
  634. CORE_CC_REG(base, capabilities),
  635. NULL);
  636. /* get pmu caps & rev */
  637. if (ci->c_inf[0].caps & CC_CAP_PMU) {
  638. ci->pmucaps =
  639. brcmf_sdiod_regrl(sdiodev,
  640. CORE_CC_REG(base, pmucapabilities),
  641. NULL);
  642. ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
  643. }
  644. ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
  645. brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
  646. ci->c_inf[0].rev, ci->pmurev,
  647. ci->c_inf[1].rev, ci->c_inf[1].id);
  648. /*
  649. * Make sure any on-chip ARM is off (in case strapping is wrong),
  650. * or downloaded code was already running.
  651. */
  652. ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
  653. }
  654. int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
  655. struct brcmf_chip **ci_ptr)
  656. {
  657. int ret;
  658. struct brcmf_chip *ci;
  659. brcmf_dbg(TRACE, "Enter\n");
  660. ci = kzalloc(sizeof(*ci), GFP_ATOMIC);
  661. if (!ci)
  662. return -ENOMEM;
  663. ret = brcmf_sdio_chip_buscoreprep(sdiodev);
  664. if (ret != 0)
  665. goto err;
  666. ret = brcmf_sdio_chip_recognition(sdiodev, ci);
  667. if (ret != 0)
  668. goto err;
  669. brcmf_sdio_chip_buscoresetup(sdiodev, ci);
  670. brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup),
  671. 0, NULL);
  672. brcmf_sdiod_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown),
  673. 0, NULL);
  674. *ci_ptr = ci;
  675. return 0;
  676. err:
  677. kfree(ci);
  678. return ret;
  679. }
  680. void
  681. brcmf_sdio_chip_detach(struct brcmf_chip **ci_ptr)
  682. {
  683. brcmf_dbg(TRACE, "Enter\n");
  684. kfree(*ci_ptr);
  685. *ci_ptr = NULL;
  686. }
  687. static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
  688. {
  689. const char *fmt;
  690. fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
  691. snprintf(buf, len, fmt, chipid);
  692. return buf;
  693. }
  694. void
  695. brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
  696. struct brcmf_chip *ci, u32 drivestrength)
  697. {
  698. const struct sdiod_drive_str *str_tab = NULL;
  699. u32 str_mask;
  700. u32 str_shift;
  701. char chn[8];
  702. u32 base = ci->c_inf[0].base;
  703. u32 i;
  704. u32 drivestrength_sel = 0;
  705. u32 cc_data_temp;
  706. u32 addr;
  707. if (!(ci->c_inf[0].caps & CC_CAP_PMU))
  708. return;
  709. switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
  710. case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
  711. str_tab = sdiod_drvstr_tab1_1v8;
  712. str_mask = 0x00003800;
  713. str_shift = 11;
  714. break;
  715. case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
  716. str_tab = sdiod_drvstr_tab6_1v8;
  717. str_mask = 0x00001800;
  718. str_shift = 11;
  719. break;
  720. case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
  721. /* note: 43143 does not support tristate */
  722. i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
  723. if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
  724. str_tab = sdiod_drvstr_tab2_3v3;
  725. str_mask = 0x00000007;
  726. str_shift = 0;
  727. } else
  728. brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
  729. brcmf_sdio_chip_name(ci->chip, chn, 8),
  730. drivestrength);
  731. break;
  732. case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
  733. str_tab = sdiod_drive_strength_tab5_1v8;
  734. str_mask = 0x00003800;
  735. str_shift = 11;
  736. break;
  737. default:
  738. brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
  739. brcmf_sdio_chip_name(ci->chip, chn, 8),
  740. ci->chiprev, ci->pmurev);
  741. break;
  742. }
  743. if (str_tab != NULL) {
  744. for (i = 0; str_tab[i].strength != 0; i++) {
  745. if (drivestrength >= str_tab[i].strength) {
  746. drivestrength_sel = str_tab[i].sel;
  747. break;
  748. }
  749. }
  750. addr = CORE_CC_REG(base, chipcontrol_addr);
  751. brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
  752. cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
  753. cc_data_temp &= ~str_mask;
  754. drivestrength_sel <<= str_shift;
  755. cc_data_temp |= drivestrength_sel;
  756. brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
  757. brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
  758. str_tab[i].strength, drivestrength, cc_data_temp);
  759. }
  760. }
  761. static void
  762. brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
  763. struct brcmf_chip *ci)
  764. {
  765. ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0);
  766. ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
  767. D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
  768. D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
  769. ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0, 0, 0);
  770. }
  771. static bool brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev,
  772. struct brcmf_chip *ci)
  773. {
  774. u8 core_idx;
  775. u32 reg_addr;
  776. if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
  777. brcmf_err("SOCRAM core is down after reset?\n");
  778. return false;
  779. }
  780. /* clear all interrupts */
  781. core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
  782. reg_addr = ci->c_inf[core_idx].base;
  783. reg_addr += offsetof(struct sdpcmd_regs, intstatus);
  784. brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
  785. ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0, 0, 0);
  786. return true;
  787. }
  788. static inline void
  789. brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
  790. struct brcmf_chip *ci)
  791. {
  792. u8 idx;
  793. u32 regdata;
  794. u32 wrapbase;
  795. idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
  796. if (idx == BRCMF_MAX_CORENUM)
  797. return;
  798. wrapbase = ci->c_inf[idx].wrapbase;
  799. regdata = brcmf_sdiod_regrl(sdiodev, wrapbase + BCMA_IOCTL, NULL);
  800. regdata &= ARMCR4_BCMA_IOCTL_CPUHALT;
  801. ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, regdata,
  802. ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT);
  803. ci->resetcore(sdiodev, ci, BCMA_CORE_80211,
  804. D11_BCMA_IOCTL_PHYRESET | D11_BCMA_IOCTL_PHYCLOCKEN,
  805. D11_BCMA_IOCTL_PHYCLOCKEN, D11_BCMA_IOCTL_PHYCLOCKEN);
  806. }
  807. static bool brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev,
  808. struct brcmf_chip *ci, u32 rstvec)
  809. {
  810. u8 core_idx;
  811. u32 reg_addr;
  812. /* clear all interrupts */
  813. core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
  814. reg_addr = ci->c_inf[core_idx].base;
  815. reg_addr += offsetof(struct sdpcmd_regs, intstatus);
  816. brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
  817. /* Write reset vector to address 0 */
  818. brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
  819. sizeof(rstvec));
  820. /* restore ARM */
  821. ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, ARMCR4_BCMA_IOCTL_CPUHALT,
  822. 0, 0);
  823. return true;
  824. }
  825. void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
  826. struct brcmf_chip *ci)
  827. {
  828. u8 arm_core_idx;
  829. arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
  830. if (BRCMF_MAX_CORENUM != arm_core_idx) {
  831. brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
  832. return;
  833. }
  834. brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
  835. }
  836. bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
  837. struct brcmf_chip *ci, u32 rstvec)
  838. {
  839. u8 arm_core_idx;
  840. arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
  841. if (BRCMF_MAX_CORENUM != arm_core_idx)
  842. return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci);
  843. return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, rstvec);
  844. }