311-v4.16-0007-brcmfmac-Remove-brcmf_sdiod_request_data.patch 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001
  2. From: Ian Molton <[email protected]>
  3. Date: Mon, 13 Nov 2017 21:35:44 +0100
  4. Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data()
  5. This function is obfuscating how IO works on this chip. Remove it
  6. and push its logic into brcmf_sdiod_reg_{read,write}().
  7. Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway
  8. we can ignore that.
  9. Signed-off-by: Ian Molton <[email protected]>
  10. Signed-off-by: Arend van Spriel <[email protected]>
  11. Signed-off-by: Kalle Valo <[email protected]>
  12. ---
  13. .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 237 ++++++++-------------
  14. .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 2 +-
  15. 2 files changed, 87 insertions(+), 152 deletions(-)
  16. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
  17. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
  18. @@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc
  19. sdiodev->state = state;
  20. }
  21. +static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
  22. + u32 address)
  23. +{
  24. + int err = 0, i;
  25. + u32 addr;
  26. +
  27. + if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
  28. + return -ENOMEDIUM;
  29. +
  30. + addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
  31. +
  32. + for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
  33. + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
  34. + addr & 0xff, &err);
  35. +
  36. + return err;
  37. +}
  38. +
  39. +static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
  40. +{
  41. + uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
  42. + int err = 0;
  43. +
  44. + if (bar0 != sdiodev->sbwad) {
  45. + err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
  46. + if (err)
  47. + return err;
  48. +
  49. + sdiodev->sbwad = bar0;
  50. + }
  51. +
  52. + *addr &= SBSDIO_SB_OFT_ADDR_MASK;
  53. + *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
  54. +
  55. + return 0;
  56. +}
  57. +
  58. static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
  59. uint regaddr)
  60. {
  61. @@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb(
  62. return err_ret;
  63. }
  64. -static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
  65. - u32 addr, u8 regsz, void *data, bool write)
  66. -{
  67. - struct sdio_func *func;
  68. - int ret = -EINVAL;
  69. -
  70. - brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
  71. - write, fn, addr, regsz);
  72. -
  73. - /* only allow byte access on F0 */
  74. - if (WARN_ON(regsz > 1 && !fn))
  75. - return -EINVAL;
  76. - func = sdiodev->func[fn];
  77. -
  78. - switch (regsz) {
  79. - case 1:
  80. - if (write) {
  81. - if (fn)
  82. - sdio_writeb(func, *(u8 *)data, addr, &ret);
  83. - else
  84. - ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
  85. - addr);
  86. - } else {
  87. - if (fn)
  88. - *(u8 *)data = sdio_readb(func, addr, &ret);
  89. - else
  90. - *(u8 *)data = sdio_f0_readb(func, addr, &ret);
  91. - }
  92. - break;
  93. - case 2:
  94. - if (write)
  95. - sdio_writew(func, *(u16 *)data, addr, &ret);
  96. - else
  97. - *(u16 *)data = sdio_readw(func, addr, &ret);
  98. - break;
  99. - case 4:
  100. - if (write)
  101. - sdio_writel(func, *(u32 *)data, addr, &ret);
  102. - else
  103. - *(u32 *)data = sdio_readl(func, addr, &ret);
  104. - break;
  105. - default:
  106. - brcmf_err("invalid size: %d\n", regsz);
  107. - break;
  108. - }
  109. -
  110. - if (ret)
  111. - brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
  112. - write ? "write" : "read", fn, addr, ret);
  113. -
  114. - return ret;
  115. -}
  116. -
  117. static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
  118. u8 regsz, void *data)
  119. {
  120. - u8 func;
  121. - s32 retry = 0;
  122. int ret;
  123. - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
  124. - return -ENOMEDIUM;
  125. -
  126. /*
  127. * figure out how to read the register based on address range
  128. * 0x00 ~ 0x7FF: function 0 CCCR and FBR
  129. * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
  130. * The rest: function 1 silicon backplane core registers
  131. + * f0 writes must be bytewise
  132. */
  133. - if ((addr & ~REG_F0_REG_MASK) == 0)
  134. - func = SDIO_FUNC_0;
  135. - else
  136. - func = SDIO_FUNC_1;
  137. -
  138. - do {
  139. - /* for retry wait for 1 ms till bus get settled down */
  140. - if (retry)
  141. - usleep_range(1000, 2000);
  142. - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
  143. - data, true);
  144. -
  145. - } while (ret != 0 && ret != -ENOMEDIUM &&
  146. - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
  147. + if ((addr & ~REG_F0_REG_MASK) == 0) {
  148. + if (WARN_ON(regsz > 1))
  149. + return -EINVAL;
  150. + ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
  151. + *(u8 *)data, addr);
  152. + } else {
  153. + switch (regsz) {
  154. + case 1:
  155. + sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
  156. + break;
  157. + case 4:
  158. + ret = brcmf_sdiod_addrprep(sdiodev, &addr);
  159. + if (ret)
  160. + goto done;
  161. - if (ret == -ENOMEDIUM)
  162. - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
  163. + sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
  164. + break;
  165. + default:
  166. + WARN(1, "Invalid reg size\n");
  167. + ret = -EINVAL;
  168. + break;
  169. + }
  170. + }
  171. +done:
  172. return ret;
  173. }
  174. static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
  175. u8 regsz, void *data)
  176. {
  177. - u8 func;
  178. - s32 retry = 0;
  179. int ret;
  180. - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
  181. - return -ENOMEDIUM;
  182. -
  183. /*
  184. * figure out how to read the register based on address range
  185. * 0x00 ~ 0x7FF: function 0 CCCR and FBR
  186. * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
  187. * The rest: function 1 silicon backplane core registers
  188. + * f0 reads must be bytewise
  189. */
  190. - if ((addr & ~REG_F0_REG_MASK) == 0)
  191. - func = SDIO_FUNC_0;
  192. - else
  193. - func = SDIO_FUNC_1;
  194. -
  195. - do {
  196. - memset(data, 0, regsz);
  197. -
  198. - /* for retry wait for 1 ms till bus get settled down */
  199. - if (retry)
  200. - usleep_range(1000, 2000);
  201. -
  202. - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
  203. - data, false);
  204. -
  205. - } while (ret != 0 && ret != -ENOMEDIUM &&
  206. - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
  207. -
  208. - if (ret == -ENOMEDIUM)
  209. - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
  210. -
  211. - return ret;
  212. -}
  213. -
  214. -static int
  215. -brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
  216. -{
  217. - int err = 0, i;
  218. - u32 addr;
  219. -
  220. - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
  221. - return -ENOMEDIUM;
  222. -
  223. - addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
  224. -
  225. - for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
  226. - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
  227. - addr & 0xff, &err);
  228. -
  229. - return err;
  230. -}
  231. -
  232. -static int
  233. -brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
  234. -{
  235. - uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
  236. - int err = 0;
  237. -
  238. - if (bar0 != sdiodev->sbwad) {
  239. - err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
  240. - if (err)
  241. - return err;
  242. + if ((addr & ~REG_F0_REG_MASK) == 0) {
  243. + if (WARN_ON(regsz > 1))
  244. + return -EINVAL;
  245. + *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
  246. + } else {
  247. + switch (regsz) {
  248. + case 1:
  249. + *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
  250. + break;
  251. + case 4:
  252. + ret = brcmf_sdiod_addrprep(sdiodev, &addr);
  253. + if (ret)
  254. + goto done;
  255. - sdiodev->sbwad = bar0;
  256. + *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
  257. + break;
  258. + default:
  259. + WARN(1, "Invalid reg size\n");
  260. + ret = -EINVAL;
  261. + break;
  262. + }
  263. }
  264. - *addr &= SBSDIO_SB_OFT_ADDR_MASK;
  265. - *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
  266. -
  267. - return 0;
  268. +done:
  269. + return ret;
  270. }
  271. u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
  272. @@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
  273. int retval;
  274. brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
  275. - retval = brcmf_sdiod_addrprep(sdiodev, &addr);
  276. - if (retval)
  277. - goto done;
  278. -
  279. retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
  280. -
  281. brcmf_dbg(SDIO, "data:0x%08x\n", data);
  282. -done:
  283. if (ret)
  284. *ret = retval;
  285. @@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
  286. int retval;
  287. brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
  288. - retval = brcmf_sdiod_addrprep(sdiodev, &addr);
  289. - if (retval)
  290. - goto done;
  291. -
  292. retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
  293. -done:
  294. if (ret)
  295. *ret = retval;
  296. }
  297. @@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
  298. return bcmerror;
  299. }
  300. -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
  301. +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
  302. {
  303. - char t_func = (char)fn;
  304. brcmf_dbg(SDIO, "Enter\n");
  305. /* issue abort cmd52 command through F0 */
  306. - brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
  307. - 1, &t_func, true);
  308. + brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
  309. brcmf_dbg(SDIO, "Exit\n");
  310. return 0;
  311. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
  312. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
  313. @@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
  314. u8 *data, uint size);
  315. /* Issue an abort to the specified function */
  316. -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
  317. +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
  318. void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
  319. void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
  320. enum brcmf_sdiod_state state);