brcmfmac: introduce unified register access interface for SDIO
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
index f971fa8bdbf4ad8019401c2c810ac4d75ab2231d..5e719d872d59501cadc74571ab260a89cd17c891 100644 (file)
@@ -233,6 +233,119 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
        return err;
 }
 
+static int
+brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
+                       void *data, bool write)
+{
+       u8 func_num, reg_size;
+       u32 bar;
+       s32 retry = 0;
+       int ret;
+
+       /*
+        * figure out how to read the register based on address range
+        * 0x00 ~ 0xFF: function 0 CCCR
+        * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
+        * The rest: function 1 silicon backplane core registers
+        */
+       if ((addr & ~REG_F0_CCCR_MASK) == 0) {
+               func_num = SDIO_FUNC_0;
+               reg_size = 1;
+       } else if ((addr & ~REG_F1_MISC_MASK) == 0) {
+               func_num = SDIO_FUNC_1;
+               reg_size = 1;
+       } else {
+               func_num = SDIO_FUNC_1;
+               reg_size = 4;
+
+               /* Set the window for SB core register */
+               bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+               if (bar != sdiodev->sbwad) {
+                       ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar);
+                       if (ret != 0) {
+                               memset(data, 0xFF, reg_size);
+                               return ret;
+                       }
+                       sdiodev->sbwad = bar;
+               }
+               addr &= SBSDIO_SB_OFT_ADDR_MASK;
+               addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+       }
+
+       do {
+               if (!write)
+                       memset(data, 0, reg_size);
+               if (retry)      /* wait for 1 ms till bus get settled down */
+                       usleep_range(1000, 2000);
+               if (reg_size == 1)
+                       ret = brcmf_sdioh_request_byte(sdiodev, write,
+                                                      func_num, addr, data);
+               else
+                       ret = brcmf_sdioh_request_word(sdiodev, write,
+                                                      func_num, addr, data, 4);
+       } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+
+       sdiodev->regfail = (ret != 0);
+       if (sdiodev->regfail)
+               brcmf_dbg(ERROR, "failed with %d\n", ret);
+
+       return ret;
+}
+
+u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+{
+       u8 data;
+       int retval;
+
+       brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       brcmf_dbg(INFO, "data:0x%02x\n", data);
+
+       if (ret)
+               *ret = retval;
+
+       return data;
+}
+
+u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+{
+       u32 data;
+       int retval;
+
+       brcmf_dbg(INFO, "addr:0x%08x\n", addr);
+       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
+       brcmf_dbg(INFO, "data:0x%08x\n", data);
+
+       if (ret)
+               *ret = retval;
+
+       return data;
+}
+
+void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
+                     u8 data, int *ret)
+{
+       int retval;
+
+       brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
+       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+
+       if (ret)
+               *ret = retval;
+}
+
+void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
+                     u32 data, int *ret)
+{
+       int retval;
+
+       brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
+       retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
+
+       if (ret)
+               *ret = retval;
+}
+
 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr)
 {
        int status;
This page took 0.025743 seconds and 5 git commands to generate.