diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-11 05:17:51 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-13 05:34:29 -0500 |
commit | c71114959dc952a509822f22251d01004b3b94cc (patch) | |
tree | 704414e7921140cb2506e2525da0b9caf31e10fd /drivers/net/wireless/ath/ath6kl/sdio.c | |
parent | 1f4c894d3a35e88331c01e681d033a2000c3667b (diff) |
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/ath6kl/sdio.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 100 |
1 files changed, 100 insertions, 0 deletions
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) | |||
845 | return 0; | 845 | return 0; |
846 | } | 846 | } |
847 | 847 | ||
848 | /* set the window address register (using 4-byte register access ). */ | ||
849 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | ||
850 | { | ||
851 | int status; | ||
852 | u8 addr_val[4]; | ||
853 | s32 i; | ||
854 | |||
855 | /* | ||
856 | * Write bytes 1,2,3 of the register to set the upper address bytes, | ||
857 | * the LSB is written last to initiate the access cycle | ||
858 | */ | ||
859 | |||
860 | for (i = 1; i <= 3; i++) { | ||
861 | /* | ||
862 | * Fill the buffer with the address byte value we want to | ||
863 | * hit 4 times. | ||
864 | */ | ||
865 | memset(addr_val, ((u8 *)&addr)[i], 4); | ||
866 | |||
867 | /* | ||
868 | * Hit each byte of the register address with a 4-byte | ||
869 | * write operation to the same address, this is a harmless | ||
870 | * operation. | ||
871 | */ | ||
872 | status = ath6kl_sdio_read_write_sync(ar, reg_addr + i, addr_val, | ||
873 | 4, HIF_WR_SYNC_BYTE_FIX); | ||
874 | if (status) | ||
875 | break; | ||
876 | } | ||
877 | |||
878 | if (status) { | ||
879 | ath6kl_err("%s: failed to write initial bytes of 0x%x " | ||
880 | "to window reg: 0x%X\n", __func__, | ||
881 | addr, reg_addr); | ||
882 | return status; | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * Write the address register again, this time write the whole | ||
887 | * 4-byte value. The effect here is that the LSB write causes the | ||
888 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no | ||
889 | * effect since we are writing the same values again | ||
890 | */ | ||
891 | status = ath6kl_sdio_read_write_sync(ar, reg_addr, (u8 *)(&addr), | ||
892 | 4, HIF_WR_SYNC_BYTE_INC); | ||
893 | |||
894 | if (status) { | ||
895 | ath6kl_err("%s: failed to write 0x%x to window reg: 0x%X\n", | ||
896 | __func__, addr, reg_addr); | ||
897 | return status; | ||
898 | } | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | ||
904 | { | ||
905 | int status; | ||
906 | |||
907 | /* set window register to start read cycle */ | ||
908 | status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, | ||
909 | address); | ||
910 | |||
911 | if (status) | ||
912 | return status; | ||
913 | |||
914 | /* read the data */ | ||
915 | status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, | ||
916 | (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC); | ||
917 | if (status) { | ||
918 | ath6kl_err("%s: failed to read from window data addr\n", | ||
919 | __func__); | ||
920 | return status; | ||
921 | } | ||
922 | |||
923 | return status; | ||
924 | } | ||
925 | |||
926 | static int ath6kl_sdio_diag_write32(struct ath6kl *ar, u32 address, | ||
927 | __le32 data) | ||
928 | { | ||
929 | int status; | ||
930 | u32 val = (__force u32) data; | ||
931 | |||
932 | /* set write data */ | ||
933 | status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, | ||
934 | (u8 *) &val, sizeof(u32), HIF_WR_SYNC_BYTE_INC); | ||
935 | if (status) { | ||
936 | ath6kl_err("%s: failed to write 0x%x to window data addr\n", | ||
937 | __func__, data); | ||
938 | return status; | ||
939 | } | ||
940 | |||
941 | /* set window register, which starts the write cycle */ | ||
942 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, | ||
943 | address); | ||
944 | } | ||
945 | |||
848 | static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) | 946 | static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) |
849 | { | 947 | { |
850 | u32 addr; | 948 | u32 addr; |
@@ -1049,6 +1147,8 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
1049 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, | 1147 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, |
1050 | .suspend = ath6kl_sdio_suspend, | 1148 | .suspend = ath6kl_sdio_suspend, |
1051 | .resume = ath6kl_sdio_resume, | 1149 | .resume = ath6kl_sdio_resume, |
1150 | .diag_read32 = ath6kl_sdio_diag_read32, | ||
1151 | .diag_write32 = ath6kl_sdio_diag_write32, | ||
1052 | .bmi_read = ath6kl_sdio_bmi_read, | 1152 | .bmi_read = ath6kl_sdio_bmi_read, |
1053 | .bmi_write = ath6kl_sdio_bmi_write, | 1153 | .bmi_write = ath6kl_sdio_bmi_write, |
1054 | .power_on = ath6kl_sdio_power_on, | 1154 | .power_on = ath6kl_sdio_power_on, |