brcmfmac: introduce unified register access interface for SDIO

Both brcmf_sdcard_cfg_read/write and brcmf_sdcard_reg_read/write
are used as interface functions for register access of SDIO WiFi
dongle. A unified interface brcmf_sdio_regr/w is introduced in
this patch in order to simplify the interface and keep the
complexity within the lower layer.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Franky Lin 2012-05-04 18:27:31 -07:00 committed by John W. Linville
parent 7d9cfc2826
commit e9b8d91d55
2 changed files with 125 additions and 0 deletions

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

View File

@ -40,6 +40,10 @@
/* Maximum number of I/O funcs */
#define SDIOD_MAX_IOFUNCS 7
/* mask of register map */
#define REG_F0_CCCR_MASK 0xFF
#define REG_F1_MISC_MASK 0x1FFFF
/* as of sdiod rev 0, supports 3 functions */
#define SBSDIO_NUM_FUNCTION 3
@ -186,6 +190,14 @@ brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr);
extern u32
brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data);
/* sdio device register access interface */
extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
u8 data, int *ret);
extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
u32 data, int *ret);
/* Indicate if last reg read/write failed */
extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev);