ath3k.c revision 07c0ea874d43c299d185948452945a361052b6e3
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) }, 7507c0ea874d43c299d185948452945a361052b6e3Cho, Yu-Chen { USB_DEVICE(0x0CF3, 0x311D) }, 769498ba7a1d38d42eef4ef6d906ab1743c9f0fd6fEran { USB_DEVICE(0x13d3, 0x3375) }, 77d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 78e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen /* Atheros AR5BBU12 with sflash firmware */ 79e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen { USB_DEVICE(0x0489, 0xE02C) }, 80b67afe7f43afd2f5cd98798993561920c1684c12John W. Linville 819670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { } /* Terminating entry */ 829670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 839670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 849670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DEVICE_TABLE(usb, ath3k_table); 859670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 86d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define BTUSB_ATH3012 0x80 87d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam/* This table is to load patch and sysconfig files 88d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam * for AR3012 */ 89d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic struct usb_device_id ath3k_blist_tbl[] = { 90d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 91d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 92d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, 9307c0ea874d43c299d185948452945a361052b6e3Cho, Yu-Chen { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, 949498ba7a1d38d42eef4ef6d906ab1743c9f0fd6fEran { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, 95d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 96d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { } /* Terminating entry */ 97d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 98d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 999670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define USB_REQ_DFU_DNLOAD 1 1009670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define BULK_SIZE 4096 101d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define FW_HDR_SIZE 20 1029670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10386e09287e4f8c81831b4d4118a48597565f0d21bAlexander Hollerstatic int ath3k_load_firmware(struct usb_device *udev, 10486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler const struct firmware *firmware) 1059670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 1069670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri u8 *send_buf; 1079670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri int err, pipe, len, size, sent = 0; 10886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler int count = firmware->size; 1099670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_DBG("udev %p", udev); 1119670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndctrlpipe(udev, 0); 1139670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11452a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 11586e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if (!send_buf) { 11686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_ERR("Can't allocate memory chunk for firmware"); 11786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler return -ENOMEM; 11886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler } 11986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler 12086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data, 20); 12186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if ((err = usb_control_msg(udev, pipe, 1229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_REQ_DFU_DNLOAD, 1239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_TYPE_VENDOR, 0, 0, 12486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { 1259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Can't change to loading configuration err"); 12686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler goto error; 1279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += 20; 1299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= 20; 1309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri while (count) { 1329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri size = min_t(uint, count, BULK_SIZE); 13386e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndbulkpipe(udev, 0x02); 13486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data + sent, size); 1359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 13686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler err = usb_bulk_msg(udev, pipe, send_buf, size, 1379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri &len, 3000); 1389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (err || (len != size)) { 1409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Error in firmware loading err = %d," 1419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri "len = %d, size = %d", err, len, size); 1429670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri goto error; 1439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1449670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1459670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += size; 1469670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= size; 1479670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1489670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1499670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukurierror: 1509670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri kfree(send_buf); 1519670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return err; 1529670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 1539670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 154d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_state(struct usb_device *udev, unsigned char *state) 155d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 156d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 157d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 158d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 159d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETSTATE, 160d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, 161d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam state, 0x01, USB_CTRL_SET_TIMEOUT); 162d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 163d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 164d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_version(struct usb_device *udev, 165d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version *version) 166d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 167d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 168d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 169d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 170d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETVERSION, 171d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, 172d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sizeof(struct ath3k_version), 173d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_CTRL_SET_TIMEOUT); 174d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 175d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 176d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_fwfile(struct usb_device *udev, 177d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware) 178d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 179d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam u8 *send_buf; 180d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int err, pipe, len, size, count, sent = 0; 181d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 182d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 183d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count = firmware->size; 184d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 18552a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 186d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!send_buf) { 187d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't allocate memory chunk for firmware"); 188d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -ENOMEM; 189d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 190d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 191d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, FW_HDR_SIZE); 192d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data, size); 193d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 194d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 195d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, 196d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, send_buf, 197d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size, USB_CTRL_SET_TIMEOUT); 198d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 199d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't change to loading configuration err"); 200d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 201d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 202d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 203d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 204d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 205d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 206d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 207d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam while (count) { 208d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, BULK_SIZE); 209d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndbulkpipe(udev, 0x02); 210d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 211d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data + sent, size); 212d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 213d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam err = usb_bulk_msg(udev, pipe, send_buf, size, 214d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam &len, 3000); 215d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (err || (len != size)) { 216d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Error in firmware loading err = %d," 217d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam "len = %d, size = %d", err, len, size); 218d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 219d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return err; 220d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 221d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 222d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 223d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 224d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 225d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 226d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 227d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 228d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 229d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_switch_pid(struct usb_device *udev) 230d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 231d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 232d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 233d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 234d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, 235d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 236d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 237d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 238d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 239d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_set_normal_mode(struct usb_device *udev) 240d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 241d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 242d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0, ret; 243d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 244d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 245d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 246d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to normal mode err"); 247d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 248d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 249d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 250d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) { 251d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("firmware was already in normal mode"); 252d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 253d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 254d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 255d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 256d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, 257d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 258d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 259d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 260d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 261d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_patch(struct usb_device *udev) 262d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 263d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 264d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 265d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 266d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version, pt_version; 267d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 268d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 269d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 270d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 271d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load ram patch err"); 272d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 273d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 274d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 275d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (fw_state & ATH3K_PATCH_UPDATE) { 276d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("Patch was already downloaded"); 277d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 278d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 279d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 280d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 281d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 282d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 283d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 284d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 285d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 286d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", 287d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version); 288d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 289d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 290d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 291d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file not found %s", filename); 292d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 293d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 294d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 295d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); 296d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.build_version = *(int *) 297d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (firmware->data + firmware->size - 4); 298d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 299d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((pt_version.rom_version != fw_version.rom_version) || 300d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (pt_version.build_version <= fw_version.build_version)) { 301d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file version did not match with firmware"); 302d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 303d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EINVAL; 304d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 305d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 306d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 307d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 308d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 309d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 310d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 311d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 312d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_syscfg(struct usb_device *udev) 313d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 314d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 315d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 316d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 317d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version; 318d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int clk_value, ret; 319d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 320d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 321d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 322d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load configration err"); 323d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EBUSY; 324d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 325d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 326d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 327d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 328d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 329d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 330d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 331d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 332d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam switch (fw_version.ref_clock) { 333d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 334d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_26M: 335d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 26; 336d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 337d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_40M: 338d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 40; 339d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 340d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_19P2: 341d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 19; 342d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 343d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam default: 344d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 0; 345d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 346d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 347d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 348d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", 349d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version, clk_value, ".dfu"); 350d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 351d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 352d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 353d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Configuration file not found %s", filename); 354d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 355d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 356d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 357d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 358d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 359d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 360d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 361d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 362d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 3639670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic int ath3k_probe(struct usb_interface *intf, 3649670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct usb_device_id *id) 3659670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 3669670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct firmware *firmware; 3679670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri struct usb_device *udev = interface_to_usbdev(intf); 36884f0e17f78471857104a20dfc57711409f68d7bfRogério Brito int ret; 3699670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3709670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("intf %p id %p", intf, id); 3719670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3729670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (intf->cur_altsetting->desc.bInterfaceNumber != 0) 3739670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return -ENODEV; 3749670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 375d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* match device ID in ath3k blacklist table */ 376d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!id->driver_info) { 377d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct usb_device_id *match; 378d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam match = usb_match_id(intf, ath3k_blist_tbl); 379d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (match) 380d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam id = match; 381d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 382d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 383d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* load patch and sysconfig files for AR3012 */ 384d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (id->driver_info & BTUSB_ATH3012) { 3852d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 3862d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li /* New firmware with patch and sysconfig files already loaded */ 3872d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) 3882d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li return -ENODEV; 3892d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 390d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_patch(udev); 391d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 392d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading patch file failed"); 393d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 394d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 395d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_syscfg(udev); 396d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 397d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading sysconfig file failed"); 398d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 399d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 400d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_set_normal_mode(udev); 401d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 402d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Set normal mode failed"); 403d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 404d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 405d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ath3k_switch_pid(udev); 406d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 407d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 408d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 409c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev); 410c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret < 0) { 411c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret == -ENOENT) 412c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" not found", 413c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE); 414c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser else 415c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" request failed (err=%d)", 416c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE, ret); 417c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser return ret; 4189670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 4199670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42084f0e17f78471857104a20dfc57711409f68d7bfRogério Brito ret = ath3k_load_firmware(udev, firmware); 42186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler release_firmware(firmware); 4229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42384f0e17f78471857104a20dfc57711409f68d7bfRogério Brito return ret; 4249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4269670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic void ath3k_disconnect(struct usb_interface *intf) 4279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 4289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("ath3k_disconnect intf %p", intf); 4299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_driver ath3k_driver = { 4329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .name = "ath3k", 4339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .probe = ath3k_probe, 4349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .disconnect = ath3k_disconnect, 4359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .id_table = ath3k_table, 4369670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 4379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 43893f1508cffc3d578c2b7bbbf298dc52326b80777Greg Kroah-Hartmanmodule_usb_driver(ath3k_driver); 4399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_AUTHOR("Atheros Communications"); 4419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DESCRIPTION("Atheros AR30xx firmware driver"); 4429670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_VERSION(VERSION); 4439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_LICENSE("GPL"); 444c3eae82a844bb33e8182c7ee81828516b51ad642Paul FertserMODULE_FIRMWARE(ATH3K_FIRMWARE); 445