mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-12-02 09:16:31 +00:00
Bluetooth: x86-Rome driver support
Add USB client driver support for Rome USB chip. Change-Id: I781dcdc913291ab0695ced1b34fde2710049586e Signed-off-by: Bhasker Neti <bneti@codeaurora.org>
This commit is contained in:
parent
480c71781b
commit
f38c173fe1
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
* Copyright (c) 2014 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -32,6 +33,19 @@
|
||||
#define VERSION "1.0"
|
||||
#define ATH3K_FIRMWARE "ath3k-1.fw"
|
||||
|
||||
#define ROME2_1_USB_RAMPATCH_FILE "ar3k/rampatch_2.1.tlv"
|
||||
#define ROME2_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_2.1.bin"
|
||||
|
||||
#define ROME1_1_USB_RAMPATCH_FILE "ar3k/rampatch_1.1.img"
|
||||
#define ROME1_1_USB_NVM_FILE "ar3k/nvm_tlv_usb_1.1.bin"
|
||||
|
||||
#define ROME2_1_USB_RAMPATCH_HEADER sizeof(struct rome2_1_version)
|
||||
#define ROME1_1_USB_RAMPATCH_HEADER sizeof(struct rome1_1_version)
|
||||
#define ROME1_1_USB_NVM_HEADER 0x04
|
||||
#define ROME2_1_USB_NVM_HEADER 0x04
|
||||
#define ROME2_1_USB_CHIP_VERSION 0x200
|
||||
#define ROME1_1_USB_CHIP_VERSION 0x101
|
||||
|
||||
#define ATH3K_DNLOAD 0x01
|
||||
#define ATH3K_GETSTATE 0x05
|
||||
#define ATH3K_SET_NORMAL_MODE 0x07
|
||||
@ -57,6 +71,34 @@ struct ath3k_version {
|
||||
unsigned char reserved[0x07];
|
||||
};
|
||||
|
||||
struct __packed rome1_1_version {
|
||||
u8 type;
|
||||
u8 length[3];
|
||||
u8 sign_ver;
|
||||
u8 sign_algo;
|
||||
u8 resv1[2];
|
||||
u16 product_id;
|
||||
u16 build_ver;
|
||||
u16 patch_ver;
|
||||
u8 resv2[2];
|
||||
u32 entry_addr;
|
||||
};
|
||||
struct __packed rome2_1_version {
|
||||
u8 type;
|
||||
u8 length[3];
|
||||
u32 total_len;
|
||||
u32 patch_len;
|
||||
u8 sign_ver;
|
||||
u8 sign_algo;
|
||||
u8 resv1[2];
|
||||
u16 product_id;
|
||||
u16 build_ver;
|
||||
u16 patch_ver;
|
||||
u8 resv2[2];
|
||||
u32 entry_addr;
|
||||
};
|
||||
|
||||
|
||||
static struct usb_device_id ath3k_table[] = {
|
||||
/* Atheros AR3011 */
|
||||
{ USB_DEVICE(0x0CF3, 0x3000) },
|
||||
@ -243,8 +285,27 @@ static int ath3k_get_version(struct usb_device *udev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_rome_version(struct usb_device *udev)
|
||||
{
|
||||
struct ath3k_version fw_version;
|
||||
int ret = 0;
|
||||
|
||||
ret = ath3k_get_version(udev, &fw_version);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Failed to get Rome Firmware version");
|
||||
return ret;
|
||||
}
|
||||
if ((fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) ||
|
||||
(fw_version.rom_version == ROME1_1_USB_CHIP_VERSION))
|
||||
ret = fw_version.rom_version;
|
||||
else
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rome_version);
|
||||
|
||||
static int ath3k_load_fwfile(struct usb_device *udev,
|
||||
const struct firmware *firmware)
|
||||
const struct firmware *firmware, int header_h)
|
||||
{
|
||||
u8 *send_buf;
|
||||
int err, pipe, len, size, count, sent = 0;
|
||||
@ -258,7 +319,7 @@ static int ath3k_load_fwfile(struct usb_device *udev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
size = min_t(uint, count, FW_HDR_SIZE);
|
||||
size = min_t(uint, count, header_h);
|
||||
memcpy(send_buf, firmware->data, size);
|
||||
|
||||
pipe = usb_sndctrlpipe(udev, 0);
|
||||
@ -334,6 +395,8 @@ static int ath3k_load_patch(struct usb_device *udev)
|
||||
char filename[ATH3K_NAME_LEN] = {0};
|
||||
const struct firmware *firmware;
|
||||
struct ath3k_version fw_version, pt_version;
|
||||
struct rome2_1_version *rome2_1_version;
|
||||
struct rome1_1_version *rome1_1_version;
|
||||
int ret;
|
||||
|
||||
ret = ath3k_get_state(udev, &fw_state);
|
||||
@ -352,20 +415,45 @@ static int ath3k_load_patch(struct usb_device *udev)
|
||||
BT_ERR("Can't get version to change to load ram patch err");
|
||||
return ret;
|
||||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
|
||||
if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) {
|
||||
BT_DBG("Chip Detected as ROME1.1");
|
||||
snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_RAMPATCH_FILE);
|
||||
} else if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) {
|
||||
BT_DBG("Chip Detected as ROME2.1");
|
||||
snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_RAMPATCH_FILE);
|
||||
} else {
|
||||
BT_DBG("Chip Detected as Ath3k");
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
|
||||
fw_version.rom_version);
|
||||
|
||||
}
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Patch file not found %s", filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
|
||||
pt_version.build_version = *(int *)
|
||||
if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION) {
|
||||
rome2_1_version = (struct rome2_1_version *) firmware->data;
|
||||
pt_version.rom_version = rome2_1_version->build_ver;
|
||||
pt_version.build_version = rome2_1_version->patch_ver;
|
||||
BT_DBG("pt_ver.rom2.1_ver : 0x%x", pt_version.rom_version);
|
||||
BT_DBG("pt_ver.build2.1_ver: 0x%x", pt_version.build_version);
|
||||
BT_DBG("fw_ver.rom2.1_ver: 0x%x", fw_version.rom_version);
|
||||
BT_DBG("fw_ver.build2.1_ver: 0x%x", fw_version.build_version);
|
||||
} else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION) {
|
||||
rome1_1_version = (struct rome1_1_version *) firmware->data;
|
||||
pt_version.build_version = rome1_1_version->build_ver;
|
||||
pt_version.rom_version = rome1_1_version->patch_ver;
|
||||
BT_DBG("pt_ver.rom1.1_ver : 0x%x", pt_version.rom_version);
|
||||
BT_DBG("pt_ver.build1.1_ver: 0x%x", pt_version.build_version);
|
||||
BT_DBG("fw_ver.rom1.1_ver: 0x%x", fw_version.rom_version);
|
||||
BT_DBG("fw_ver.build1.1_ver: 0x%x", fw_version.build_version);
|
||||
} else {
|
||||
pt_version.rom_version = *(int *)(firmware->data +
|
||||
firmware->size - 8);
|
||||
pt_version.build_version = *(int *)
|
||||
(firmware->data + firmware->size - 4);
|
||||
|
||||
}
|
||||
if ((pt_version.rom_version != fw_version.rom_version) ||
|
||||
(pt_version.build_version <= fw_version.build_version)) {
|
||||
BT_ERR("Patch file version did not match with firmware");
|
||||
@ -373,7 +461,15 @@ static int ath3k_load_patch(struct usb_device *udev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ath3k_load_fwfile(udev, firmware);
|
||||
if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION)
|
||||
ret = ath3k_load_fwfile(udev, firmware,
|
||||
ROME2_1_USB_RAMPATCH_HEADER);
|
||||
else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION)
|
||||
ret = ath3k_load_fwfile(udev, firmware,
|
||||
ROME1_1_USB_RAMPATCH_HEADER);
|
||||
else
|
||||
ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE);
|
||||
|
||||
release_firmware(firmware);
|
||||
|
||||
return ret;
|
||||
@ -415,8 +511,13 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
|
||||
fw_version.rom_version, clk_value, ".dfu");
|
||||
if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION)
|
||||
snprintf(filename, ATH3K_NAME_LEN, ROME2_1_USB_NVM_FILE);
|
||||
else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION)
|
||||
snprintf(filename, ATH3K_NAME_LEN, ROME1_1_USB_NVM_FILE);
|
||||
else
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
|
||||
fw_version.rom_version, clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
@ -424,12 +525,36 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath3k_load_fwfile(udev, firmware);
|
||||
if (fw_version.rom_version == ROME2_1_USB_CHIP_VERSION)
|
||||
ret = ath3k_load_fwfile(udev, firmware, ROME2_1_USB_NVM_HEADER);
|
||||
else if (fw_version.rom_version == ROME1_1_USB_CHIP_VERSION)
|
||||
ret = ath3k_load_fwfile(udev, firmware, ROME1_1_USB_NVM_HEADER);
|
||||
else
|
||||
ret = ath3k_load_fwfile(udev, firmware, FW_HDR_SIZE);
|
||||
release_firmware(firmware);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int rome_download(struct usb_device *udev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath3k_load_patch(udev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Loading patch file failed");
|
||||
return ret;
|
||||
}
|
||||
ret = ath3k_load_syscfg(udev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Loading sysconfig file failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rome_download);
|
||||
static int ath3k_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@ -441,7 +566,10 @@ static int ath3k_probe(struct usb_interface *intf,
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (get_rome_version(udev)) {
|
||||
BT_INFO("Rome detected, fw dnld will be triggered from btusb");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* match device ID in ath3k blacklist table */
|
||||
if (!id->driver_info) {
|
||||
const struct usb_device_id *match;
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
@ -1332,7 +1331,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
struct btusb_data *data;
|
||||
struct hci_dev *hdev;
|
||||
int i, err;
|
||||
int i, version, err;
|
||||
|
||||
BT_DBG("intf %p id %p", intf, id);
|
||||
|
||||
@ -1362,12 +1361,17 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_ATH3012) {
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
version = get_rome_version(udev);
|
||||
BT_INFO("Rome Version: 0x%x", version);
|
||||
/* Old firmware would otherwise let ath3k driver load
|
||||
* patch and sysconfig files */
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001)
|
||||
if (version)
|
||||
rome_download(udev);
|
||||
else if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) {
|
||||
BT_INFO("FW for ar3k is yet to be downloaded");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
Copyright (C) 2014 The Linux Foundation. All rights reserved.
|
||||
|
||||
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
|
||||
@ -28,6 +29,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#ifndef AF_BLUETOOTH
|
||||
#define AF_BLUETOOTH 31
|
||||
@ -344,4 +346,7 @@ void sco_exit(void);
|
||||
|
||||
void bt_sock_reclassify_lock(struct sock *sk, int proto);
|
||||
|
||||
int get_rome_version(struct usb_device *udev);
|
||||
int rome_download(struct usb_device *udev);
|
||||
|
||||
#endif /* __BLUETOOTH_H */
|
||||
|
Loading…
Reference in New Issue
Block a user