diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-11 12:17:51 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-13 12:34:29 +0200 |
commit | c71114959dc952a509822f22251d01004b3b94cc (patch) | |
tree | 704414e7921140cb2506e2525da0b9caf31e10fd /drivers/net/wireless/ath | |
parent | 1f4c894d3a35e88331c01e681d033a2000c3667b (diff) | |
download | blackbird-op-linux-c71114959dc952a509822f22251d01004b3b94cc.tar.gz blackbird-op-linux-c71114959dc952a509822f22251d01004b3b94cc.zip |
ath6kl: move diag commands to hif driver
This is preparation for USB support which will have different diag
commands.
Based on code by Kevin Fang.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/hif-ops.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/hif.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 76 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 100 |
4 files changed, 126 insertions, 72 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h index 0c4c602464b7..2fe1dadfc77a 100644 --- a/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h @@ -91,6 +91,26 @@ static inline int ath6kl_hif_suspend(struct ath6kl *ar, return ar->hif_ops->suspend(ar, wow); } +/* + * Read from the ATH6KL through its diagnostic window. No cooperation from + * the Target is required for this. + */ +static inline int ath6kl_hif_diag_read32(struct ath6kl *ar, u32 address, + u32 *value) +{ + return ar->hif_ops->diag_read32(ar, address, value); +} + +/* + * Write to the ATH6KL through its diagnostic window. No cooperation from + * the Target is required for this. + */ +static inline int ath6kl_hif_diag_write32(struct ath6kl *ar, u32 address, + __le32 value) +{ + return ar->hif_ops->diag_write32(ar, address, value); +} + static inline int ath6kl_hif_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) { return ar->hif_ops->bmi_read(ar, buf, len); diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h index 42004e9069b6..15b5d98c7dc4 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.h +++ b/drivers/net/wireless/ath/ath6kl/hif.h @@ -244,6 +244,8 @@ struct ath6kl_hif_ops { void (*cleanup_scatter)(struct ath6kl *ar); int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow); int (*resume)(struct ath6kl *ar); + int (*diag_read32)(struct ath6kl *ar, u32 address, u32 *value); + int (*diag_write32)(struct ath6kl *ar, u32 address, __le32 value); int (*bmi_read)(struct ath6kl *ar, u8 *buf, u32 len); int (*bmi_write)(struct ath6kl *ar, u8 *buf, u32 len); int (*power_on)(struct ath6kl *ar); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 1195f9408857..ea848944fdc4 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -175,64 +175,6 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie) ar->cookie_count++; } -/* set the window address register (using 4-byte register access ). */ -static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) -{ - int status; - s32 i; - __le32 addr_val; - - /* - * Write bytes 1,2,3 of the register to set the upper address bytes, - * the LSB is written last to initiate the access cycle - */ - - for (i = 1; i <= 3; i++) { - /* - * Fill the buffer with the address byte value we want to - * hit 4 times. No need to worry about endianness as the - * same byte is copied to all four bytes of addr_val at - * any time. - */ - memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4); - - /* - * Hit each byte of the register address with a 4-byte - * write operation to the same address, this is a harmless - * operation. - */ - status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val, - 4, HIF_WR_SYNC_BYTE_FIX); - if (status) - break; - } - - if (status) { - ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n", - addr, reg_addr); - return status; - } - - /* - * Write the address register again, this time write the whole - * 4-byte value. The effect here is that the LSB write causes the - * cycle to start, the extra 3 byte write to bytes 1,2,3 has no - * effect since we are writing the same values again - */ - addr_val = cpu_to_le32(addr); - status = hif_read_write_sync(ar, reg_addr, - (u8 *)&(addr_val), - 4, HIF_WR_SYNC_BYTE_INC); - - if (status) { - ath6kl_err("failed to write 0x%x to window reg: 0x%X\n", - addr, reg_addr); - return status; - } - - return 0; -} - /* * Read from the hardware through its diagnostic window. No cooperation * from the firmware is required for this. @@ -241,14 +183,7 @@ int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value) { int ret; - /* set window register to start read cycle */ - ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address); - if (ret) - return ret; - - /* read the data */ - ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value, - sizeof(*value), HIF_RD_SYNC_BYTE_INC); + ret = ath6kl_hif_diag_read32(ar, address, value); if (ret) { ath6kl_warn("failed to read32 through diagnose window: %d\n", ret); @@ -266,18 +201,15 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) { int ret; - /* set write data */ - ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value, - sizeof(value), HIF_WR_SYNC_BYTE_INC); + ret = ath6kl_hif_diag_write32(ar, address, value); + if (ret) { ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", address, value); return ret; } - /* set window register, which starts the write cycle */ - return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, - address); + return 0; } int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 46a9bd66b94c..b633c8026cf5 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -845,6 +845,104 @@ static int ath6kl_sdio_resume(struct ath6kl *ar) return 0; } +/* set the window address register (using 4-byte register access ). */ +static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) +{ + int status; + u8 addr_val[4]; + s32 i; + + /* + * Write bytes 1,2,3 of the register to set the upper address bytes, + * the LSB is written last to initiate the access cycle + */ + + for (i = 1; i <= 3; i++) { + /* + * Fill the buffer with the address byte value we want to + * hit 4 times. + */ + memset(addr_val, ((u8 *)&addr)[i], 4); + + /* + * Hit each byte of the register address with a 4-byte + * write operation to the same address, this is a harmless + * operation. + */ + status = ath6kl_sdio_read_write_sync(ar, reg_addr + i, addr_val, + 4, HIF_WR_SYNC_BYTE_FIX); + if (status) + break; + } + + if (status) { + ath6kl_err("%s: failed to write initial bytes of 0x%x " + "to window reg: 0x%X\n", __func__, + addr, reg_addr); + return status; + } + + /* + * Write the address register again, this time write the whole + * 4-byte value. The effect here is that the LSB write causes the + * cycle to start, the extra 3 byte write to bytes 1,2,3 has no + * effect since we are writing the same values again + */ + status = ath6kl_sdio_read_write_sync(ar, reg_addr, (u8 *)(&addr), + 4, HIF_WR_SYNC_BYTE_INC); + + if (status) { + ath6kl_err("%s: failed to write 0x%x to window reg: 0x%X\n", + __func__, addr, reg_addr); + return status; + } + + return 0; +} + +static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data) +{ + int status; + + /* set window register to start read cycle */ + status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, + address); + + if (status) + return status; + + /* read the data */ + status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, + (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC); + if (status) { + ath6kl_err("%s: failed to read from window data addr\n", + __func__); + return status; + } + + return status; +} + +static int ath6kl_sdio_diag_write32(struct ath6kl *ar, u32 address, + __le32 data) +{ + int status; + u32 val = (__force u32) data; + + /* set write data */ + status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, + (u8 *) &val, sizeof(u32), HIF_WR_SYNC_BYTE_INC); + if (status) { + ath6kl_err("%s: failed to write 0x%x to window data addr\n", + __func__, data); + return status; + } + + /* set window register, which starts the write cycle */ + return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, + address); +} + static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) { u32 addr; @@ -1049,6 +1147,8 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { .cleanup_scatter = ath6kl_sdio_cleanup_scatter, .suspend = ath6kl_sdio_suspend, .resume = ath6kl_sdio_resume, + .diag_read32 = ath6kl_sdio_diag_read32, + .diag_write32 = ath6kl_sdio_diag_write32, .bmi_read = ath6kl_sdio_bmi_read, .bmi_write = ath6kl_sdio_bmi_write, .power_on = ath6kl_sdio_power_on, |