123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001
- From: Ian Molton <[email protected]>
- Date: Mon, 13 Nov 2017 21:35:44 +0100
- Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data()
- This function is obfuscating how IO works on this chip. Remove it
- and push its logic into brcmf_sdiod_reg_{read,write}().
- Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway
- we can ignore that.
- Signed-off-by: Ian Molton <[email protected]>
- Signed-off-by: Arend van Spriel <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- ---
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 237 ++++++++-------------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 2 +-
- 2 files changed, 87 insertions(+), 152 deletions(-)
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
- @@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc
- sdiodev->state = state;
- }
-
- +static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
- + u32 address)
- +{
- + int err = 0, i;
- + u32 addr;
- +
- + if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- + return -ENOMEDIUM;
- +
- + addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
- +
- + for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
- + brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
- + addr & 0xff, &err);
- +
- + return err;
- +}
- +
- +static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
- +{
- + uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- + int err = 0;
- +
- + if (bar0 != sdiodev->sbwad) {
- + err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
- + if (err)
- + return err;
- +
- + sdiodev->sbwad = bar0;
- + }
- +
- + *addr &= SBSDIO_SB_OFT_ADDR_MASK;
- + *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- +
- + return 0;
- +}
- +
- static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
- uint regaddr)
- {
- @@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb(
- return err_ret;
- }
-
- -static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
- - u32 addr, u8 regsz, void *data, bool write)
- -{
- - struct sdio_func *func;
- - int ret = -EINVAL;
- -
- - brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
- - write, fn, addr, regsz);
- -
- - /* only allow byte access on F0 */
- - if (WARN_ON(regsz > 1 && !fn))
- - return -EINVAL;
- - func = sdiodev->func[fn];
- -
- - switch (regsz) {
- - case 1:
- - if (write) {
- - if (fn)
- - sdio_writeb(func, *(u8 *)data, addr, &ret);
- - else
- - ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
- - addr);
- - } else {
- - if (fn)
- - *(u8 *)data = sdio_readb(func, addr, &ret);
- - else
- - *(u8 *)data = sdio_f0_readb(func, addr, &ret);
- - }
- - break;
- - case 2:
- - if (write)
- - sdio_writew(func, *(u16 *)data, addr, &ret);
- - else
- - *(u16 *)data = sdio_readw(func, addr, &ret);
- - break;
- - case 4:
- - if (write)
- - sdio_writel(func, *(u32 *)data, addr, &ret);
- - else
- - *(u32 *)data = sdio_readl(func, addr, &ret);
- - break;
- - default:
- - brcmf_err("invalid size: %d\n", regsz);
- - break;
- - }
- -
- - if (ret)
- - brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
- - write ? "write" : "read", fn, addr, ret);
- -
- - return ret;
- -}
- -
- static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
- {
- - u8 func;
- - s32 retry = 0;
- int ret;
-
- - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- - return -ENOMEDIUM;
- -
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
- + * f0 writes must be bytewise
- */
- - if ((addr & ~REG_F0_REG_MASK) == 0)
- - func = SDIO_FUNC_0;
- - else
- - func = SDIO_FUNC_1;
- -
- - do {
- - /* for retry wait for 1 ms till bus get settled down */
- - if (retry)
- - usleep_range(1000, 2000);
-
- - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- - data, true);
- -
- - } while (ret != 0 && ret != -ENOMEDIUM &&
- - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
- + if ((addr & ~REG_F0_REG_MASK) == 0) {
- + if (WARN_ON(regsz > 1))
- + return -EINVAL;
- + ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
- + *(u8 *)data, addr);
- + } else {
- + switch (regsz) {
- + case 1:
- + sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
- + break;
- + case 4:
- + ret = brcmf_sdiod_addrprep(sdiodev, &addr);
- + if (ret)
- + goto done;
-
- - if (ret == -ENOMEDIUM)
- - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
- + sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
- + break;
- + default:
- + WARN(1, "Invalid reg size\n");
- + ret = -EINVAL;
- + break;
- + }
- + }
-
- +done:
- return ret;
- }
-
- static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
- {
- - u8 func;
- - s32 retry = 0;
- int ret;
-
- - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- - return -ENOMEDIUM;
- -
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
- + * f0 reads must be bytewise
- */
- - if ((addr & ~REG_F0_REG_MASK) == 0)
- - func = SDIO_FUNC_0;
- - else
- - func = SDIO_FUNC_1;
- -
- - do {
- - memset(data, 0, regsz);
- -
- - /* for retry wait for 1 ms till bus get settled down */
- - if (retry)
- - usleep_range(1000, 2000);
- -
- - ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
- - data, false);
- -
- - } while (ret != 0 && ret != -ENOMEDIUM &&
- - retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
- -
- - if (ret == -ENOMEDIUM)
- - brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
- -
- - return ret;
- -}
- -
- -static int
- -brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
- -{
- - int err = 0, i;
- - u32 addr;
- -
- - if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- - return -ENOMEDIUM;
- -
- - addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
- -
- - for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
- - brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
- - addr & 0xff, &err);
- -
- - return err;
- -}
- -
- -static int
- -brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
- -{
- - uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- - int err = 0;
- -
- - if (bar0 != sdiodev->sbwad) {
- - err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
- - if (err)
- - return err;
- + if ((addr & ~REG_F0_REG_MASK) == 0) {
- + if (WARN_ON(regsz > 1))
- + return -EINVAL;
- + *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
- + } else {
- + switch (regsz) {
- + case 1:
- + *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
- + break;
- + case 4:
- + ret = brcmf_sdiod_addrprep(sdiodev, &addr);
- + if (ret)
- + goto done;
-
- - sdiodev->sbwad = bar0;
- + *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
- + break;
- + default:
- + WARN(1, "Invalid reg size\n");
- + ret = -EINVAL;
- + break;
- + }
- }
-
- - *addr &= SBSDIO_SB_OFT_ADDR_MASK;
- - *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
- -
- - return 0;
- +done:
- + return ret;
- }
-
- u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
- @@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- - retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- - if (retval)
- - goto done;
- -
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
- -
- brcmf_dbg(SDIO, "data:0x%08x\n", data);
-
- -done:
- if (ret)
- *ret = retval;
-
- @@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
- - retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- - if (retval)
- - goto done;
- -
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-
- -done:
- if (ret)
- *ret = retval;
- }
- @@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- return bcmerror;
- }
-
- -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
- +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
- {
- - char t_func = (char)fn;
- brcmf_dbg(SDIO, "Enter\n");
-
- /* issue abort cmd52 command through F0 */
- - brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
- - 1, &t_func, true);
- + brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
-
- brcmf_dbg(SDIO, "Exit\n");
- return 0;
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
- @@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
- u8 *data, uint size);
-
- /* Issue an abort to the specified function */
- -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
- +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
- void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
- void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
- enum brcmf_sdiod_state state);
|