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 | |
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')
-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, | |||
91 | return ar->hif_ops->suspend(ar, wow); | 91 | return ar->hif_ops->suspend(ar, wow); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* | ||
95 | * Read from the ATH6KL through its diagnostic window. No cooperation from | ||
96 | * the Target is required for this. | ||
97 | */ | ||
98 | static inline int ath6kl_hif_diag_read32(struct ath6kl *ar, u32 address, | ||
99 | u32 *value) | ||
100 | { | ||
101 | return ar->hif_ops->diag_read32(ar, address, value); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Write to the ATH6KL through its diagnostic window. No cooperation from | ||
106 | * the Target is required for this. | ||
107 | */ | ||
108 | static inline int ath6kl_hif_diag_write32(struct ath6kl *ar, u32 address, | ||
109 | __le32 value) | ||
110 | { | ||
111 | return ar->hif_ops->diag_write32(ar, address, value); | ||
112 | } | ||
113 | |||
94 | static inline int ath6kl_hif_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | 114 | static inline int ath6kl_hif_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) |
95 | { | 115 | { |
96 | return ar->hif_ops->bmi_read(ar, buf, len); | 116 | 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 { | |||
244 | void (*cleanup_scatter)(struct ath6kl *ar); | 244 | void (*cleanup_scatter)(struct ath6kl *ar); |
245 | int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow); | 245 | int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow); |
246 | int (*resume)(struct ath6kl *ar); | 246 | int (*resume)(struct ath6kl *ar); |
247 | int (*diag_read32)(struct ath6kl *ar, u32 address, u32 *value); | ||
248 | int (*diag_write32)(struct ath6kl *ar, u32 address, __le32 value); | ||
247 | int (*bmi_read)(struct ath6kl *ar, u8 *buf, u32 len); | 249 | int (*bmi_read)(struct ath6kl *ar, u8 *buf, u32 len); |
248 | int (*bmi_write)(struct ath6kl *ar, u8 *buf, u32 len); | 250 | int (*bmi_write)(struct ath6kl *ar, u8 *buf, u32 len); |
249 | int (*power_on)(struct ath6kl *ar); | 251 | 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) | |||
175 | ar->cookie_count++; | 175 | ar->cookie_count++; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* set the window address register (using 4-byte register access ). */ | ||
179 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | ||
180 | { | ||
181 | int status; | ||
182 | s32 i; | ||
183 | __le32 addr_val; | ||
184 | |||
185 | /* | ||
186 | * Write bytes 1,2,3 of the register to set the upper address bytes, | ||
187 | * the LSB is written last to initiate the access cycle | ||
188 | */ | ||
189 | |||
190 | for (i = 1; i <= 3; i++) { | ||
191 | /* | ||
192 | * Fill the buffer with the address byte value we want to | ||
193 | * hit 4 times. No need to worry about endianness as the | ||
194 | * same byte is copied to all four bytes of addr_val at | ||
195 | * any time. | ||
196 | */ | ||
197 | memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4); | ||
198 | |||
199 | /* | ||
200 | * Hit each byte of the register address with a 4-byte | ||
201 | * write operation to the same address, this is a harmless | ||
202 | * operation. | ||
203 | */ | ||
204 | status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val, | ||
205 | 4, HIF_WR_SYNC_BYTE_FIX); | ||
206 | if (status) | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | if (status) { | ||
211 | ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n", | ||
212 | addr, reg_addr); | ||
213 | return status; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Write the address register again, this time write the whole | ||
218 | * 4-byte value. The effect here is that the LSB write causes the | ||
219 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no | ||
220 | * effect since we are writing the same values again | ||
221 | */ | ||
222 | addr_val = cpu_to_le32(addr); | ||
223 | status = hif_read_write_sync(ar, reg_addr, | ||
224 | (u8 *)&(addr_val), | ||
225 | 4, HIF_WR_SYNC_BYTE_INC); | ||
226 | |||
227 | if (status) { | ||
228 | ath6kl_err("failed to write 0x%x to window reg: 0x%X\n", | ||
229 | addr, reg_addr); | ||
230 | return status; | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* | 178 | /* |
237 | * Read from the hardware through its diagnostic window. No cooperation | 179 | * Read from the hardware through its diagnostic window. No cooperation |
238 | * from the firmware is required for this. | 180 | * from the firmware is required for this. |
@@ -241,14 +183,7 @@ int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value) | |||
241 | { | 183 | { |
242 | int ret; | 184 | int ret; |
243 | 185 | ||
244 | /* set window register to start read cycle */ | 186 | ret = ath6kl_hif_diag_read32(ar, address, value); |
245 | ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | /* read the data */ | ||
250 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value, | ||
251 | sizeof(*value), HIF_RD_SYNC_BYTE_INC); | ||
252 | if (ret) { | 187 | if (ret) { |
253 | ath6kl_warn("failed to read32 through diagnose window: %d\n", | 188 | ath6kl_warn("failed to read32 through diagnose window: %d\n", |
254 | ret); | 189 | ret); |
@@ -266,18 +201,15 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) | |||
266 | { | 201 | { |
267 | int ret; | 202 | int ret; |
268 | 203 | ||
269 | /* set write data */ | 204 | ret = ath6kl_hif_diag_write32(ar, address, value); |
270 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value, | 205 | |
271 | sizeof(value), HIF_WR_SYNC_BYTE_INC); | ||
272 | if (ret) { | 206 | if (ret) { |
273 | ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", | 207 | ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", |
274 | address, value); | 208 | address, value); |
275 | return ret; | 209 | return ret; |
276 | } | 210 | } |
277 | 211 | ||
278 | /* set window register, which starts the write cycle */ | 212 | return 0; |
279 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, | ||
280 | address); | ||
281 | } | 213 | } |
282 | 214 | ||
283 | int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) | 215 | 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) | |||
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, |