1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2005-2011 Atheros Communications Inc.
4 * Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc.
5 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
14 void ath10k_bmi_start(struct ath10k
*ar
)
16 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi start\n");
18 ar
->bmi
.done_sent
= false;
20 EXPORT_SYMBOL(ath10k_bmi_start
);
22 int ath10k_bmi_done(struct ath10k
*ar
)
25 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.done
);
28 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi done\n");
30 if (ar
->bmi
.done_sent
) {
31 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi skipped\n");
35 ar
->bmi
.done_sent
= true;
36 cmd
.id
= __cpu_to_le32(BMI_DONE
);
38 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, NULL
, NULL
);
40 ath10k_warn(ar
, "unable to write to the device: %d\n", ret
);
47 int ath10k_bmi_get_target_info(struct ath10k
*ar
,
48 struct bmi_target_info
*target_info
)
52 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.get_target_info
);
53 u32 resplen
= sizeof(resp
.get_target_info
);
56 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi get target info\n");
58 if (ar
->bmi
.done_sent
) {
59 ath10k_warn(ar
, "BMI Get Target Info Command disallowed\n");
63 cmd
.id
= __cpu_to_le32(BMI_GET_TARGET_INFO
);
65 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, &resp
, &resplen
);
67 ath10k_warn(ar
, "unable to get target info from device\n");
71 if (resplen
< sizeof(resp
.get_target_info
)) {
72 ath10k_warn(ar
, "invalid get_target_info response length (%d)\n",
77 target_info
->version
= __le32_to_cpu(resp
.get_target_info
.version
);
78 target_info
->type
= __le32_to_cpu(resp
.get_target_info
.type
);
83 #define TARGET_VERSION_SENTINAL 0xffffffffu
85 int ath10k_bmi_get_target_info_sdio(struct ath10k
*ar
,
86 struct bmi_target_info
*target_info
)
90 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.get_target_info
);
95 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi get target info SDIO\n");
97 if (ar
->bmi
.done_sent
) {
98 ath10k_warn(ar
, "BMI Get Target Info Command disallowed\n");
102 cmd
.id
= __cpu_to_le32(BMI_GET_TARGET_INFO
);
104 /* Step 1: Read 4 bytes of the target info and check if it is
105 * the special sentinel version word or the first word in the
108 resplen
= sizeof(u32
);
109 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, &tmp
, &resplen
);
111 ath10k_warn(ar
, "unable to read from device\n");
115 /* Some SDIO boards have a special sentinel byte before the real
118 if (__le32_to_cpu(tmp
) == TARGET_VERSION_SENTINAL
) {
119 /* Step 1b: Read the version length */
120 resplen
= sizeof(u32
);
121 ret
= ath10k_hif_exchange_bmi_msg(ar
, NULL
, 0, &tmp
,
124 ath10k_warn(ar
, "unable to read from device\n");
129 ver_len
= __le32_to_cpu(tmp
);
131 /* Step 2: Check the target info length */
132 if (ver_len
!= sizeof(resp
.get_target_info
)) {
133 ath10k_warn(ar
, "Unexpected target info len: %u. Expected: %zu\n",
134 ver_len
, sizeof(resp
.get_target_info
));
138 /* Step 3: Read the rest of the version response */
139 resplen
= sizeof(resp
.get_target_info
) - sizeof(u32
);
140 ret
= ath10k_hif_exchange_bmi_msg(ar
, NULL
, 0,
141 &resp
.get_target_info
.version
,
144 ath10k_warn(ar
, "unable to read from device\n");
148 target_info
->version
= __le32_to_cpu(resp
.get_target_info
.version
);
149 target_info
->type
= __le32_to_cpu(resp
.get_target_info
.type
);
154 int ath10k_bmi_read_memory(struct ath10k
*ar
,
155 u32 address
, void *buffer
, u32 length
)
159 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.read_mem
);
163 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi read address 0x%x length %d\n",
166 if (ar
->bmi
.done_sent
) {
167 ath10k_warn(ar
, "command disallowed\n");
172 rxlen
= min_t(u32
, length
, BMI_MAX_DATA_SIZE
);
174 cmd
.id
= __cpu_to_le32(BMI_READ_MEMORY
);
175 cmd
.read_mem
.addr
= __cpu_to_le32(address
);
176 cmd
.read_mem
.len
= __cpu_to_le32(rxlen
);
178 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
,
181 ath10k_warn(ar
, "unable to read from the device (%d)\n",
186 memcpy(buffer
, resp
.read_mem
.payload
, rxlen
);
194 EXPORT_SYMBOL(ath10k_bmi_read_memory
);
196 int ath10k_bmi_write_soc_reg(struct ath10k
*ar
, u32 address
, u32 reg_val
)
199 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.write_soc_reg
);
202 ath10k_dbg(ar
, ATH10K_DBG_BMI
,
203 "bmi write soc register 0x%08x val 0x%08x\n",
206 if (ar
->bmi
.done_sent
) {
207 ath10k_warn(ar
, "bmi write soc register command in progress\n");
211 cmd
.id
= __cpu_to_le32(BMI_WRITE_SOC_REGISTER
);
212 cmd
.write_soc_reg
.addr
= __cpu_to_le32(address
);
213 cmd
.write_soc_reg
.value
= __cpu_to_le32(reg_val
);
215 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, NULL
, NULL
);
217 ath10k_warn(ar
, "Unable to write soc register to device: %d\n",
225 int ath10k_bmi_read_soc_reg(struct ath10k
*ar
, u32 address
, u32
*reg_val
)
229 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.read_soc_reg
);
230 u32 resplen
= sizeof(resp
.read_soc_reg
);
233 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi read soc register 0x%08x\n",
236 if (ar
->bmi
.done_sent
) {
237 ath10k_warn(ar
, "bmi read soc register command in progress\n");
241 cmd
.id
= __cpu_to_le32(BMI_READ_SOC_REGISTER
);
242 cmd
.read_soc_reg
.addr
= __cpu_to_le32(address
);
244 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, &resp
, &resplen
);
246 ath10k_warn(ar
, "Unable to read soc register from device: %d\n",
251 *reg_val
= __le32_to_cpu(resp
.read_soc_reg
.value
);
253 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi read soc register value 0x%08x\n",
259 int ath10k_bmi_write_memory(struct ath10k
*ar
,
260 u32 address
, const void *buffer
, u32 length
)
263 u32 hdrlen
= sizeof(cmd
.id
) + sizeof(cmd
.write_mem
);
267 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi write address 0x%x length %d\n",
270 if (ar
->bmi
.done_sent
) {
271 ath10k_warn(ar
, "command disallowed\n");
276 txlen
= min(length
, BMI_MAX_DATA_SIZE
- hdrlen
);
278 /* copy before roundup to avoid reading beyond buffer*/
279 memcpy(cmd
.write_mem
.payload
, buffer
, txlen
);
280 txlen
= roundup(txlen
, 4);
282 cmd
.id
= __cpu_to_le32(BMI_WRITE_MEMORY
);
283 cmd
.write_mem
.addr
= __cpu_to_le32(address
);
284 cmd
.write_mem
.len
= __cpu_to_le32(txlen
);
286 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, hdrlen
+ txlen
,
289 ath10k_warn(ar
, "unable to write to the device (%d)\n",
294 /* fixup roundup() so `length` zeroes out for last chunk */
295 txlen
= min(txlen
, length
);
305 int ath10k_bmi_execute(struct ath10k
*ar
, u32 address
, u32 param
, u32
*result
)
309 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.execute
);
310 u32 resplen
= sizeof(resp
.execute
);
313 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi execute address 0x%x param 0x%x\n",
316 if (ar
->bmi
.done_sent
) {
317 ath10k_warn(ar
, "command disallowed\n");
321 cmd
.id
= __cpu_to_le32(BMI_EXECUTE
);
322 cmd
.execute
.addr
= __cpu_to_le32(address
);
323 cmd
.execute
.param
= __cpu_to_le32(param
);
325 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, &resp
, &resplen
);
327 ath10k_warn(ar
, "unable to read from the device\n");
331 if (resplen
< sizeof(resp
.execute
)) {
332 ath10k_warn(ar
, "invalid execute response length (%d)\n",
337 *result
= __le32_to_cpu(resp
.execute
.result
);
339 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi execute result 0x%x\n", *result
);
344 static int ath10k_bmi_lz_data_large(struct ath10k
*ar
, const void *buffer
, u32 length
)
347 u32 hdrlen
= sizeof(cmd
->id
) + sizeof(cmd
->lz_data
);
352 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "large bmi lz data buffer 0x%pK length %d\n",
355 if (ar
->bmi
.done_sent
) {
356 ath10k_warn(ar
, "command disallowed\n");
360 buf_len
= sizeof(*cmd
) + BMI_MAX_LARGE_DATA_SIZE
- BMI_MAX_DATA_SIZE
;
361 cmd
= kzalloc(buf_len
, GFP_KERNEL
);
366 txlen
= min(length
, BMI_MAX_LARGE_DATA_SIZE
- hdrlen
);
368 WARN_ON_ONCE(txlen
& 3);
370 cmd
->id
= __cpu_to_le32(BMI_LZ_DATA
);
371 cmd
->lz_data
.len
= __cpu_to_le32(txlen
);
372 memcpy(cmd
->lz_data
.payload
, buffer
, txlen
);
374 ret
= ath10k_hif_exchange_bmi_msg(ar
, cmd
, hdrlen
+ txlen
,
377 ath10k_warn(ar
, "unable to write to the device\n");
391 int ath10k_bmi_lz_data(struct ath10k
*ar
, const void *buffer
, u32 length
)
394 u32 hdrlen
= sizeof(cmd
.id
) + sizeof(cmd
.lz_data
);
398 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi lz data buffer 0x%pK length %d\n",
401 if (ar
->bmi
.done_sent
) {
402 ath10k_warn(ar
, "command disallowed\n");
407 txlen
= min(length
, BMI_MAX_DATA_SIZE
- hdrlen
);
409 WARN_ON_ONCE(txlen
& 3);
411 cmd
.id
= __cpu_to_le32(BMI_LZ_DATA
);
412 cmd
.lz_data
.len
= __cpu_to_le32(txlen
);
413 memcpy(cmd
.lz_data
.payload
, buffer
, txlen
);
415 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, hdrlen
+ txlen
,
418 ath10k_warn(ar
, "unable to write to the device\n");
429 int ath10k_bmi_lz_stream_start(struct ath10k
*ar
, u32 address
)
432 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.lz_start
);
435 ath10k_dbg(ar
, ATH10K_DBG_BMI
, "bmi lz stream start address 0x%x\n",
438 if (ar
->bmi
.done_sent
) {
439 ath10k_warn(ar
, "command disallowed\n");
443 cmd
.id
= __cpu_to_le32(BMI_LZ_STREAM_START
);
444 cmd
.lz_start
.addr
= __cpu_to_le32(address
);
446 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, NULL
, NULL
);
448 ath10k_warn(ar
, "unable to Start LZ Stream to the device\n");
455 int ath10k_bmi_fast_download(struct ath10k
*ar
,
456 u32 address
, const void *buffer
, u32 length
)
459 u32 head_len
= rounddown(length
, 4);
460 u32 trailer_len
= length
- head_len
;
463 ath10k_dbg(ar
, ATH10K_DBG_BMI
,
464 "bmi fast download address 0x%x buffer 0x%pK length %d\n",
465 address
, buffer
, length
);
467 ret
= ath10k_bmi_lz_stream_start(ar
, address
);
471 /* copy the last word into a zero padded buffer */
473 memcpy(trailer
, buffer
+ head_len
, trailer_len
);
475 if (ar
->hw_params
.bmi_large_size_download
)
476 ret
= ath10k_bmi_lz_data_large(ar
, buffer
, head_len
);
478 ret
= ath10k_bmi_lz_data(ar
, buffer
, head_len
);
484 ret
= ath10k_bmi_lz_data(ar
, trailer
, 4);
490 * Close compressed stream and open a new (fake) one.
491 * This serves mainly to flush Target caches.
493 ret
= ath10k_bmi_lz_stream_start(ar
, 0x00);
498 int ath10k_bmi_set_start(struct ath10k
*ar
, u32 address
)
501 u32 cmdlen
= sizeof(cmd
.id
) + sizeof(cmd
.set_app_start
);
504 if (ar
->bmi
.done_sent
) {
505 ath10k_warn(ar
, "bmi set start command disallowed\n");
509 cmd
.id
= __cpu_to_le32(BMI_SET_APP_START
);
510 cmd
.set_app_start
.addr
= __cpu_to_le32(address
);
512 ret
= ath10k_hif_exchange_bmi_msg(ar
, &cmd
, cmdlen
, NULL
, NULL
);
514 ath10k_warn(ar
, "unable to set start to the device:%d\n", ret
);