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) }, 7755ed7d4d1469eafbe3ad7e8fcd44f5af27845a81AceLan Kao { USB_DEVICE(0x04CA, 0x3005) }, 7887522a433ba6886b5ccbb497e0a7cb8097def64eAceLan Kao { USB_DEVICE(0x13d3, 0x3362) }, 79ac71311e65e2c4c2dbac76db698fecbee755b016AceLan Kao { USB_DEVICE(0x0CF3, 0xE004) }, 80d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 81e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen /* Atheros AR5BBU12 with sflash firmware */ 82e9036e336a8e5640871e0006ea4a89982b25046fCho, Yu-Chen { USB_DEVICE(0x0489, 0xE02C) }, 83b67afe7f43afd2f5cd98798993561920c1684c12John W. Linville 849670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri { } /* Terminating entry */ 859670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 869670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 879670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DEVICE_TABLE(usb, ath3k_table); 889670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 89d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define BTUSB_ATH3012 0x80 90d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam/* This table is to load patch and sysconfig files 91d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam * for AR3012 */ 92d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic struct usb_device_id ath3k_blist_tbl[] = { 93d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 94d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* Atheros AR3012 with sflash firmware*/ 95d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, 9607c0ea874d43c299d185948452945a361052b6e3Cho, Yu-Chen { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, 979498ba7a1d38d42eef4ef6d906ab1743c9f0fd6fEran { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, 9855ed7d4d1469eafbe3ad7e8fcd44f5af27845a81AceLan Kao { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, 9987522a433ba6886b5ccbb497e0a7cb8097def64eAceLan Kao { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, 100ac71311e65e2c4c2dbac76db698fecbee755b016AceLan Kao { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, 101d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 102d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam { } /* Terminating entry */ 103d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam}; 104d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 1059670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define USB_REQ_DFU_DNLOAD 1 1069670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri#define BULK_SIZE 4096 107d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam#define FW_HDR_SIZE 20 1089670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 10986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Hollerstatic int ath3k_load_firmware(struct usb_device *udev, 11086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler const struct firmware *firmware) 1119670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 1129670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri u8 *send_buf; 1139670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri int err, pipe, len, size, sent = 0; 11486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler int count = firmware->size; 1159670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_DBG("udev %p", udev); 1179670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 11886e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndctrlpipe(udev, 0); 1199670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 12052a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 12186e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if (!send_buf) { 12286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler BT_ERR("Can't allocate memory chunk for firmware"); 12386e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler return -ENOMEM; 12486e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler } 12586e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler 12686e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data, 20); 12786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler if ((err = usb_control_msg(udev, pipe, 1289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_REQ_DFU_DNLOAD, 1299670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri USB_TYPE_VENDOR, 0, 0, 13086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { 1319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Can't change to loading configuration err"); 13286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler goto error; 1339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += 20; 1359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= 20; 1369670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri while (count) { 1389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri size = min_t(uint, count, BULK_SIZE); 13986e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler pipe = usb_sndbulkpipe(udev, 0x02); 14086e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler memcpy(send_buf, firmware->data + sent, size); 1419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 14286e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler err = usb_bulk_msg(udev, pipe, send_buf, size, 1439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri &len, 3000); 1449670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1459670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (err || (len != size)) { 1469670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_ERR("Error in firmware loading err = %d," 1479670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri "len = %d, size = %d", err, len, size); 1489670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri goto error; 1499670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1509670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1519670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri sent += size; 1529670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri count -= size; 1539670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 1549670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 1559670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukurierror: 1569670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri kfree(send_buf); 1579670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return err; 1589670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 1599670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 160d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_state(struct usb_device *udev, unsigned char *state) 161d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 162d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 163d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 164d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 165d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETSTATE, 166d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, 167d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam state, 0x01, USB_CTRL_SET_TIMEOUT); 168d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 169d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 170d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_get_version(struct usb_device *udev, 171d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version *version) 172d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 173d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 174d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 175d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_rcvctrlpipe(udev, 0); 176d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_GETVERSION, 177d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, 178d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sizeof(struct ath3k_version), 179d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_CTRL_SET_TIMEOUT); 180d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 181d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 182d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_fwfile(struct usb_device *udev, 183d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware) 184d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 185d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam u8 *send_buf; 186d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int err, pipe, len, size, count, sent = 0; 187d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 188d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 189d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count = firmware->size; 190d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 19152a1020e80beece986002f673eca24dae6255b55David Herrmann send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); 192d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!send_buf) { 193d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't allocate memory chunk for firmware"); 194d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -ENOMEM; 195d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 196d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 197d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, FW_HDR_SIZE); 198d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data, size); 199d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 200d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 201d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, 202d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, send_buf, 203d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size, USB_CTRL_SET_TIMEOUT); 204d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 205d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't change to loading configuration err"); 206d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 207d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 208d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 209d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 210d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 211d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 212d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 213d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam while (count) { 214d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam size = min_t(uint, count, BULK_SIZE); 215d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndbulkpipe(udev, 0x02); 216d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 217d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam memcpy(send_buf, firmware->data + sent, size); 218d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 219d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam err = usb_bulk_msg(udev, pipe, send_buf, size, 220d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam &len, 3000); 221d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (err || (len != size)) { 222d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Error in firmware loading err = %d," 223d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam "len = %d, size = %d", err, len, size); 224d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 225d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return err; 226d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 227d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam sent += size; 228d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam count -= size; 229d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 230d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 231d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam kfree(send_buf); 232d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 233d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 234d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 235d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_switch_pid(struct usb_device *udev) 236d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 237d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0; 238d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 239d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 240d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, 241d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 242d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 243d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 244d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 245d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_set_normal_mode(struct usb_device *udev) 246d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 247d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 248d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int pipe = 0, ret; 249d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 250d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 251d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 252d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to normal mode err"); 253d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 254d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 255d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 256d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) { 257d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("firmware was already in normal mode"); 258d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 259d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 260d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 261d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pipe = usb_sndctrlpipe(udev, 0); 262d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, 263d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam USB_TYPE_VENDOR, 0, 0, 264d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam NULL, 0, USB_CTRL_SET_TIMEOUT); 265d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 266d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 267d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_patch(struct usb_device *udev) 268d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 269d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 270d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 271d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 272d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version, pt_version; 273d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int ret; 274d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 275d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 276d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 277d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load ram patch err"); 278d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 279d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 280d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 281d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (fw_state & ATH3K_PATCH_UPDATE) { 282d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_DBG("Patch was already downloaded"); 283d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 284d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 285d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 286d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 287d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 288d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 289d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 290d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 291d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 292d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", 293d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version); 294d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 295d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 296d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 297d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file not found %s", filename); 298d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 299d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 300d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 301d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); 302d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam pt_version.build_version = *(int *) 303d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (firmware->data + firmware->size - 4); 304d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 305d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if ((pt_version.rom_version != fw_version.rom_version) || 306d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam (pt_version.build_version <= fw_version.build_version)) { 307d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Patch file version did not match with firmware"); 308d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 309d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EINVAL; 310d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 311d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 312d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 313d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 314d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 315d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 316d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 317d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 318d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugamstatic int ath3k_load_syscfg(struct usb_device *udev) 319d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam{ 320d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam unsigned char fw_state; 321d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam char filename[ATH3K_NAME_LEN] = {0}; 322d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct firmware *firmware; 323d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam struct ath3k_version fw_version; 324d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam int clk_value, ret; 325d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 326d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_state(udev, &fw_state); 327d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 328d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get state to change to load configration err"); 329d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return -EBUSY; 330d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 331d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 332d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_get_version(udev, &fw_version); 333d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 334d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Can't get version to change to load ram patch err"); 335d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 336d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 337d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 338d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam switch (fw_version.ref_clock) { 339d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 340d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_26M: 341d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 26; 342d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 343d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_40M: 344d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 40; 345d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 346d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam case ATH3K_XTAL_FREQ_19P2: 347d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 19; 348d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 349d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam default: 350d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam clk_value = 0; 351d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam break; 352d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 353d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 354d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", 355d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam fw_version.rom_version, clk_value, ".dfu"); 356d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 357d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = request_firmware(&firmware, filename, &udev->dev); 358d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 359d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Configuration file not found %s", filename); 360d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 361d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 362d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 363d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_fwfile(udev, firmware); 364d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam release_firmware(firmware); 365d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 366d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 367d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam} 368d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 3699670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic int ath3k_probe(struct usb_interface *intf, 3709670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct usb_device_id *id) 3719670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 3729670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri const struct firmware *firmware; 3739670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri struct usb_device *udev = interface_to_usbdev(intf); 37484f0e17f78471857104a20dfc57711409f68d7bfRogério Brito int ret; 3759670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3769670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("intf %p id %p", intf, id); 3779670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 3789670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri if (intf->cur_altsetting->desc.bInterfaceNumber != 0) 3799670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri return -ENODEV; 3809670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 381d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* match device ID in ath3k blacklist table */ 382d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (!id->driver_info) { 383d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam const struct usb_device_id *match; 384d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam match = usb_match_id(intf, ath3k_blist_tbl); 385d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (match) 386d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam id = match; 387d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 388d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 389d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam /* load patch and sysconfig files for AR3012 */ 390d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (id->driver_info & BTUSB_ATH3012) { 3912d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 3922d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li /* New firmware with patch and sysconfig files already loaded */ 3932d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) 3942d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li return -ENODEV; 3952d25f8b462f3b849d8913d02978657ef06e67dd8Steven.Li 396d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_patch(udev); 397d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 398d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading patch file failed"); 399d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 400d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 401d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_load_syscfg(udev); 402d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 403d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Loading sysconfig file failed"); 404d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 405d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 406d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ret = ath3k_set_normal_mode(udev); 407d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam if (ret < 0) { 408d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam BT_ERR("Set normal mode failed"); 409d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return ret; 410d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 411d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam ath3k_switch_pid(udev); 412d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam return 0; 413d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam } 414d9f51b51db2064c9049bf7924318fd8c6ed852cbBala Shanmugam 415c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev); 416c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret < 0) { 417c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser if (ret == -ENOENT) 418c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" not found", 419c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE); 420c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser else 421c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser BT_ERR("Firmware file \"%s\" request failed (err=%d)", 422c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser ATH3K_FIRMWARE, ret); 423c3eae82a844bb33e8182c7ee81828516b51ad642Paul Fertser return ret; 4249670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri } 4259670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42684f0e17f78471857104a20dfc57711409f68d7bfRogério Brito ret = ath3k_load_firmware(udev, firmware); 42786e09287e4f8c81831b4d4118a48597565f0d21bAlexander Holler release_firmware(firmware); 4289670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 42984f0e17f78471857104a20dfc57711409f68d7bfRogério Brito return ret; 4309670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4319670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4329670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic void ath3k_disconnect(struct usb_interface *intf) 4339670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri{ 4349670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri BT_DBG("ath3k_disconnect intf %p", intf); 4359670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri} 4369670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4379670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuristatic struct usb_driver ath3k_driver = { 4389670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .name = "ath3k", 4399670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .probe = ath3k_probe, 4409670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .disconnect = ath3k_disconnect, 4419670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri .id_table = ath3k_table, 4429670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri}; 4439670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 44493f1508cffc3d578c2b7bbbf298dc52326b80777Greg Kroah-Hartmanmodule_usb_driver(ath3k_driver); 4459670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram Kandukuri 4469670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_AUTHOR("Atheros Communications"); 4479670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_DESCRIPTION("Atheros AR30xx firmware driver"); 4489670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_VERSION(VERSION); 4499670d80a9a6e24725c4111bef5d6cc7786ad0dc5Vikram KandukuriMODULE_LICENSE("GPL"); 450c3eae82a844bb33e8182c7ee81828516b51ad642Paul FertserMODULE_FIRMWARE(ATH3K_FIRMWARE); 451