mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Merge "Bluetooth: btrtl: add support for retrieving the UART settings" into odroidg12-4.9.y-android
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#define RTL_ROM_LMP_8821A 0x8821
|
||||
#define RTL_ROM_LMP_8761A 0x8761
|
||||
#define RTL_ROM_LMP_8822B 0x8822
|
||||
#define RTL_CONFIG_MAGIC 0x8723ab55
|
||||
|
||||
#define IC_MATCH_FL_LMPSUBV (1 << 0)
|
||||
#define IC_MATCH_FL_HCIREV (1 << 1)
|
||||
@@ -587,6 +588,114 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btrtl_setup_realtek);
|
||||
|
||||
static unsigned int btrtl_convert_baudrate(u32 device_baudrate)
|
||||
{
|
||||
switch (device_baudrate) {
|
||||
case 0x0252a00a:
|
||||
return 230400;
|
||||
|
||||
case 0x05f75004:
|
||||
return 921600;
|
||||
|
||||
case 0x00005004:
|
||||
return 1000000;
|
||||
|
||||
case 0x04928002:
|
||||
case 0x01128002:
|
||||
return 1500000;
|
||||
|
||||
case 0x00005002:
|
||||
return 2000000;
|
||||
|
||||
case 0x0000b001:
|
||||
return 2500000;
|
||||
|
||||
case 0x04928001:
|
||||
return 3000000;
|
||||
|
||||
case 0x052a6001:
|
||||
return 3500000;
|
||||
|
||||
case 0x00005001:
|
||||
return 4000000;
|
||||
|
||||
case 0x0252c014:
|
||||
default:
|
||||
return 115200;
|
||||
}
|
||||
}
|
||||
|
||||
int btrtl_get_uart_settings(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev,
|
||||
unsigned int *controller_baudrate,
|
||||
u32 *device_baudrate, bool *flow_control)
|
||||
{
|
||||
struct rtl_vendor_config *config;
|
||||
struct rtl_vendor_config_entry *entry;
|
||||
int i, total_data_len;
|
||||
bool found = false;
|
||||
|
||||
total_data_len = btrtl_dev->cfg_len - sizeof(*config);
|
||||
if (total_data_len <= 0) {
|
||||
rtl_dev_warn(hdev, "no config loaded\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
config = (struct rtl_vendor_config *)btrtl_dev->cfg_data;
|
||||
if (le32_to_cpu(config->signature) != RTL_CONFIG_MAGIC) {
|
||||
rtl_dev_err(hdev, "invalid config magic\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (total_data_len < le16_to_cpu(config->total_len)) {
|
||||
rtl_dev_err(hdev, "config is too short\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < total_data_len; ) {
|
||||
entry = ((void *)config->entry) + i;
|
||||
|
||||
switch (le16_to_cpu(entry->offset)) {
|
||||
case 0xc:
|
||||
if (entry->len < sizeof(*device_baudrate)) {
|
||||
rtl_dev_err(hdev, "invalid UART config entry\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*device_baudrate = get_unaligned_le32(entry->data);
|
||||
*controller_baudrate = btrtl_convert_baudrate(
|
||||
*device_baudrate);
|
||||
|
||||
if (entry->len >= 13)
|
||||
*flow_control = !!(entry->data[12] & BIT(2));
|
||||
else
|
||||
*flow_control = false;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtl_dev_dbg(hdev, "skipping config entry 0x%x (len %u)\n",
|
||||
le16_to_cpu(entry->offset), entry->len);
|
||||
break;
|
||||
};
|
||||
|
||||
i += sizeof(*entry) + entry->len;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
rtl_dev_err(hdev, "no UART config entry found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rtl_dev_dbg(hdev, "device baudrate = 0x%08x\n", *device_baudrate);
|
||||
rtl_dev_dbg(hdev, "controller baudrate = %u\n", *controller_baudrate);
|
||||
rtl_dev_dbg(hdev, "flow control %d\n", *flow_control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btrtl_get_uart_settings);
|
||||
|
||||
MODULE_AUTHOR("Daniel Drake <drake@endlessm.com>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Realtek devices ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
|
||||
@@ -45,6 +45,18 @@ struct rtl_epatch_header {
|
||||
__le16 num_patches;
|
||||
} __packed;
|
||||
|
||||
struct rtl_vendor_config_entry {
|
||||
__le16 offset;
|
||||
__u8 len;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct rtl_vendor_config {
|
||||
__le32 signature;
|
||||
__le16 total_len;
|
||||
struct rtl_vendor_config_entry entry[0];
|
||||
} __packed;
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_RTL)
|
||||
|
||||
struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev);
|
||||
@@ -52,6 +64,10 @@ void btrtl_free(struct btrtl_device_info *btrtl_dev);
|
||||
int btrtl_download_firmware(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev);
|
||||
int btrtl_setup_realtek(struct hci_dev *hdev);
|
||||
int btrtl_get_uart_settings(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev,
|
||||
unsigned int *controller_baudrate,
|
||||
u32 *device_baudrate, bool *flow_control);
|
||||
|
||||
#else
|
||||
|
||||
@@ -75,4 +91,13 @@ static inline int btrtl_setup_realtek(struct hci_dev *hdev)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
|
||||
struct btrtl_device_info *btrtl_dev,
|
||||
unsigned int *controller_baudrate,
|
||||
u32 *device_baudrate,
|
||||
bool *flow_control)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user