.. | .. |
---|
| 1 | +// SPDX-License-Identifier: ISC |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
---|
3 | 4 | * Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc. |
---|
4 | | - * |
---|
5 | | - * Permission to use, copy, modify, and/or distribute this software for any |
---|
6 | | - * purpose with or without fee is hereby granted, provided that the above |
---|
7 | | - * copyright notice and this permission notice appear in all copies. |
---|
8 | | - * |
---|
9 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
---|
10 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
---|
11 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
---|
12 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
13 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
---|
14 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
---|
15 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
16 | 5 | */ |
---|
17 | 6 | |
---|
18 | 7 | #include "bmi.h" |
---|
.. | .. |
---|
23 | 12 | |
---|
24 | 13 | void ath10k_bmi_start(struct ath10k *ar) |
---|
25 | 14 | { |
---|
26 | | - int ret; |
---|
27 | | - |
---|
28 | 15 | ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n"); |
---|
29 | 16 | |
---|
30 | 17 | ar->bmi.done_sent = false; |
---|
31 | | - |
---|
32 | | - /* Enable hardware clock to speed up firmware download */ |
---|
33 | | - if (ar->hw_params.hw_ops->enable_pll_clk) { |
---|
34 | | - ret = ar->hw_params.hw_ops->enable_pll_clk(ar); |
---|
35 | | - ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret); |
---|
36 | | - } |
---|
37 | 18 | } |
---|
| 19 | +EXPORT_SYMBOL(ath10k_bmi_start); |
---|
38 | 20 | |
---|
39 | 21 | int ath10k_bmi_done(struct ath10k *ar) |
---|
40 | 22 | { |
---|
.. | .. |
---|
208 | 190 | |
---|
209 | 191 | return 0; |
---|
210 | 192 | } |
---|
| 193 | +EXPORT_SYMBOL(ath10k_bmi_read_memory); |
---|
211 | 194 | |
---|
212 | 195 | int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val) |
---|
213 | 196 | { |
---|
.. | .. |
---|
357 | 340 | return 0; |
---|
358 | 341 | } |
---|
359 | 342 | |
---|
| 343 | +static int ath10k_bmi_lz_data_large(struct ath10k *ar, const void *buffer, u32 length) |
---|
| 344 | +{ |
---|
| 345 | + struct bmi_cmd *cmd; |
---|
| 346 | + u32 hdrlen = sizeof(cmd->id) + sizeof(cmd->lz_data); |
---|
| 347 | + u32 txlen; |
---|
| 348 | + int ret; |
---|
| 349 | + size_t buf_len; |
---|
| 350 | + |
---|
| 351 | + ath10k_dbg(ar, ATH10K_DBG_BMI, "large bmi lz data buffer 0x%pK length %d\n", |
---|
| 352 | + buffer, length); |
---|
| 353 | + |
---|
| 354 | + if (ar->bmi.done_sent) { |
---|
| 355 | + ath10k_warn(ar, "command disallowed\n"); |
---|
| 356 | + return -EBUSY; |
---|
| 357 | + } |
---|
| 358 | + |
---|
| 359 | + buf_len = sizeof(*cmd) + BMI_MAX_LARGE_DATA_SIZE - BMI_MAX_DATA_SIZE; |
---|
| 360 | + cmd = kzalloc(buf_len, GFP_KERNEL); |
---|
| 361 | + if (!cmd) |
---|
| 362 | + return -ENOMEM; |
---|
| 363 | + |
---|
| 364 | + while (length) { |
---|
| 365 | + txlen = min(length, BMI_MAX_LARGE_DATA_SIZE - hdrlen); |
---|
| 366 | + |
---|
| 367 | + WARN_ON_ONCE(txlen & 3); |
---|
| 368 | + |
---|
| 369 | + cmd->id = __cpu_to_le32(BMI_LZ_DATA); |
---|
| 370 | + cmd->lz_data.len = __cpu_to_le32(txlen); |
---|
| 371 | + memcpy(cmd->lz_data.payload, buffer, txlen); |
---|
| 372 | + |
---|
| 373 | + ret = ath10k_hif_exchange_bmi_msg(ar, cmd, hdrlen + txlen, |
---|
| 374 | + NULL, NULL); |
---|
| 375 | + if (ret) { |
---|
| 376 | + ath10k_warn(ar, "unable to write to the device\n"); |
---|
| 377 | + kfree(cmd); |
---|
| 378 | + return ret; |
---|
| 379 | + } |
---|
| 380 | + |
---|
| 381 | + buffer += txlen; |
---|
| 382 | + length -= txlen; |
---|
| 383 | + } |
---|
| 384 | + |
---|
| 385 | + kfree(cmd); |
---|
| 386 | + |
---|
| 387 | + return 0; |
---|
| 388 | +} |
---|
| 389 | + |
---|
360 | 390 | int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length) |
---|
361 | 391 | { |
---|
362 | 392 | struct bmi_cmd cmd; |
---|
.. | .. |
---|
441 | 471 | if (trailer_len > 0) |
---|
442 | 472 | memcpy(trailer, buffer + head_len, trailer_len); |
---|
443 | 473 | |
---|
444 | | - ret = ath10k_bmi_lz_data(ar, buffer, head_len); |
---|
| 474 | + if (ar->hw_params.bmi_large_size_download) |
---|
| 475 | + ret = ath10k_bmi_lz_data_large(ar, buffer, head_len); |
---|
| 476 | + else |
---|
| 477 | + ret = ath10k_bmi_lz_data(ar, buffer, head_len); |
---|
| 478 | + |
---|
445 | 479 | if (ret) |
---|
446 | 480 | return ret; |
---|
447 | 481 | |
---|
.. | .. |
---|
459 | 493 | |
---|
460 | 494 | return ret; |
---|
461 | 495 | } |
---|
| 496 | + |
---|
| 497 | +int ath10k_bmi_set_start(struct ath10k *ar, u32 address) |
---|
| 498 | +{ |
---|
| 499 | + struct bmi_cmd cmd; |
---|
| 500 | + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.set_app_start); |
---|
| 501 | + int ret; |
---|
| 502 | + |
---|
| 503 | + if (ar->bmi.done_sent) { |
---|
| 504 | + ath10k_warn(ar, "bmi set start command disallowed\n"); |
---|
| 505 | + return -EBUSY; |
---|
| 506 | + } |
---|
| 507 | + |
---|
| 508 | + cmd.id = __cpu_to_le32(BMI_SET_APP_START); |
---|
| 509 | + cmd.set_app_start.addr = __cpu_to_le32(address); |
---|
| 510 | + |
---|
| 511 | + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL); |
---|
| 512 | + if (ret) { |
---|
| 513 | + ath10k_warn(ar, "unable to set start to the device:%d\n", ret); |
---|
| 514 | + return ret; |
---|
| 515 | + } |
---|
| 516 | + |
---|
| 517 | + return 0; |
---|
| 518 | +} |
---|