^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Marvell BT-over-SDIO driver: SDIO interface related functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2009, Marvell International Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This software file (the "File") is distributed by Marvell International
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Ltd. under the terms of the GNU General Public License Version 2, June 1991
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * (the "License"). You may use, redistribute and/or modify this File in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * accordance with the terms and conditions of the License, a copy of which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * is available by writing to the Free Software Foundation, Inc.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * this warranty disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mmc/sdio_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mmc/sdio_func.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/devcoredump.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <net/bluetooth/bluetooth.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <net/bluetooth/hci_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "btmrvl_drv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "btmrvl_sdio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define VERSION "1.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct memory_type_mapping mem_type_mapping_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {"ITCM", NULL, 0, 0xF0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {"DTCM", NULL, 0, 0xF1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {"SQRAM", NULL, 0, 0xF2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {"APU", NULL, 0, 0xF3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {"CIU", NULL, 0, 0xF4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {"ICU", NULL, 0, 0xF5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {"MAC", NULL, 0, 0xF6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {"EXT7", NULL, 0, 0xF7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {"EXT8", NULL, 0, 0xF8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {"EXT9", NULL, 0, 0xF9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {"EXT10", NULL, 0, 0xFA},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {"EXT11", NULL, 0, 0xFB},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {"EXT12", NULL, 0, 0xFC},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {"EXT13", NULL, 0, 0xFD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {"EXTLAST", NULL, 0, 0xFE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static const struct of_device_id btmrvl_sdio_of_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { .compatible = "marvell,sd8897-bt" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { .compatible = "marvell,sd8997-bt" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct btmrvl_sdio_card *card = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct device *dev = &card->func->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) dev_info(dev, "wake by bt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cfg->wake_by_bt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) disable_irq_nosync(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pm_wakeup_event(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pm_system_wakeup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* This function parses device tree node using mmc subnode devicetree API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * The device node is saved in card->plt_of_node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * If the device tree node exists and includes interrupts attributes, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * function will request platform specific wakeup interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int btmrvl_sdio_probe_of(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct btmrvl_plt_wake_cfg *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!dev->of_node ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dev_info(dev, "sdio device tree data not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) card->plt_of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cfg = card->plt_wake_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (cfg && card->plt_of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!cfg->irq_bt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_err(dev, "fail to parse irq_bt from device tree\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) cfg->irq_bt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ret = devm_request_irq(dev, cfg->irq_bt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) btmrvl_wake_irq_bt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0, "bt_wake", card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "Failed to request irq_bt %d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) cfg->irq_bt, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* Configure wakeup (enabled by default) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) device_init_wakeup(dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) disable_irq(cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* The btmrvl_sdio_remove() callback function is called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * when user removes this module from kernel space or ejects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * the card from the slot. The driver handles these 2 cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * differently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * If the user is removing the module, a MODULE_SHUTDOWN_REQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * command is sent to firmware and interrupt will be disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * If the card is removed, there is no need to send command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * or disable interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The variable 'user_rmmod' is used to distinguish these two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * scenarios. This flag is initialized as FALSE in case the card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * is removed, and will be set to TRUE for module removal when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * module_exit function is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static u8 user_rmmod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static u8 sdio_ireg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .cfg = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .host_int_mask = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .host_intstatus = 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .card_status = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .sq_read_base_addr_a0 = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .sq_read_base_addr_a1 = 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .card_fw_status0 = 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .card_fw_status1 = 0x41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .card_rx_len = 0x42,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .card_rx_unit = 0x43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .io_port_0 = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .io_port_1 = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .io_port_2 = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .int_read_to_clear = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .cfg = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .host_int_mask = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .host_intstatus = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .card_status = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .sq_read_base_addr_a0 = 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .sq_read_base_addr_a1 = 0x41,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .card_revision = 0x5c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .card_fw_status0 = 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .card_fw_status1 = 0x61,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .card_rx_len = 0x62,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .card_rx_unit = 0x63,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .io_port_0 = 0x78,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .io_port_1 = 0x79,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .io_port_2 = 0x7a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .int_read_to_clear = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static const struct btmrvl_sdio_card_reg btmrvl_reg_8887 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .cfg = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .host_int_mask = 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .host_intstatus = 0x0C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .card_status = 0x5C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .sq_read_base_addr_a0 = 0x6C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .sq_read_base_addr_a1 = 0x6D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .card_revision = 0xC8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .card_fw_status0 = 0x88,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .card_fw_status1 = 0x89,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .card_rx_len = 0x8A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .card_rx_unit = 0x8B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .io_port_0 = 0xE4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .io_port_1 = 0xE5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .io_port_2 = 0xE6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .int_read_to_clear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .host_int_rsr = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .card_misc_cfg = 0xD8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .cfg = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .host_int_mask = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .host_intstatus = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .card_status = 0x50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .sq_read_base_addr_a0 = 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .sq_read_base_addr_a1 = 0x61,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .card_revision = 0xbc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .card_fw_status0 = 0xc0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .card_fw_status1 = 0xc1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .card_rx_len = 0xc2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .card_rx_unit = 0xc3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .io_port_0 = 0xd8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .io_port_1 = 0xd9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .io_port_2 = 0xda,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .int_read_to_clear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .host_int_rsr = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .card_misc_cfg = 0xcc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .fw_dump_ctrl = 0xe2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .fw_dump_start = 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .fw_dump_end = 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static const struct btmrvl_sdio_card_reg btmrvl_reg_89xx = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .cfg = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .host_int_mask = 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .host_intstatus = 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .card_status = 0x5c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .sq_read_base_addr_a0 = 0xf8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .sq_read_base_addr_a1 = 0xf9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .card_revision = 0xc8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .card_fw_status0 = 0xe8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .card_fw_status1 = 0xe9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .card_rx_len = 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .card_rx_unit = 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .io_port_0 = 0xe4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .io_port_1 = 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .io_port_2 = 0xe6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .int_read_to_clear = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .host_int_rsr = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .card_misc_cfg = 0xd8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .fw_dump_ctrl = 0xf0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .fw_dump_start = 0xf1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .fw_dump_end = 0xf8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .helper = "mrvl/sd8688_helper.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .firmware = "mrvl/sd8688.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .reg = &btmrvl_reg_8688,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .support_pscan_win_report = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .sd_blksz_fw_dl = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .supports_fw_dump = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .firmware = "mrvl/sd8787_uapsta.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .reg = &btmrvl_reg_87xx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .support_pscan_win_report = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .supports_fw_dump = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .firmware = "mrvl/sd8797_uapsta.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .reg = &btmrvl_reg_87xx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .support_pscan_win_report = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .supports_fw_dump = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .firmware = "mrvl/sd8887_uapsta.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .reg = &btmrvl_reg_8887,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .support_pscan_win_report = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .supports_fw_dump = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .firmware = "mrvl/sd8897_uapsta.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .reg = &btmrvl_reg_8897,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .support_pscan_win_report = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .supports_fw_dump = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .firmware = "mrvl/sdsd8977_combo_v2.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .reg = &btmrvl_reg_89xx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .support_pscan_win_report = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .supports_fw_dump = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .firmware = "mrvl/sd8987_uapsta.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .reg = &btmrvl_reg_89xx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .support_pscan_win_report = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .supports_fw_dump = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .helper = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .firmware = "mrvl/sdsd8997_combo_v4.bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .reg = &btmrvl_reg_89xx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .support_pscan_win_report = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .sd_blksz_fw_dl = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .supports_fw_dump = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static const struct sdio_device_id btmrvl_sdio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Marvell SD8688 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8688_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Marvell SD8787 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* Marvell SD8787 Bluetooth AMP device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787_BT_AMP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* Marvell SD8797 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* Marvell SD8887 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Marvell SD8897 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Marvell SD8977 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8977_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .driver_data = (unsigned long)&btmrvl_sdio_sd8977 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* Marvell SD8987 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8987_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .driver_data = (unsigned long)&btmrvl_sdio_sd8987 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Marvell SD8997 Bluetooth device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997_BT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_DEVICE_TABLE(sdio, btmrvl_sdio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) card->rx_unit = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) u8 fws0, fws1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *dat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *dat = (((u16) fws1) << 8) | fws0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) *dat = (u16) reg << card->rx_unit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) BT_ERR("Unable to enable the host interrupt!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) u8 host_int_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) host_int_mask &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) BT_ERR("Unable to disable the host interrupt!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) status = sdio_readb(card->func, card->reg->card_status, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if ((status & bits) == bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) BT_ERR("FAILED! ret=%d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) int pollnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) u16 firmwarestat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int tries, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Wait for firmware to become ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) for (tries = 0; tries < pollnum; tries++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = btmrvl_sdio_read_fw_status(card, &firmwarestat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (firmwarestat == FIRMWARE_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) const struct firmware *fw_helper = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) const u8 *helper = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) void *tmphlprbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int tmphlprbufsz, hlprblknow, helperlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) u8 *helperbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) u32 tx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = request_firmware(&fw_helper, card->helper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) &card->func->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if ((ret < 0) || !fw_helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) BT_ERR("request_firmware(helper) failed, error code = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) helper = fw_helper->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) helperlen = fw_helper->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) BT_DBG("Downloading helper image (%d bytes), block size %d bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) helperlen, SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!tmphlprbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) BT_ERR("Unable to allocate buffer for helper."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) " Terminating download");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* Perform helper data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) tx_len = (FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) - SDIO_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) hlprblknow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = btmrvl_sdio_poll_card_status(card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) CARD_IO_READY | DN_LD_CARD_RDY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) BT_ERR("Helper download poll status timeout @ %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) hlprblknow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* Check if there is more data? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (hlprblknow >= helperlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (helperlen - hlprblknow < tx_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) tx_len = helperlen - hlprblknow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* Little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) helperbuf[0] = ((tx_len & 0x000000ff) >> 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) helperbuf[1] = ((tx_len & 0x0000ff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) helperbuf[2] = ((tx_len & 0x00ff0000) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) helperbuf[3] = ((tx_len & 0xff000000) >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) memcpy(&helperbuf[SDIO_HEADER_LEN], &helper[hlprblknow],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) tx_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Now send the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) ret = sdio_writesb(card->func, card->ioport, helperbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) FIRMWARE_TRANSFER_NBLOCK * SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) BT_ERR("IO error during helper download @ %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) hlprblknow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) hlprblknow += tx_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) } while (true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) BT_DBG("Transferring helper image EOF block");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) memset(helperbuf, 0x0, SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) ret = sdio_writesb(card->func, card->ioport, helperbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) BT_ERR("IO error in writing helper image EOF block");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) kfree(tmphlprbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) release_firmware(fw_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) const struct firmware *fw_firmware = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) const u8 *firmware = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) int firmwarelen, tmpfwbufsz, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) unsigned int tries, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) u8 base0, base1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) void *tmpfwbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) u8 *fwbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) u16 len, blksz_dl = card->sd_blksz_fw_dl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int txlen = 0, tx_blocks = 0, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ret = request_firmware(&fw_firmware, card->firmware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) &card->func->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if ((ret < 0) || !fw_firmware) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) BT_ERR("request_firmware(firmware) failed, error code = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) firmware = fw_firmware->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) firmwarelen = fw_firmware->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!tmpfwbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) BT_ERR("Unable to allocate buffer for firmware."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) " Terminating download");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* Ensure aligned firmware buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* Perform firmware data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret = btmrvl_sdio_poll_card_status(card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) CARD_IO_READY | DN_LD_CARD_RDY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) BT_ERR("FW download with helper poll status"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) " timeout @ %d", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* Check if there is more data ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (offset >= firmwarelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) base0 = sdio_readb(card->func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) card->reg->sq_read_base_addr_a0, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) BT_ERR("BASE0 register read failed:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) " base0 = 0x%04X(%d)."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) " Terminating download",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) base0, base0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) base1 = sdio_readb(card->func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) card->reg->sq_read_base_addr_a1, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) BT_ERR("BASE1 register read failed:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) " base1 = 0x%04X(%d)."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) " Terminating download",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) base1, base1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) len = (((u16) base1) << 8) | base0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) else if (len > BTM_UPLD_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) BT_ERR("FW download failure @%d, invalid length %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) offset, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) txlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (len & BIT(0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (count > MAX_WRITE_IOMEM_RETRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) BT_ERR("FW download failure @%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) "over max retry count", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) BT_ERR("FW CRC error indicated by the helper: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) "len = 0x%04X, txlen = %d", len, txlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) len &= ~BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* Set txlen to 0 so as to resend from same offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) txlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* Last block ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (firmwarelen - offset < txlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) txlen = firmwarelen - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) tx_blocks = DIV_ROUND_UP(txlen, blksz_dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) memcpy(fwbuf, &firmware[offset], txlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret = sdio_writesb(card->func, card->ioport, fwbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) tx_blocks * blksz_dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) BT_ERR("FW download, writesb(%d) failed @%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) count, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) sdio_writeb(card->func, HOST_CMD53_FIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) card->reg->cfg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) BT_ERR("writeb failed (CFG)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) offset += txlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) } while (true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) BT_INFO("FW download over, size %d bytes", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) kfree(tmpfwbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) release_firmware(fw_firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) u16 buf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) int ret, num_blocks, blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u32 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) u8 *payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct hci_dev *hdev = priv->btmrvl_dev.hcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!card || !card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) BT_ERR("card or function is NULL!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* Read the length of data to be transferred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ret = btmrvl_sdio_read_rx_len(card, &buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) BT_ERR("read rx_len failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) blksz = SDIO_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) num_blocks = DIV_ROUND_UP(buf_len, blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (buf_len <= SDIO_HEADER_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) BT_ERR("invalid packet length: %d", buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* Allocate buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) BT_ERR("No free skb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if ((unsigned long) skb->data & (BTSDIO_DMA_ALIGN - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) skb_put(skb, (unsigned long) skb->data &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) (BTSDIO_DMA_ALIGN - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) skb_pull(skb, (unsigned long) skb->data &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (BTSDIO_DMA_ALIGN - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) payload = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) ret = sdio_readsb(card->func, payload, card->ioport,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) num_blocks * blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) BT_ERR("readsb failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* This is SDIO specific header length: byte[2][1][0], type: byte[3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) buf_len = payload[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) buf_len |= payload[1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) buf_len |= payload[2] << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (buf_len > blksz * num_blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) buf_len, blksz * num_blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) type = payload[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) case HCI_ACLDATA_PKT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case HCI_SCODATA_PKT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) case HCI_EVENT_PKT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) hci_skb_pkt_type(skb) = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) skb_put(skb, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) skb_pull(skb, SDIO_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (type == HCI_EVENT_PKT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (btmrvl_check_evtpkt(priv, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) hci_recv_frame(hdev, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) hci_recv_frame(hdev, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) hdev->stat.byte_rx += buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case MRVL_VENDOR_PKT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) skb_put(skb, buf_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) skb_pull(skb, SDIO_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (btmrvl_process_event(priv, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) hci_recv_frame(hdev, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) hdev->stat.byte_rx += buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) BT_ERR("Unknown packet type:%d", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) BT_ERR("hex: %*ph", blksz * num_blocks, payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) hdev->stat.err_rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ulong flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) u8 ireg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) spin_lock_irqsave(&priv->driver_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) ireg = sdio_ireg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) sdio_ireg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) spin_unlock_irqrestore(&priv->driver_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (ireg & DN_LD_HOST_INT_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (priv->btmrvl_dev.tx_dnld_rdy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) BT_DBG("tx_done already received: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) " int_status=0x%x", ireg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) priv->btmrvl_dev.tx_dnld_rdy = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (ireg & UP_LD_HOST_INT_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) btmrvl_sdio_card_to_host(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct btmrvl_adapter *adapter = card->priv->adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) *ireg = adapter->hw_regs[card->reg->host_intstatus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) *ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) BT_ERR("sdio_readb: read int status failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (*ireg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * Clear the interrupt status register and re-enable the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) BT_DBG("int_status = 0x%x", *ireg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) UP_LD_HOST_INT_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) card->reg->host_intstatus, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) BT_ERR("sdio_writeb: clear int status failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static void btmrvl_sdio_interrupt(struct sdio_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct btmrvl_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct btmrvl_sdio_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ulong flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) u8 ireg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) card = sdio_get_drvdata(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (!card || !card->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) func, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) priv = card->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (priv->surprise_removed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (card->reg->int_read_to_clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) ret = btmrvl_sdio_read_to_clear(card, &ireg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ret = btmrvl_sdio_write_to_clear(card, &ireg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) spin_lock_irqsave(&priv->driver_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) sdio_ireg |= ireg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) spin_unlock_irqrestore(&priv->driver_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) btmrvl_interrupt(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) struct sdio_func *func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (!card || !card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) BT_ERR("Error: card or function is NULL!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) func = card->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) sdio_claim_host(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ret = sdio_enable_func(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) BT_ERR("sdio_enable_func() failed: ret=%d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) goto release_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) ret = sdio_claim_irq(func, btmrvl_sdio_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) BT_ERR("sdio_claim_irq failed: ret=%d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) goto disable_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) ret = sdio_set_block_size(card->func, SDIO_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) BT_ERR("cannot set SDIO block size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) reg = sdio_readb(func, card->reg->io_port_0, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) card->ioport = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) reg = sdio_readb(func, card->reg->io_port_1, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) card->ioport |= (reg << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) reg = sdio_readb(func, card->reg->io_port_2, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) card->ioport |= (reg << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (card->reg->int_read_to_clear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) reg = sdio_readb(func, card->reg->host_int_rsr, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) reg = sdio_readb(func, card->reg->card_misc_cfg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) goto release_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) sdio_set_drvdata(func, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) sdio_release_host(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) release_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) sdio_release_irq(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) disable_func:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) sdio_disable_func(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) release_host:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) sdio_release_host(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) static int btmrvl_sdio_unregister_dev(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (card && card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) sdio_release_irq(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) sdio_disable_func(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) sdio_set_drvdata(card->func, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static int btmrvl_sdio_enable_host_int(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!card || !card->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ret = btmrvl_sdio_enable_host_int_mask(card, HIM_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) btmrvl_sdio_get_rx_unit(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static int btmrvl_sdio_disable_host_int(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (!card || !card->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ret = btmrvl_sdio_disable_host_int_mask(card, HIM_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) u8 *payload, u16 nb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int blksz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) u8 *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) void *tmpbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) int tmpbufsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (!card || !card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) BT_ERR("card or function is NULL!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) blksz = DIV_ROUND_UP(nb, SDIO_BLOCK_SIZE) * SDIO_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) buf = payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) nb < blksz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) tmpbufsz = ALIGN_SZ(blksz, BTSDIO_DMA_ALIGN) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) BTSDIO_DMA_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!tmpbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) buf = (u8 *) ALIGN_ADDR(tmpbuf, BTSDIO_DMA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) memcpy(buf, payload, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* Transfer data to card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ret = sdio_writesb(card->func, card->ioport, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) BT_ERR("i=%d writesb failed: %d", i, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) BT_ERR("hex: %*ph", nb, payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (i > MAX_WRITE_IOMEM_RETRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) } while (ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) priv->btmrvl_dev.tx_dnld_rdy = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) kfree(tmpbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) u8 fws0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) int pollnum = MAX_POLL_TRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (!card || !card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) BT_ERR("card or function is NULL!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (!btmrvl_sdio_verify_fw_download(card, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) BT_DBG("Firmware already downloaded!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /* Check if other function driver is downloading the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) BT_ERR("Failed to read FW downloading status!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (fws0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* Give other function more time to download the firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) pollnum *= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (card->helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ret = btmrvl_sdio_download_helper(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) BT_ERR("Failed to download helper!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (btmrvl_sdio_download_fw_w_helper(card)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) BT_ERR("Failed to download firmware!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * winner or not, with this test the FW synchronizes when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) * module can continue its initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) BT_ERR("FW failed to be active in time!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (!card || !card->func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) BT_ERR("card or function is NULL!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) BT_DBG("wake up firmware");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) unsigned int reg, reg_start, reg_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) char buf[256], *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) u8 loop, func, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) int MAX_LOOP = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) btmrvl_sdio_wakeup_fw(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) for (loop = 0; loop < MAX_LOOP; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) memset(buf, 0, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ptr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (loop == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /* Read the registers of SDIO function0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) func = loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) reg_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) reg_end = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) func = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) reg_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) reg_end = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) func, reg_start, reg_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) for (reg = reg_start; reg <= reg_end; reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if (func == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) data = sdio_f0_readb(card->func, reg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) data = sdio_readb(card->func, reg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) ptr += sprintf(ptr, "%02x ", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) ptr += sprintf(ptr, "ERR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) BT_INFO("%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* This function read/write firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) static enum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) u8 doneflag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) int ret, tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) u8 ctrl_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) BT_ERR("SDIO write err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return RDWR_STATUS_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) BT_ERR("SDIO read err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) return RDWR_STATUS_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (ctrl_data == FW_DUMP_DONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (doneflag && ctrl_data == doneflag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return RDWR_STATUS_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (ctrl_data != FW_DUMP_HOST_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) BT_INFO("The ctrl reg was changed, re-try again!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) sdio_writeb(card->func, FW_DUMP_HOST_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) card->reg->fw_dump_ctrl, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) BT_ERR("SDIO write err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return RDWR_STATUS_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (ctrl_data == FW_DUMP_HOST_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) BT_ERR("Fail to pull ctrl_data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) return RDWR_STATUS_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return RDWR_STATUS_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* This function dump sdio register and memory data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static void btmrvl_sdio_coredump(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) struct sdio_func *func = dev_to_sdio_func(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct btmrvl_sdio_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) struct btmrvl_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) unsigned int reg, reg_start, reg_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) enum rdwr_status stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) u8 dump_num = 0, idx, i, read_reg, doneflag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) u32 memory_size, fw_dump_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) card = sdio_get_drvdata(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) priv = card->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) /* dump sdio register first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) btmrvl_sdio_dump_regs(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (!card->supports_fw_dump) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) BT_ERR("Firmware dump not supported for this card!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (entry->mem_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) vfree(entry->mem_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) entry->mem_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) entry->mem_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) btmrvl_sdio_wakeup_fw(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) sdio_claim_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) BT_INFO("== btmrvl firmware dump start ==");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (stat == RDWR_STATUS_FAILURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) reg = card->reg->fw_dump_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) /* Read the number of the memories which will dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dump_num = sdio_readb(card->func, reg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) BT_ERR("SDIO read memory length err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) /* Read the length of every memory which will dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) for (idx = 0; idx < dump_num; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (stat == RDWR_STATUS_FAILURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) memory_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) reg = card->reg->fw_dump_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) read_reg = sdio_readb(card->func, reg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) BT_ERR("SDIO read err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) memory_size |= (read_reg << i*8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) reg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) if (memory_size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) BT_INFO("Firmware dump finished!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) sdio_writeb(card->func, FW_DUMP_READ_DONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) card->reg->fw_dump_ctrl, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) entry->mem_ptr = vzalloc(memory_size + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) entry->mem_size = memory_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) if (!entry->mem_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) BT_ERR("Vzalloc %s failed", entry->mem_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) fw_dump_len += (strlen("========Start dump ") +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) strlen(entry->mem_name) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) strlen("========\n") +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) (memory_size + 1) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) strlen("\n========End dump========\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) dbg_ptr = entry->mem_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) end_ptr = dbg_ptr + memory_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) doneflag = entry->done_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) BT_INFO("Start %s output, please wait...",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) entry->mem_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) if (stat == RDWR_STATUS_FAILURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) reg_start = card->reg->fw_dump_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) reg_end = card->reg->fw_dump_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) for (reg = reg_start; reg <= reg_end; reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) *dbg_ptr = sdio_readb(card->func, reg, &ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) BT_ERR("SDIO read err");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (dbg_ptr < end_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) dbg_ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) BT_ERR("Allocated buffer not enough");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (stat != RDWR_STATUS_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) BT_INFO("%s done: size=0x%tx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) entry->mem_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dbg_ptr - entry->mem_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) BT_INFO("== btmrvl firmware dump end ==");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) sdio_release_host(card->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (fw_dump_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) fw_dump_data = vzalloc(fw_dump_len+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (!fw_dump_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) BT_ERR("Vzalloc fw_dump_data fail!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) fw_dump_ptr = fw_dump_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /* Dump all the memory data into single file, a userspace script will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) * be used to split all the memory data to multiple files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) for (idx = 0; idx < dump_num; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (entry->mem_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) strcpy(fw_dump_ptr, "========Start dump ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) fw_dump_ptr += strlen("========Start dump ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) strcpy(fw_dump_ptr, entry->mem_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) fw_dump_ptr += strlen(entry->mem_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) strcpy(fw_dump_ptr, "========\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) fw_dump_ptr += strlen("========\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) fw_dump_ptr += entry->mem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) strcpy(fw_dump_ptr, "\n========End dump========\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) fw_dump_ptr += strlen("\n========End dump========\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) vfree(mem_type_mapping_tbl[idx].mem_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) mem_type_mapping_tbl[idx].mem_ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) /* fw_dump_data will be free in device coredump release function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * after 5 min
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) dev_coredumpv(&card->func->dev, fw_dump_data, fw_dump_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) static int btmrvl_sdio_probe(struct sdio_func *func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) const struct sdio_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct btmrvl_private *priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct btmrvl_sdio_card *card = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) id->vendor, id->device, id->class, func->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (!card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) card->func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (id->driver_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) struct btmrvl_sdio_device *data = (void *) id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) card->helper = data->helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) card->firmware = data->firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) card->reg = data->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) card->support_pscan_win_report = data->support_pscan_win_report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) card->supports_fw_dump = data->supports_fw_dump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) if (btmrvl_sdio_register_dev(card) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) BT_ERR("Failed to register BT device!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /* Disable the interrupts on the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) btmrvl_sdio_disable_host_int(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) if (btmrvl_sdio_download_fw(card)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) BT_ERR("Downloading firmware failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) goto unreg_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) btmrvl_sdio_enable_host_int(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) /* Device tree node parsing and platform specific configuration*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) btmrvl_sdio_probe_of(&func->dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) priv = btmrvl_add_card(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (!priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) BT_ERR("Initializing card failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) goto disable_host_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) card->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* Initialize the interface specific function pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) priv->hw_host_to_card = btmrvl_sdio_host_to_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) priv->hw_process_int_status = btmrvl_sdio_process_int_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (btmrvl_register_hdev(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) BT_ERR("Register hdev failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) goto disable_host_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) disable_host_int:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) btmrvl_sdio_disable_host_int(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) unreg_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) btmrvl_sdio_unregister_dev(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) static void btmrvl_sdio_remove(struct sdio_func *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) struct btmrvl_sdio_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) card = sdio_get_drvdata(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (card) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /* Send SHUTDOWN command & disable interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) * if user removes the module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (user_rmmod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) btmrvl_send_module_cfg_cmd(card->priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) MODULE_SHUTDOWN_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) btmrvl_sdio_disable_host_int(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) BT_DBG("unregister dev");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) card->priv->surprise_removed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) btmrvl_sdio_unregister_dev(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) btmrvl_remove_card(card->priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) static int btmrvl_sdio_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) struct sdio_func *func = dev_to_sdio_func(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) struct btmrvl_sdio_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) struct btmrvl_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) mmc_pm_flag_t pm_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) struct hci_dev *hcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) pm_flags = sdio_get_host_pm_caps(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) pm_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (!(pm_flags & MMC_PM_KEEP_POWER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) BT_ERR("%s: cannot remain alive while suspended",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) sdio_func_id(func));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) card = sdio_get_drvdata(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (!card || !card->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) BT_ERR("card or priv structure is not valid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) BT_ERR("sdio_func is not specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) /* Enable platform specific wakeup interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) card->plt_wake_cfg->wake_by_bt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) enable_irq(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) enable_irq_wake(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) priv = card->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) priv->adapter->is_suspending = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) hcidev = priv->btmrvl_dev.hcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) BT_DBG("%s: SDIO suspend", hcidev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) hci_suspend_dev(hcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (priv->adapter->hs_state != HS_ACTIVATED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) if (btmrvl_enable_hs(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) BT_ERR("HS not activated, suspend failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /* Disable platform specific wakeup interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (card->plt_wake_cfg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) card->plt_wake_cfg->irq_bt >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) disable_irq_wake(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) disable_irq(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) priv->adapter->is_suspending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) priv->adapter->is_suspending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) priv->adapter->is_suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) /* We will keep the power when hs enabled successfully */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (priv->adapter->hs_state == HS_ACTIVATED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) BT_DBG("suspend with MMC_PM_KEEP_POWER");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) BT_DBG("suspend without MMC_PM_KEEP_POWER");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) static int btmrvl_sdio_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) struct sdio_func *func = dev_to_sdio_func(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) struct btmrvl_sdio_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) struct btmrvl_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) mmc_pm_flag_t pm_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) struct hci_dev *hcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) pm_flags = sdio_get_host_pm_caps(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) pm_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) card = sdio_get_drvdata(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) if (!card || !card->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) BT_ERR("card or priv structure is not valid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) BT_ERR("sdio_func is not specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) priv = card->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) if (!priv->adapter->is_suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) BT_DBG("device already resumed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) priv->hw_wakeup_firmware(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) priv->adapter->hs_state = HS_DEACTIVATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) hcidev = priv->btmrvl_dev.hcidev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) priv->adapter->is_suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) BT_DBG("%s: SDIO resume", hcidev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) hci_resume_dev(hcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) /* Disable platform specific wakeup interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) device_may_wakeup(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) disable_irq_wake(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) disable_irq(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) if (card->plt_wake_cfg->wake_by_bt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) /* Undo our disable, since interrupt handler already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) * did this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) enable_irq(card->plt_wake_cfg->irq_bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) static const struct dev_pm_ops btmrvl_sdio_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) .suspend = btmrvl_sdio_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) .resume = btmrvl_sdio_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) static struct sdio_driver bt_mrvl_sdio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) .name = "btmrvl_sdio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) .id_table = btmrvl_sdio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) .probe = btmrvl_sdio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) .remove = btmrvl_sdio_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) .coredump = btmrvl_sdio_coredump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) .pm = &btmrvl_sdio_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) static int __init btmrvl_sdio_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) BT_ERR("SDIO Driver Registration Failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) /* Clear the flag in case user removes the card. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) user_rmmod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) static void __exit btmrvl_sdio_exit_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) /* Set the flag as user is removing this module. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) user_rmmod = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) sdio_unregister_driver(&bt_mrvl_sdio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) module_init(btmrvl_sdio_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) module_exit(btmrvl_sdio_exit_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) MODULE_AUTHOR("Marvell International Ltd.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) MODULE_VERSION(VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) MODULE_FIRMWARE("mrvl/sd8688.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) MODULE_FIRMWARE("mrvl/sdsd8977_combo_v2.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) MODULE_FIRMWARE("mrvl/sd8987_uapsta.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) MODULE_FIRMWARE("mrvl/sdsd8997_combo_v4.bin");