|
@@ -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;
|