ath3k.c revision 93f1508cffc3d578c2b7bbbf298dc52326b80777
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" 339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 34d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_DNLOAD 0x01 35d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_GETSTATE 0x05 36d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_SET_NORMAL_MODE 0x07 37d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_GETVERSION 0x09 38d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define USB_REG_SWITCH_VID_PID 0x0a 39d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 40d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_MODE_MASK 0x3F 41d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_NORMAL_MODE 0x0E 42d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 43d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_PATCH_UPDATE 0x80 44d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_SYSCFG_UPDATE 0x40 45d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 46d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_26M 0x00 47d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_40M 0x01 48d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_XTAL_FREQ_19P2 0x02 49d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define ATH3K_NAME_LEN 0xFF 50d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 51d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstruct ath3k_version { 52d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int rom_version; 53d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int build_version; 54d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned int ram_version; 55d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char ref_clock; 56d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char reserved[0x07]; 57d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 589670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 599670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_device_id ath3k_table[] = { 609670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri /* Atheros AR3011 */ 619670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { USB_DEVICE(0x0CF3, 0x3000) }, 62be93112accb42c5586a459683d71975cc70673caBala Shanmugam 63be93112accb42c5586a459683d71975cc70673caBala Shanmugam /* Atheros AR3011 with sflash firmware*/ 64be93112accb42c5586a459683d71975cc70673caBala Shanmugam { USB_DEVICE(0x0CF3, 0x3002) }, 652a7bccccdb9604a717c2128a931f022267d35629Andy Ross { USB_DEVICE(0x13d3, 0x3304) }, 668e7c3d2e4ba18ee4cdcc1f89aec944fbff4ce735Ricardo Mendoza { USB_DEVICE(0x0930, 0x0215) }, 67be93112accb42c5586a459683d71975cc70673caBala Shanmugam 68509e7861d8a5e26bb07b5a3a13e2b9e442283631Cho, Yu-Chen /* Atheros AR9285 Malbec with sflash firmware */ 69509e7861d8a5e26bb07b5a3a13e2b9e442283631Cho, Yu-Chen { USB_DEVICE(0x03F0, 0x311D) }, 70d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 71d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 72d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0CF3, 0x3004) }, 73d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 74e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen /* Atheros AR5BBU12 with sflash firmware */ 75e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen { USB_DEVICE(0x0489, 0xE02C) }, 76b67afe7f43afd2f5cd98798993561920c1684c12John W. Linville 779670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { } /* Terminating entry */ 789670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 799670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 809670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DEVICE_TABLE(usb, ath3k_table); 819670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 82d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define BTUSB_ATH3012 0x80 83d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam/* This table is to load patch and sysconfig files 84d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam * for AR3012 */ 85d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic struct usb_device_id ath3k_blist_tbl[] = { 86d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 87d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 88d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, 89d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 90d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { } /* Terminating entry */ 91d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 92d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 939670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define USB_REQ_DFU_DNLOAD 1 949670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define BULK_SIZE 4096 95d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define FW_HDR_SIZE 20 969670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 9786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Hollerstatic int ath3k_load_firmware(struct usb_device *udev, 9886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler const struct firmware *firmware) 999670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 1009670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri u8 *send_buf; 1019670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri int err, pipe, len, size, sent = 0; 10286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler int count = firmware->size; 1039670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_DBG("udev %p", udev); 1059670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndctrlpipe(udev, 0); 1079670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1080ba22bb258341783939ed07bf7e7a9d92f3b0edfDavid Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 10986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if (!send_buf) { 11086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_ERR("Can't allocate memory chunk for firmware"); 11186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler return -ENOMEM; 11286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler } 11386e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler 11486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data, 20); 11586e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if ((err = usb_control_msg(udev, pipe, 1169670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_REQ_DFU_DNLOAD, 1179670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_TYPE_VENDOR, 0, 0, 11886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { 1199670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Can't change to loading configuration err"); 12086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler goto error; 1219670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += 20; 1239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= 20; 1249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri while (count) { 1269670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri size = min_t(uint, count, BULK_SIZE); 12786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndbulkpipe(udev, 0x02); 12886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data + sent, size); 1299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 13086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler err = usb_bulk_msg(udev, pipe, send_buf, size, 1319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri &len, 3000); 1329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (err || (len != size)) { 1349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Error in firmware loading err = %d," 1359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri "len = %d, size = %d", err, len, size); 1369670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri goto error; 1379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += size; 1409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= size; 1419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1429670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukurierror: 1449670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri kfree(send_buf); 1459670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return err; 1469670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 1479670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 148d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_state(struct usb_device *udev, unsigned char *state) 149d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 150d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 151d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 152d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 153d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETSTATE, 154d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, 155d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam state, 0x01, USB_CTRL_SET_TIMEOUT); 156d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 157d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 158d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_version(struct usb_device *udev, 159d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version *version) 160d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 161d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 162d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 163d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 164d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETVERSION, 165d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, 166d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sizeof(struct ath3k_version), 167d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_CTRL_SET_TIMEOUT); 168d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 169d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 170d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_fwfile(struct usb_device *udev, 171d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware) 172d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 173d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam u8 *send_buf; 174d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int err, pipe, len, size, count, sent = 0; 175d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 176d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 177d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count = firmware->size; 178d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 1790ba22bb258341783939ed07bf7e7a9d92f3b0edfDavid Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 180d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!send_buf) { 181d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't allocate memory chunk for firmware"); 182d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -ENOMEM; 183d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 184d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 185d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, FW_HDR_SIZE); 186d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data, size); 187d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 188d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 189d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, 190d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, send_buf, 191d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size, USB_CTRL_SET_TIMEOUT); 192d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 193d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't change to loading configuration err"); 194d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 195d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 196d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 197d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 198d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 199d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 200d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 201d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam while (count) { 202d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, BULK_SIZE); 203d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndbulkpipe(udev, 0x02); 204d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 205d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data + sent, size); 206d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 207d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam err = usb_bulk_msg(udev, pipe, send_buf, size, 208d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam &len, 3000); 209d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (err || (len != size)) { 210d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Error in firmware loading err = %d," 211d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam "len = %d, size = %d", err, len, size); 212d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 213d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return err; 214d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 215d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 216d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 217d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 218d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 219d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 220d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 221d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 222d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 223d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_switch_pid(struct usb_device *udev) 224d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 225d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 226d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 227d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 228d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, 229d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 230d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 231d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 232d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 233d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_set_normal_mode(struct usb_device *udev) 234d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 235d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 236d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0, ret; 237d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 238d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 239d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 240d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to normal mode err"); 241d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 242d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 243d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 244d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) { 245d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("firmware was already in normal mode"); 246d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 247d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 248d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 249d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 250d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, 251d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 252d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 253d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 254d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 255d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_patch(struct usb_device *udev) 256d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 257d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 258d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 259d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 260d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version, pt_version; 261d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 262d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 263d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 264d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 265d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load ram patch err"); 266d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 267d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 268d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 269d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (fw_state & ATH3K_PATCH_UPDATE) { 270d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("Patch was already downloaded"); 271d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 272d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 273d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 274d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 275d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 276d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 277d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 278d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 279d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 280d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", 281d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version); 282d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 283d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 284d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 285d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file not found %s", filename); 286d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 287d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 288d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 289d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); 290d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.build_version = *(int *) 291d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (firmware->data + firmware->size - 4); 292d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 293d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((pt_version.rom_version != fw_version.rom_version) || 294d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (pt_version.build_version <= fw_version.build_version)) { 295d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file version did not match with firmware"); 296d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 297d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EINVAL; 298d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 299d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 300d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 301d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 302d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 303d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 304d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 305d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 306d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_syscfg(struct usb_device *udev) 307d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 308d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 309d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 310d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 311d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version; 312d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int clk_value, ret; 313d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 314d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 315d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 316d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load configration err"); 317d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EBUSY; 318d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 319d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 320d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 321d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 322d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 323d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 324d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 325d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 326d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam switch (fw_version.ref_clock) { 327d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 328d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_26M: 329d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 26; 330d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 331d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_40M: 332d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 40; 333d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 334d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_19P2: 335d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 19; 336d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 337d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam default: 338d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 0; 339d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 340d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 341d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 342d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", 343d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version, clk_value, ".dfu"); 344d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 345d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 346d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 347d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Configuration file not found %s", filename); 348d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 349d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 350d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 351d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 352d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 353d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 354d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 355d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 356d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 3579670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic int ath3k_probe(struct usb_interface *intf, 3589670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct usb_device_id *id) 3599670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 3609670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct firmware *firmware; 3619670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri struct usb_device *udev = interface_to_usbdev(intf); 36284f0e17f78471857104a20dfc57711409f68d7bfRogério Brito int ret; 3639670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3649670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("intf %p id %p", intf, id); 3659670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3669670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (intf->cur_altsetting->desc.bInterfaceNumber != 0) 3679670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return -ENODEV; 3689670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 369d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* match device ID in ath3k blacklist table */ 370d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!id->driver_info) { 371d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct usb_device_id *match; 372d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam match = usb_match_id(intf, ath3k_blist_tbl); 373d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (match) 374d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam id = match; 375d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 376d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 377d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* load patch and sysconfig files for AR3012 */ 378d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (id->driver_info & BTUSB_ATH3012) { 3792d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 3802d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li /* New firmware with patch and sysconfig files already loaded */ 3812d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) 3822d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li return -ENODEV; 3832d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 384d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_patch(udev); 385d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 386d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading patch file failed"); 387d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 388d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 389d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_syscfg(udev); 390d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 391d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading sysconfig file failed"); 392d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 393d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 394d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_set_normal_mode(udev); 395d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 396d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Set normal mode failed"); 397d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 398d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 399d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ath3k_switch_pid(udev); 400d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 401d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 402d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 4039670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { 404d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Error loading firmware"); 4059670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return -EIO; 4069670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 4079670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 40884f0e17f78471857104a20dfc57711409f68d7bfRogério Brito ret = ath3k_load_firmware(udev, firmware); 40986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler release_firmware(firmware); 4109670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 41184f0e17f78471857104a20dfc57711409f68d7bfRogério Brito return ret; 4129670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4139670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4149670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic void ath3k_disconnect(struct usb_interface *intf) 4159670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 4169670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("ath3k_disconnect intf %p", intf); 4179670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4189670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4199670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_driver ath3k_driver = { 4209670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .name = "ath3k", 4219670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .probe = ath3k_probe, 4229670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .disconnect = ath3k_disconnect, 4239670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .id_table = ath3k_table, 4249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 4259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42693f1508cffc3d578c2b7bbbf298dc52326b80777Greg Kroah-Hartmanmodule_usb_driver(ath3k_driver); 4279670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_AUTHOR("Atheros Communications"); 4299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DESCRIPTION("Atheros AR30xx firmware driver"); 4309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_VERSION(VERSION); 4319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_LICENSE("GPL"); 4329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_FIRMWARE("ath3k-1.fw"); 433