From patchwork Fri Nov 17 22:35:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Blumenstingl X-Patchwork-Id: 10064075 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 93CB460352 for ; Fri, 17 Nov 2017 22:36:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 875272AE48 for ; Fri, 17 Nov 2017 22:36:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7C3F92AE4F; Fri, 17 Nov 2017 22:36:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 00F832AE50 for ; Fri, 17 Nov 2017 22:36:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=xvUO6ld0RhD+2R2k2Jh70dKX3dG0csDUKq2vzAPG34Y=; b=nSOL6duNP//bneK+M/lLpThn2j A/pnItJdVOpBfwA+vJCX4Vrt0V1RpZkyZkCbRTrwa13CFQu7Uery3vtHdbIJBe3+k2WTR9n5GegS3 n7tmsddKWEDF6jeokLz+jPPoKnlEdeDsdG6ahCZFjlJ/5qgPCMi170bWhYDKt8DgwUSZyJKjpm2jW Ygt/p3rUZB6Y7KJGFifcr+/6TAZAD4w87Cn8fFjCnRExMGp63ulWmDmBondqYQ3hbmwKNwRTCV9nV WPTzK06onu4APiRoiU1sG6V/qxnfWVRLKjNmynklgXFmzD5ZhnEEkcTLgjGAbWbOFeJjW/BJcxk3O qdy5xrlg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1eFpFZ-0003pj-01; Fri, 17 Nov 2017 22:36:41 +0000 Received: from mail-wr0-x241.google.com ([2a00:1450:400c:c0c::241]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1eFpFP-0003f7-TQ for linux-amlogic@lists.infradead.org; Fri, 17 Nov 2017 22:36:37 +0000 Received: by mail-wr0-x241.google.com with SMTP id z75so1983876wrc.5 for ; Fri, 17 Nov 2017 14:36:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+H7hV11DyPIoqXFDjGVd4fqmywbgk6VZ7jJXlZpATm4=; b=F2Plf+qNtkIMrGFevK61Pl4gAX3O0eM1z5JGmKVZ90ajxblivAf6WZzLaQDNo+ZAIF 7nNn9cDcq2ZoyNqk9s40i6yS0MU8DwCW+oyzB7PXsv9gPW7rJ5mM44lTElhgUom9JKyL B4ERQgc4JMlyGtfoLnTEeyq77B2zxg1JreV+U4hVyWhF+wJnTlcIVmulpzg1W/2YcOlN qFu4BKN9DblavVcjwNUFy/lpdfokJ5n+Y5LUdXjyB6hgin9gqLNDtMnQ/PPD6qGcYa3K MHy4oe6JzCKry1qy+jQqGg8OQzbvPXtsVQ0WrZN3lNo84dBbDlNMO1GEpjngmq9YemvK fVFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+H7hV11DyPIoqXFDjGVd4fqmywbgk6VZ7jJXlZpATm4=; b=tTDJVSj6FpJpnwaPdb/QAhNyyUPcgC4IyB32ZrhfUK2o5WIvIbNOU7TnDLgcTY4+pL 8yXHVylh/d283lWEBlA5ZFqov1XVfxlfggxOX7TBlFBBn4dRguJqQdWChRjFpnfNAf4t hy7ZwCkvaYckJjqp/j9U1D/8ZxB56es/1wqOQ1lV6lhXWMLQ6I/nLyZFEG6q/np+LdiO BtjaBb2Xfeqnxfpu5rGFEfR1f0gQQ7a38mCjARVU89OvvCFvNKgvn6dfr6Wou1xOkYoo ahN1j7ejPQOc3FV6s23qof4lBoUhfDwqZwKjEd9FQNMXmIRp4x7vB8/gNvmq8OUNdvvF kOcg== X-Gm-Message-State: AJaThX4WZO+lmq30smxq0F4Page3gKTpyS3YSzycbBS0TuELYJcGoxc6 zz3W9f8YTLidTL4bevLSd28= X-Google-Smtp-Source: AGs4zMaENeKBz02PWEuvDfXhCHz/xShPYH19Pdc7b5F3kZmwAX+q3QY1FvBAuNEaWtXWTEfJS8Hj9w== X-Received: by 10.223.190.14 with SMTP id n14mr6043245wrh.46.1510958170852; Fri, 17 Nov 2017 14:36:10 -0800 (PST) Received: from blackbox.darklights.net (p200300DCD3F8BE04428D5CFFFEB99DB8.dip0.t-ipconnect.de. [2003:dc:d3f8:be04:428d:5cff:feb9:9db8]) by smtp.googlemail.com with ESMTPSA id k5sm5094876wmg.21.2017.11.17.14.36.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Nov 2017 14:36:10 -0800 (PST) From: Martin Blumenstingl To: robh+dt@kernel.org, devicetree@vger.kernel.org, linux-bluetooth@vger.kernel.org, linux-serial@vger.kernel.org Subject: [RFC v1 4/8] Bluetooth: btrtl: add support for retrieving the UART settings Date: Fri, 17 Nov 2017 23:35:39 +0100 Message-Id: <20171117223543.32429-5-martin.blumenstingl@googlemail.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171117223543.32429-1-martin.blumenstingl@googlemail.com> References: <20171117223543.32429-1-martin.blumenstingl@googlemail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171117_143632_226312_2CB51390 X-CRM114-Status: GOOD ( 17.50 ) X-BeenThere: linux-amlogic@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, johan.hedberg@gmail.com, gregkh@linuxfoundation.org, Martin Blumenstingl , gustavo@padovan.org, marcel@holtmann.org, johan@kernel.org, linux-sunxi@googlegroups.com, jslaby@suse.com, linux-amlogic@lists.infradead.org, Larry.Finger@lwfinger.net MIME-Version: 1.0 Sender: "linux-amlogic" Errors-To: linux-amlogic-bounces+patchwork-linux-amlogic=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The UART settings are embedded in the config blob. This has to be parsed to successfully initialize the Bluetooth part of the RTL8723BS (which is an SDIO chip, but the Bluetooth part is connected via UART). The Realtek "rtl8723bs_bt" and "rtl8723ds_bt" userspace Bluetooth UART initialization tools (rtk_hciattach) use the following sequence: - send H5 sync pattern (already supported by hci_h5) - get LMP version (already supported by btrtl) - get ROM version (already supported by btrtl) - load the firmware and config for the current chipset (already supported by btrtl) - read UART settings from the config blob (part of this patch) - send UART settings via a vendor command to the device (which changes the baudrate of the device and enables or disables flow control depending on the config) - change the baudrate and flow control settings on the host - send the firmware and config blob to the device (already supported by btrtl) Sending the last firmware and config blob download command (rtl_download_cmd) fails if the UART settings are not updated beforehand. This is presumably because the device applies the config right after the firmware and config blob download - which means that at this point the host is using different UART settings than the device (which will obviously result in non-working communication). Signed-off-by: Martin Blumenstingl --- drivers/bluetooth/btrtl.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btrtl.h | 25 +++++++++++ 2 files changed, 137 insertions(+) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 07f96b8000f1..45b872f5ad22 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -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 struct btrtl_device_info { u16 lmp_subver; @@ -522,6 +523,117 @@ int btrtl_setup_realtek(struct hci_dev *hdev) } EXPORT_SYMBOL_GPL(btrtl_setup_realtek); +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) { + bt_dev_warn(hdev, "rtl: no config loaded"); + return -EINVAL; + } + + config = (struct rtl_vendor_config *)btrtl_dev->cfg_data; + if (le32_to_cpu(config->signature) != RTL_CONFIG_MAGIC) { + bt_dev_err(hdev, "rtl: invalid config magic"); + return -EINVAL; + } + + if (total_data_len < le16_to_cpu(config->total_len)) { + bt_dev_err(hdev, "rtl: config is too short"); + 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)) { + bt_dev_err(hdev, + "rtl: invalid UART config entry"); + 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: + bt_dev_dbg(hdev, + "rtl: skipping config entry 0x%x (len %u)", + le16_to_cpu(entry->offset), entry->len); + break; + }; + + i += sizeof(*entry) + entry->len; + } + + if (!found) { + bt_dev_err(hdev, "rtl: no UART config entry found"); + return -ENOENT; + } + + bt_dev_dbg(hdev, "rtl: device baudrate = 0x%08x", *device_baudrate); + bt_dev_dbg(hdev, "rtl: controller baudrate = %u", + *controller_baudrate); + bt_dev_dbg(hdev, "rtl: flow control %d", *flow_control); + + return 0; +} +EXPORT_SYMBOL_GPL(btrtl_get_uart_settings); + MODULE_AUTHOR("Daniel Drake "); MODULE_DESCRIPTION("Bluetooth support for Realtek devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h index 21c28dcbe5e0..2e7856fa5ac7 100644 --- a/drivers/bluetooth/btrtl.h +++ b/drivers/bluetooth/btrtl.h @@ -40,6 +40,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); @@ -47,6 +59,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 @@ -70,4 +86,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