ath3k.c revision 9498ba7a1d38d42eef4ef6d906ab1743c9f0fd6f
19670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri/* 29670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * Copyright (c) 2008-2009 Atheros Communications Inc. 39670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * 49670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * This program is free software; you can redistribute it and/or modify 59670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * it under the terms of the GNU General Public License as published by 69670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * the Free Software Foundation; either version 2 of the License, or 79670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * (at your option) any later version. 89670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * 99670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * This program is distributed in the hope that it will be useful, 109670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * but WITHOUT ANY WARRANTY; without even the implied warranty of 119670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 129670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * GNU General Public License for more details. 139670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * 149670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * You should have received a copy of the GNU General Public License 159670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * along with this program; if not, write to the Free Software 169670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 179670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri * 189670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri */ 199670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 209670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 219670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/module.h> 229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/kernel.h> 239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/init.h> 249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/slab.h> 259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/types.h> 269670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/errno.h> 279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/device.h> 289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/firmware.h> 299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <linux/usb.h> 309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#include <net/bluetooth/bluetooth.h> 319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define VERSION "1.0" 33c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser#define ATH3K_FIRMWARE "ath3k-1.fw" 349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 35d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_DNLOAD 0x01 36d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_GETSTATE 0x05 37d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_SET_NORMAL_MODE 0x07 38d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_GETVERSION 0x09 39d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define USB_REG_SWITCH_VID_PID 0x0a 40d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 41d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_MODE_MASK 0x3F 42d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_NORMAL_MODE 0x0E 43d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 44d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_PATCH_UPDATE 0x80 45d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_SYSCFG_UPDATE 0x40 46d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 47d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_26M 0x00 48d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_40M 0x01 49d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_19P2 0x02 50d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_NAME_LEN 0xFF 51d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 52d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstruct ath3k_version { 53d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int rom_version; 54d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int build_version; 55d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int ram_version; 56d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char ref_clock; 57d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char reserved[0x07]; 58d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 599670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 609670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_device_id ath3k_table[] = { 619670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri /* Atheros AR3011 */ 629670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { USB_DEVICE(0x0CF3, 0x3000) }, 63be93112accb42c5586a459683d71975cc70673caBala Shanmugam 64be93112accb42c5586a459683d71975cc70673caBala Shanmugam /* Atheros AR3011 with sflash firmware*/ 65be93112accb42c5586a459683d71975cc70673caBala Shanmugam { USB_DEVICE(0x0CF3, 0x3002) }, 662a7bccccdb9604a717c2128a931f022267d35629Andy Ross { USB_DEVICE(0x13d3, 0x3304) }, 678e7c3d2e4ba18ee4cdcc1f89aec944fbff4ce735Ricardo Mendoza { USB_DEVICE(0x0930, 0x0215) }, 686b6ba88b5bb8779156b21bb957520a448c3642e2Keng-Yu Lin { USB_DEVICE(0x0489, 0xE03D) }, 69be93112accb42c5586a459683d71975cc70673caBala Shanmugam 70509e7861d8a5e26bb07b5a3a13e2b9e442283631Cho, Yu-Chen /* Atheros AR9285 Malbec with sflash firmware */ 71509e7861d8a5e26bb07b5a3a13e2b9e442283631Cho, Yu-Chen { USB_DEVICE(0x03F0, 0x311D) }, 72d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 73d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 74d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0CF3, 0x3004) }, 759498ba7a1d38d42eef4ef6d906ab1743c9f0fd6fEran { USB_DEVICE(0x13d3, 0x3375) }, 76d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 77e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen /* Atheros AR5BBU12 with sflash firmware */ 78e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen { USB_DEVICE(0x0489, 0xE02C) }, 79b67afe7f43afd2f5cd98798993561920c1684c12John W. Linville 809670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { } /* Terminating entry */ 819670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 829670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 839670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DEVICE_TABLE(usb, ath3k_table); 849670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 85d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define BTUSB_ATH3012 0x80 86d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam/* This table is to load patch and sysconfig files 87d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam * for AR3012 */ 88d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic struct usb_device_id ath3k_blist_tbl[] = { 89d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 90d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 91d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, 929498ba7a1d38d42eef4ef6d906ab1743c9f0fd6fEran { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, 93d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 94d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { } /* Terminating entry */ 95d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 96d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 979670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define USB_REQ_DFU_DNLOAD 1 989670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define BULK_SIZE 4096 99d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define FW_HDR_SIZE 20 1009670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Hollerstatic int ath3k_load_firmware(struct usb_device *udev, 10286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler const struct firmware *firmware) 1039670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 1049670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri u8 *send_buf; 1059670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri int err, pipe, len, size, sent = 0; 10686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler int count = firmware->size; 1079670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_DBG("udev %p", udev); 1099670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndctrlpipe(udev, 0); 1119670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11252a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 11386e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if (!send_buf) { 11486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_ERR("Can't allocate memory chunk for firmware"); 11586e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler return -ENOMEM; 11686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler } 11786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler 11886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data, 20); 11986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if ((err = usb_control_msg(udev, pipe, 1209670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_REQ_DFU_DNLOAD, 1219670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_TYPE_VENDOR, 0, 0, 12286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { 1239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Can't change to loading configuration err"); 12486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler goto error; 1259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1269670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += 20; 1279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= 20; 1289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri while (count) { 1309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri size = min_t(uint, count, BULK_SIZE); 13186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndbulkpipe(udev, 0x02); 13286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data + sent, size); 1339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 13486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler err = usb_bulk_msg(udev, pipe, send_buf, size, 1359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri &len, 3000); 1369670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (err || (len != size)) { 1389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Error in firmware loading err = %d," 1399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri "len = %d, size = %d", err, len, size); 1409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri goto error; 1419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1429670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += size; 1449670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= size; 1459670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1469670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1479670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukurierror: 1489670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri kfree(send_buf); 1499670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return err; 1509670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 1519670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 152d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_state(struct usb_device *udev, unsigned char *state) 153d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 154d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 155d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 156d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 157d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETSTATE, 158d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, 159d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam state, 0x01, USB_CTRL_SET_TIMEOUT); 160d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 161d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 162d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_version(struct usb_device *udev, 163d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version *version) 164d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 165d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 166d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 167d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 168d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETVERSION, 169d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, 170d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sizeof(struct ath3k_version), 171d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_CTRL_SET_TIMEOUT); 172d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 173d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 174d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_fwfile(struct usb_device *udev, 175d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware) 176d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 177d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam u8 *send_buf; 178d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int err, pipe, len, size, count, sent = 0; 179d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 180d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 181d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count = firmware->size; 182d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 18352a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 184d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!send_buf) { 185d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't allocate memory chunk for firmware"); 186d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -ENOMEM; 187d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 188d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 189d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, FW_HDR_SIZE); 190d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data, size); 191d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 192d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 193d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, 194d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, send_buf, 195d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size, USB_CTRL_SET_TIMEOUT); 196d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 197d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't change to loading configuration err"); 198d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 199d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 200d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 201d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 202d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 203d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 204d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 205d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam while (count) { 206d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, BULK_SIZE); 207d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndbulkpipe(udev, 0x02); 208d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 209d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data + sent, size); 210d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 211d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam err = usb_bulk_msg(udev, pipe, send_buf, size, 212d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam &len, 3000); 213d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (err || (len != size)) { 214d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Error in firmware loading err = %d," 215d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam "len = %d, size = %d", err, len, size); 216d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 217d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return err; 218d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 219d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 220d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 221d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 222d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 223d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 224d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 225d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 226d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 227d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_switch_pid(struct usb_device *udev) 228d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 229d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 230d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 231d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 232d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, 233d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 234d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 235d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 236d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 237d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_set_normal_mode(struct usb_device *udev) 238d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 239d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 240d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0, ret; 241d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 242d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 243d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 244d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to normal mode err"); 245d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 246d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 247d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 248d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) { 249d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("firmware was already in normal mode"); 250d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 251d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 252d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 253d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 254d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, 255d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 256d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 257d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 258d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 259d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_patch(struct usb_device *udev) 260d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 261d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 262d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 263d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 264d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version, pt_version; 265d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 266d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 267d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 268d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 269d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load ram patch err"); 270d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 271d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 272d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 273d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (fw_state & ATH3K_PATCH_UPDATE) { 274d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("Patch was already downloaded"); 275d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 276d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 277d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 278d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 279d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 280d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 281d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 282d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 283d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 284d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", 285d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version); 286d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 287d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 288d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 289d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file not found %s", filename); 290d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 291d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 292d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 293d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); 294d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.build_version = *(int *) 295d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (firmware->data + firmware->size - 4); 296d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 297d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((pt_version.rom_version != fw_version.rom_version) || 298d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (pt_version.build_version <= fw_version.build_version)) { 299d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file version did not match with firmware"); 300d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 301d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EINVAL; 302d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 303d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 304d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 305d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 306d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 307d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 308d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 309d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 310d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_syscfg(struct usb_device *udev) 311d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 312d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 313d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 314d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 315d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version; 316d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int clk_value, ret; 317d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 318d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 319d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 320d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load configration err"); 321d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EBUSY; 322d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 323d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 324d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 325d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 326d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 327d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 328d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 329d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 330d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam switch (fw_version.ref_clock) { 331d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 332d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_26M: 333d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 26; 334d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 335d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_40M: 336d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 40; 337d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 338d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_19P2: 339d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 19; 340d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 341d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam default: 342d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 0; 343d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 344d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 345d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 346d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", 347d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version, clk_value, ".dfu"); 348d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 349d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 350d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 351d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Configuration file not found %s", filename); 352d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 353d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 354d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 355d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 356d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 357d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 358d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 359d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 360d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 3619670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic int ath3k_probe(struct usb_interface *intf, 3629670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct usb_device_id *id) 3639670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 3649670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct firmware *firmware; 3659670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri struct usb_device *udev = interface_to_usbdev(intf); 36684f0e17f78471857104a20dfc57711409f68d7bfRogério Brito int ret; 3679670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3689670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("intf %p id %p", intf, id); 3699670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3709670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (intf->cur_altsetting->desc.bInterfaceNumber != 0) 3719670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return -ENODEV; 3729670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 373d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* match device ID in ath3k blacklist table */ 374d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!id->driver_info) { 375d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct usb_device_id *match; 376d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam match = usb_match_id(intf, ath3k_blist_tbl); 377d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (match) 378d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam id = match; 379d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 380d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 381d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* load patch and sysconfig files for AR3012 */ 382d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (id->driver_info & BTUSB_ATH3012) { 3832d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 3842d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li /* New firmware with patch and sysconfig files already loaded */ 3852d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) 3862d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li return -ENODEV; 3872d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 388d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_patch(udev); 389d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 390d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading patch file failed"); 391d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 392d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 393d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_syscfg(udev); 394d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 395d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading sysconfig file failed"); 396d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 397d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 398d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_set_normal_mode(udev); 399d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 400d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Set normal mode failed"); 401d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 402d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 403d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ath3k_switch_pid(udev); 404d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 405d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 406d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 407c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev); 408c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret < 0) { 409c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret == -ENOENT) 410c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" not found", 411c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE); 412c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser else 413c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" request failed (err=%d)", 414c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE, ret); 415c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser return ret; 4169670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 4179670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 41884f0e17f78471857104a20dfc57711409f68d7bfRogério Brito ret = ath3k_load_firmware(udev, firmware); 41986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler release_firmware(firmware); 4209670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42184f0e17f78471857104a20dfc57711409f68d7bfRogério Brito return ret; 4229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic void ath3k_disconnect(struct usb_interface *intf) 4259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 4269670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("ath3k_disconnect intf %p", intf); 4279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_driver ath3k_driver = { 4309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .name = "ath3k", 4319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .probe = ath3k_probe, 4329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .disconnect = ath3k_disconnect, 4339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .id_table = ath3k_table, 4349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 4359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 43693f1508cffc3d578c2b7bbbf298dc52326b80777Greg Kroah-Hartmanmodule_usb_driver(ath3k_driver); 4379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_AUTHOR("Atheros Communications"); 4399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DESCRIPTION("Atheros AR30xx firmware driver"); 4409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_VERSION(VERSION); 4419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_LICENSE("GPL"); 442c3eae82a844bb33e8182c7ee81828516b51ad642Paul FertserMODULE_FIRMWARE(ATH3K_FIRMWARE); 443