* Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg
From: Andy Gross @ 2017-03-22 21:52 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Eugene Krasnikov,
Kalle Valo, David Brown, David S. Miller, Arnd Bergmann,
linux-bluetooth, linux-kernel, wcn36xx, linux-wireless, netdev,
linux-arm-msm, linux-soc
In-Reply-To: <20170320233544.1656-1-bjorn.andersson@linaro.org>
On Mon, Mar 20, 2017 at 04:35:42PM -0700, Bjorn Andersson wrote:
> By moving these client drivers to use RPMSG instead of the direct SMD
> API we can reuse them ontop of the newly added GLINK wire-protocol
> support found in the 820 and 835 Qualcomm platforms.
>
> As the new (RPMSG-based) and old SMD implementations are mutually
> exclusive we have to change all client drivers in one commit, to make
> sure we have a working system before and after this transition.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
For the qcom/smd parts:
Acked-by: Andy Gross <andy.gross@linaro.org>
^ permalink raw reply
* Re: [PATCHv2 09/11] Bluetooth: add nokia driver
From: Rob Herring @ 2017-03-22 21:26 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170321223216.11733-10-sre@kernel.org>
On Tue, Mar 21, 2017 at 5:32 PM, Sebastian Reichel <sre@kernel.org> wrote:
> This adds a driver for the Nokia H4+ protocol, which is used
> at least on the Nokia N9, N900 & N950.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> + btdev->wakeup_host = devm_gpiod_get(dev, "host-wakeup", GPIOD_IN);
> + if (IS_ERR(btdev->wakeup_host)) {
> + err = PTR_ERR(btdev->wakeup_host);
> + dev_err(dev, "could not get host wakeup gpio: %d", err);
> + return err;
> + }
> +
> + btdev->wake_irq = gpiod_to_irq(btdev->wakeup_host);
Missed this in the binding review, but generally, we make these
interrupts rather than gpios in the binding.
> +
> + err = devm_request_threaded_irq(dev, btdev->wake_irq, NULL,
> + wakeup_handler,
> + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> + "wakeup", btdev);
> + if (err) {
> + dev_err(dev, "could request wakeup irq: %d", err);
> + return err;
> + }
^ permalink raw reply
* Re: [PATCHv2.1] serdev: implement get/set tiocm
From: Rob Herring @ 2017-03-22 21:18 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170322005837.6047-1-sre@kernel.org>
On Tue, Mar 21, 2017 at 7:58 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Add method for getting and setting tiocm.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Changes since PATCHv2:
> * fix serdev_device_set_tiocm inline definition for disabled SERDEV
> * use <linux/termios.h> instead of <asm-generic/termios.h>
> ---
> drivers/tty/serdev/core.c | 22 ++++++++++++++++++++++
> drivers/tty/serdev/serdev-ttyport.c | 24 ++++++++++++++++++++++++
> include/linux/serdev.h | 13 +++++++++++++
> 3 files changed, 59 insertions(+)
I'm not that big of a fan of {set,get}_tiocm, but I guess it is fine.
Acked-by: Rob Herring <robh@kernel.org>
Rob
^ permalink raw reply
* Re: [PATCHv2 10/11] ARM: dts: N900: Add bluetooth
From: Rob Herring @ 2017-03-22 21:06 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170321223216.11733-11-sre@kernel.org>
On Tue, Mar 21, 2017 at 5:32 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Add bcm2048 node and its system clock to the N900 device tree file.
> Apart from that a reference to the new clock has been added to
> wl1251 (which uses it, too).
>
> Acked-by: Pavel Machek <pavel@ucw.cz>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Changes since PATCHv1:
> - update compatible string
> ---
> arch/arm/boot/dts/omap3-n900.dts | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCHv2 11/11] ARM: dts: N9/N950: add bluetooth
From: Rob Herring @ 2017-03-22 21:06 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170321223216.11733-12-sre@kernel.org>
On Tue, Mar 21, 2017 at 5:32 PM, Sebastian Reichel <sre@kernel.org> wrote:
> The Nokia N950 and N9 have a wl1271 (with nokia bootloader) bluetooth
> module connected to second UART.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Changes since PATCHv1:
> - update compatible string
> ---
> arch/arm/boot/dts/omap3-n950-n9.dtsi | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCHv2 08/11] dt-bindings: net: bluetooth: Add nokia-bluetooth
From: Rob Herring @ 2017-03-22 21:04 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170321223216.11733-9-sre@kernel.org>
On Tue, Mar 21, 2017 at 5:32 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Add binding document for serial bluetooth chips using
> Nokia H4+ protocol.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> Changes since PATCHv1:
> * change compatible strings
> * mention active high/low state for GPIOs
> ---
> .../devicetree/bindings/net/nokia-bluetooth.txt | 51 ++++++++++++++++++++++
> 1 file changed, 51 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/nokia-bluetooth.txt
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCHv2 07/11] serdev: add helpers for cts and rts handling
From: Rob Herring @ 2017-03-22 21:03 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Samuel Thibault,
Pavel Machek, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, open list:BLUETOOTH DRIVERS,
linux-serial@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20170321223216.11733-8-sre@kernel.org>
On Tue, Mar 21, 2017 at 5:32 PM, Sebastian Reichel <sre@kernel.org> wrote:
> Add serdev helper functions for handling of cts and rts
> lines using the serdev's tiocm functions.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
> ---
> include/linux/serdev.h | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/include/linux/serdev.h b/include/linux/serdev.h
> index 3ad1d695f947..8cdce2ea0d51 100644
> --- a/include/linux/serdev.h
> +++ b/include/linux/serdev.h
> @@ -16,6 +16,7 @@
> #include <linux/types.h>
> #include <linux/device.h>
> #include <asm-generic/termios.h>
> +#include <linux/delay.h>
>
> struct serdev_controller;
> struct serdev_device;
> @@ -254,6 +255,36 @@ static inline int serdev_device_write_room(struct serdev_device *sdev)
>
> #endif /* CONFIG_SERIAL_DEV_BUS */
>
> +static inline bool serdev_device_get_cts(struct serdev_device *serdev)
> +{
> + int status = serdev_device_get_tiocm(serdev);
> + return !!(status & TIOCM_CTS);
> +}
> +
> +static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms)
> +{
> + unsigned long timeout;
> + bool signal;
> +
> + timeout = jiffies + msecs_to_jiffies(timeout_ms);
> + while (!time_after(jiffies, timeout)) {
You can use time_is_after_jiffies(timeout) instead of !time_after.
> + signal = serdev_device_get_cts(serdev);
> + if (signal == state)
> + return 0;
> + usleep_range(1000, 2000);
> + }
> +
> + return -ETIMEDOUT;
> +}
> +
> +static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable)
> +{
> + if (enable)
> + return serdev_device_set_tiocm(serdev, TIOCM_OUT2 | TIOCM_RTS, 0);
Perhaps a comment why we're messing with OUT2.
With those,
Acked-by: Rob Herring <robh@kernel.org>
> + else
> + return serdev_device_set_tiocm(serdev, 0, TIOCM_OUT2 | TIOCM_RTS);
> +}
> +
> /*
> * serdev hooks into TTY core
> */
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg
From: Marcel Holtmann @ 2017-03-22 19:23 UTC (permalink / raw)
To: David S. Miller
Cc: Bjorn Andersson, Gustavo F. Padovan, Johan Hedberg,
Eugene Krasnikov, Kalle Valo, Andy Gross, David Brown, arnd,
linux-bluetooth, linux-kernel, wcn36xx, linux-wireless, netdev,
linux-arm-msm, linux-soc
In-Reply-To: <20170322.114439.679826829857326050.davem@davemloft.net>
Hi Dave,
>> By moving these client drivers to use RPMSG instead of the direct SMD
>> API we can reuse them ontop of the newly added GLINK wire-protocol
>> support found in the 820 and 835 Qualcomm platforms.
>>
>> As the new (RPMSG-based) and old SMD implementations are mutually
>> exclusive we have to change all client drivers in one commit, to make
>> sure we have a working system before and after this transition.
>>
>> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
>> ---
>>
>> Based on v4.11-rc3 with Arnd's Kconfig dependency fixes for BT_QCOMSMD
>> (https://lkml.org/lkml/2017/3/20/1038).
>
> Just some questions since I'm supposed to merge this into my net-next
> tree.
>
> What is the status of the Kconfig dependency fix and how will I be
> getting it?
I acked that one separately and added you:
[PATCH v2] Bluetooth: btqcomsmd: fix compile-test dependency
> Second, should I merge all three of these patches to net-next or just
> this one?
I think you have to take all 3 patches. Otherwise it will break.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/3] soc: qcom: smd: Transition client drivers from smd to rpmsg
From: David Miller @ 2017-03-22 18:44 UTC (permalink / raw)
To: bjorn.andersson
Cc: marcel, gustavo, johan.hedberg, k.eugene.e, kvalo, andy.gross,
david.brown, arnd, linux-bluetooth, linux-kernel, wcn36xx,
linux-wireless, netdev, linux-arm-msm, linux-soc
In-Reply-To: <20170320233544.1656-1-bjorn.andersson@linaro.org>
From: Bjorn Andersson <bjorn.andersson@linaro.org>
Date: Mon, 20 Mar 2017 16:35:42 -0700
> By moving these client drivers to use RPMSG instead of the direct SMD
> API we can reuse them ontop of the newly added GLINK wire-protocol
> support found in the 820 and 835 Qualcomm platforms.
>
> As the new (RPMSG-based) and old SMD implementations are mutually
> exclusive we have to change all client drivers in one commit, to make
> sure we have a working system before and after this transition.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>
> Based on v4.11-rc3 with Arnd's Kconfig dependency fixes for BT_QCOMSMD
> (https://lkml.org/lkml/2017/3/20/1038).
Just some questions since I'm supposed to merge this into my net-next
tree.
What is the status of the Kconfig dependency fix and how will I be
getting it?
Second, should I merge all three of these patches to net-next or just
this one?
Thanks.
^ permalink raw reply
* Re: way of woking / how to develop new features (roadmap)
From: Luiz Augusto von Dentz @ 2017-03-22 9:40 UTC (permalink / raw)
To: Mike.Stahl; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <OFB1F3144F.CCE46262-ONC12580EA.0051B938-C12580EA.0053A564@continental-corporation.com>
Hi Mike,
On Tue, Mar 21, 2017 at 5:13 PM,
<Mike.Stahl@continental-corporation.com> wrote:
> Dear community members,
>
> I just joined this mailing list and I have a couple of questions regarding
> the way of working in this community.
>
> 1. Is there any documentation that explains how to contribute to the open
> source development (i.e. is there a kind of guideline for a BlueZ software
> engineer)?
Please check the HACKING document:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/HACKING
> 2. How is the development of new profile features (or profile version
> upgrades) organized for BlueZ:
> a) How does the community discuss and agree on the features that should
> be developed next?
It depends on the feature, for example if that affects the public APIs
then you might want to send an email with the intended API as RFC to
collect feedback. If you need quicker feedback join the irc channel
#bluez@freenode.
> b) What are the typical steps to integrate new/additional functionality
> into Bluez?
Send patches, it may take a few iteration until they get merged but
that is no different than working with Linux kernel community.
> c) Does a kind of roadmap exist for Bluetooth profiles/features?
Not in a formal way, most companies do have something on their own
though, we do however have a TODO document:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/TODO
> d) Are there working groups for specific topics in order to coordinate
> development activities and to share experience?
Nope, we do have maintainers that focus more on specific areas, I
currently maintain the userspace area, others may focus more on
Kernel, Android or some specific profile.
> 3. What is the focus of current BlueZ development? This question basically
> goes to all community members. Feedback from everybody who likes to answer
> is very welcome!
I guess it would be easier to look at the git history instead of
asking here, in any case from my side Im currently working on
finalizing IPSP support.
>
> Thank you in anticipation!
>
> Best regards
>
> Mike
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCHv2.1] serdev: implement get/set tiocm
From: Pavel Machek @ 2017-03-22 9:40 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Rob Herring,
Samuel Thibault, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, linux-bluetooth, linux-serial, devicetree,
linux-kernel
In-Reply-To: <20170322005837.6047-1-sre@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 338 bytes --]
On Wed 2017-03-22 01:58:37, Sebastian Reichel wrote:
> Add method for getting and setting tiocm.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCHv2 05/11] serdev: add serdev_device_wait_until_sent
From: Pavel Machek @ 2017-03-22 9:39 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Rob Herring,
Samuel Thibault, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, linux-bluetooth, linux-serial, devicetree,
linux-kernel
In-Reply-To: <20170321223216.11733-6-sre@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 677 bytes --]
Hi!
> @@ -47,10 +48,13 @@ static void ttyport_write_wakeup(struct tty_port *port)
> struct serport *serport = serdev_controller_get_drvdata(ctrl);
>
> if (!test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &port->tty->flags))
> - return;
> + goto out;
>
> if (test_bit(SERPORT_ACTIVE, &serport->flags))
> serdev_controller_write_wakeup(ctrl);
> +
> +out:
I'd do "if (test_and_clear_bit() && test_bit()) serdev_()"
here. Otherwise it looks fine.
Acked-by: Pavel Machek <pavel@ucw.cz>
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCHv2 04/11] tty: serial: omap: add UPF_BOOT_AUTOCONF flag for DT init
From: Pavel Machek @ 2017-03-22 9:32 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Rob Herring,
Samuel Thibault, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, linux-bluetooth, linux-serial, devicetree,
linux-kernel
In-Reply-To: <20170321223216.11733-5-sre@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 369 bytes --]
On Tue 2017-03-21 23:32:09, Sebastian Reichel wrote:
> The UPF_BOOT_AUTOCONF flag is needed for proper
> flow control support.
>
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCHv2 02/11] Bluetooth: hci_uart: add serdev driver support library
From: Pavel Machek @ 2017-03-22 9:32 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, Rob Herring,
Samuel Thibault, Tony Lindgren, Greg Kroah-Hartman, Jiri Slaby,
Mark Rutland, linux-bluetooth, linux-serial, devicetree,
linux-kernel, Rob Herring
In-Reply-To: <20170321223216.11733-3-sre@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 856 bytes --]
On Tue 2017-03-21 23:32:07, Sebastian Reichel wrote:
> From: Rob Herring <robh@kernel.org>
>
> This adds library functions for serdev based BT drivers. This is largely
> copied from hci_ldisc.c and modified to use serdev calls. There's a little
> bit of duplication, but I avoided intermixing this as the ldisc code should
> eventually go away.
>
> Signed-off-by: Rob Herring <robh@kernel.org>
> Cc: Marcel Holtmann <marcel@holtmann.org>
> Cc: Gustavo Padovan <gustavo@padovan.org>
> Cc: Johan Hedberg <johan.hedberg@gmail.com>
> Cc: linux-bluetooth@vger.kernel.org
> [Fix style issues reported by Pavel]
> Signed-off-by: Sebastian Reichel <sre@kernel.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: Unexpected SMP Command 0x17
From: Marcel Holtmann @ 2017-03-22 7:36 UTC (permalink / raw)
To: Wong, Joshua Weng Onn
Cc: Bluez mailing list, Wong, Mun choy, Zulqarnain, Adam,
avinashk@marvell.com
In-Reply-To: <E3B98393E6037849B63EA428240A651360654F@PGSMSX103.gar.corp.intel.com>
Hi Joshua,
> I am seeing an error during the LE pairing process which makes the pairing to fail. I have two DUTs which uses the Marvell 88W8897.
> Here are my BT settings for both master and slave:
>
> Master:
> $ btmgmt info
> current settings: powered connectable discoverable bondable ssp br/edr le secure-conn
>
> Slave:
> $ btmgmt info
> Current settings: powered connectable bondable le advertising secure-conn
>
> When I initiate the pairing process from the master, I observed the message:
> "Bluetooth: hci0 unexpected SMP command 0x0a from 74:c6:3b:ab:68:ea"
>
> Where 74:c6:3b:ab:68:ea is the address of the slave device.
>
> In the btmon log of the master device, it is observed that after the Slave device has transmitted the keys, the Master does not transmit it. Hence, the Slave is not receiving the keys and thus disconnects the link and pairing is failed.
>
>> ACL Data RX: Handle 128 flags 0x02 dlen 21 [hci0] 124.801098
> SMP: Encryption Information (0x06) len 16
> Long term key: 9ac691e96e85e82ca68f4b6d2abec80f
>> HCI Event: Encryption Change (0x08) plen 4 [hci0] 124.801261
> Status: Success (0x00)
> Handle: 128
> Encryption: Enabled with AES-CCM (0x01)
>> ACL Data RX: Handle 128 flags 0x02 dlen 15 [hci0] 124.812761
> SMP: Master Identification (0x07) len 10
> EDIV: 0xea3f
> Rand: 0x806e542a78f55d7c
>> ACL Data RX: Handle 128 flags 0x02 dlen 21 [hci0] 124.812782
> SMP: Signing Information (0x0a) len 16
> Signature key: 4451b8ae0eff90f0a47fb96be53479fb
>> HCI Event: Disconnect Complete (0x05) plen 4 [hci0] 154.839591
> Status: Success (0x00)
> Handle: 128
> Reason: Remote User Terminated Connection (0x13)
>
> => At this point, Master should start sending LTK to slave, but Master doesn't send the LTK so Slave disconnects the link and pairing is failed.
>
> What could possibly cause the master to not send the LTK? My kernel version is v4.1.27 and bluez stack is v5.40. I would appreciate advice on this.
if this is LE Secure Connections, then the LTK is no longer distributed. It is being calculated from ECDH. Please include the complete SMP exchanges. Only then we can see what is going on.
Also keep in mind that 4.1.x kernels are actually rather old. The latest one is 4.10.x and if there is a bug, you should verify that it also happens with the latest kernel.
Regards
Marcel
^ permalink raw reply
* Unexpected SMP Command 0x17
From: Wong, Joshua Weng Onn @ 2017-03-22 2:47 UTC (permalink / raw)
To: Bluez mailing list; +Cc: Wong, Mun choy, Zulqarnain, Adam, avinashk@marvell.com
SGkgYWxsLA0KDQpJIGFtIHNlZWluZyBhbiBlcnJvciBkdXJpbmcgdGhlIExFIHBhaXJpbmcgcHJv
Y2VzcyB3aGljaCBtYWtlcyB0aGUgcGFpcmluZyB0byBmYWlsLiBJIGhhdmUgdHdvIERVVHMgd2hp
Y2ggdXNlcyB0aGUgTWFydmVsbCA4OFc4ODk3Lg0KSGVyZSBhcmUgbXkgQlQgc2V0dGluZ3MgZm9y
IGJvdGggbWFzdGVyIGFuZCBzbGF2ZToNCg0KTWFzdGVyOg0KJCBidG1nbXQgaW5mbw0KY3VycmVu
dCBzZXR0aW5nczogcG93ZXJlZCBjb25uZWN0YWJsZSBkaXNjb3ZlcmFibGUgYm9uZGFibGUgc3Nw
IGJyL2VkciBsZSBzZWN1cmUtY29ubg0KDQpTbGF2ZToNCiQgYnRtZ210IGluZm8NCkN1cnJlbnQg
c2V0dGluZ3M6IHBvd2VyZWQgY29ubmVjdGFibGUgYm9uZGFibGUgbGUgYWR2ZXJ0aXNpbmcgc2Vj
dXJlLWNvbm4NCg0KV2hlbiBJIGluaXRpYXRlIHRoZSBwYWlyaW5nIHByb2Nlc3MgZnJvbSB0aGUg
bWFzdGVyLCBJIG9ic2VydmVkIHRoZSBtZXNzYWdlOg0KIkJsdWV0b290aDogaGNpMCB1bmV4cGVj
dGVkIFNNUCBjb21tYW5kIDB4MGEgZnJvbSA3NDpjNjozYjphYjo2ODplYSINCg0KV2hlcmUgNzQ6
YzY6M2I6YWI6Njg6ZWEgaXMgdGhlIGFkZHJlc3Mgb2YgdGhlIHNsYXZlIGRldmljZS4NCg0KSW4g
dGhlIGJ0bW9uIGxvZyBvZiB0aGUgbWFzdGVyIGRldmljZSwgaXQgaXMgb2JzZXJ2ZWQgdGhhdCBh
ZnRlciB0aGUgU2xhdmUgZGV2aWNlIGhhcyB0cmFuc21pdHRlZCB0aGUga2V5cywgdGhlIE1hc3Rl
ciBkb2VzIG5vdCB0cmFuc21pdCBpdC4gSGVuY2UsIHRoZSBTbGF2ZSBpcyBub3QgcmVjZWl2aW5n
IHRoZSBrZXlzIGFuZCB0aHVzIGRpc2Nvbm5lY3RzIHRoZSBsaW5rIGFuZCBwYWlyaW5nIGlzIGZh
aWxlZC4NCg0KPiBBQ0wgRGF0YSBSWDogSGFuZGxlIDEyOCBmbGFncyAweDAyIGRsZW4gMjEgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgW2hjaTBdIDEyNC44MDEwOTgNCiAgICAgIFNNUDog
RW5jcnlwdGlvbiBJbmZvcm1hdGlvbiAoMHgwNikgbGVuIDE2DQogICAgICAgIExvbmcgdGVybSBr
ZXk6IDlhYzY5MWU5NmU4NWU4MmNhNjhmNGI2ZDJhYmVjODBmDQo+IEhDSSBFdmVudDogRW5jcnlw
dGlvbiBDaGFuZ2UgKDB4MDgpIHBsZW4gNCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBb
aGNpMF0gMTI0LjgwMTI2MQ0KICAgICAgICBTdGF0dXM6IFN1Y2Nlc3MgKDB4MDApDQogICAgICAg
IEhhbmRsZTogMTI4DQogICAgICAgIEVuY3J5cHRpb246IEVuYWJsZWQgd2l0aCBBRVMtQ0NNICgw
eDAxKQ0KPiBBQ0wgRGF0YSBSWDogSGFuZGxlIDEyOCBmbGFncyAweDAyIGRsZW4gMTUgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgW2hjaTBdIDEyNC44MTI3NjENCiAgICAgIFNNUDogTWFz
dGVyIElkZW50aWZpY2F0aW9uICgweDA3KSBsZW4gMTANCiAgICAgICAgRURJVjogMHhlYTNmDQog
ICAgICAgIFJhbmQ6IDB4ODA2ZTU0MmE3OGY1NWQ3Yw0KPiBBQ0wgRGF0YSBSWDogSGFuZGxlIDEy
OCBmbGFncyAweDAyIGRsZW4gMjEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2hjaTBd
IDEyNC44MTI3ODINCiAgICAgIFNNUDogU2lnbmluZyBJbmZvcm1hdGlvbiAoMHgwYSkgbGVuIDE2
DQogICAgICAgIFNpZ25hdHVyZSBrZXk6IDQ0NTFiOGFlMGVmZjkwZjBhNDdmYjk2YmU1MzQ3OWZi
DQo+IEhDSSBFdmVudDogRGlzY29ubmVjdCBDb21wbGV0ZSAoMHgwNSkgcGxlbiA0ICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBbaGNpMF0gMTU0LjgzOTU5MQ0KICAgICAgICBTdGF0dXM6IFN1
Y2Nlc3MgKDB4MDApDQogICAgICAgIEhhbmRsZTogMTI4DQogICAgICAgIFJlYXNvbjogUmVtb3Rl
IFVzZXIgVGVybWluYXRlZCBDb25uZWN0aW9uICgweDEzKQ0KDQo9PiBBdCB0aGlzIHBvaW50LCBN
YXN0ZXIgc2hvdWxkIHN0YXJ0IHNlbmRpbmcgTFRLIHRvIHNsYXZlLCBidXQgTWFzdGVyIGRvZXNu
J3Qgc2VuZCB0aGUgTFRLIHNvIFNsYXZlIGRpc2Nvbm5lY3RzIHRoZSBsaW5rIGFuZCBwYWlyaW5n
IGlzIGZhaWxlZC4NCg0KV2hhdCBjb3VsZCBwb3NzaWJseSBjYXVzZSB0aGUgbWFzdGVyIHRvIG5v
dCBzZW5kIHRoZSBMVEs/IE15IGtlcm5lbCB2ZXJzaW9uIGlzIHY0LjEuMjcgYW5kIGJsdWV6IHN0
YWNrIGlzIHY1LjQwLiBJIHdvdWxkIGFwcHJlY2lhdGUgYWR2aWNlIG9uIHRoaXMuDQoNClRoYW5r
IHlvdS4NCg0Kfkpvc2h1YQ0K
^ permalink raw reply
* [PATCHv2.1] serdev: implement get/set tiocm
From: Sebastian Reichel @ 2017-03-22 0:58 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-7-sre@kernel.org>
Add method for getting and setting tiocm.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Changes since PATCHv2:
* fix serdev_device_set_tiocm inline definition for disabled SERDEV
* use <linux/termios.h> instead of <asm-generic/termios.h>
---
drivers/tty/serdev/core.c | 22 ++++++++++++++++++++++
drivers/tty/serdev/serdev-ttyport.c | 24 ++++++++++++++++++++++++
include/linux/serdev.h | 13 +++++++++++++
3 files changed, 59 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index a63b74031e22..1e1cbae3a0ea 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -184,6 +184,28 @@ void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout)
}
EXPORT_SYMBOL_GPL(serdev_device_wait_until_sent);
+int serdev_device_get_tiocm(struct serdev_device *serdev)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->get_tiocm)
+ return -ENOTSUPP;
+
+ return ctrl->ops->get_tiocm(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_get_tiocm);
+
+int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->set_tiocm)
+ return -ENOTSUPP;
+
+ return ctrl->ops->set_tiocm(ctrl, set, clear);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_tiocm);
+
static int serdev_drv_probe(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index db2bc601e554..c5bdb901ff11 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -179,6 +179,28 @@ static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout
tty_wait_until_sent(tty, timeout);
}
+static int ttyport_get_tiocm(struct serdev_controller *ctrl)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+
+ if (!tty->ops->tiocmget)
+ return -ENOTSUPP;
+
+ return tty->driver->ops->tiocmget(tty);
+}
+
+static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, unsigned int clear)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+
+ if (!tty->ops->tiocmset)
+ return -ENOTSUPP;
+
+ return tty->driver->ops->tiocmset(tty, set, clear);
+}
+
static const struct serdev_controller_ops ctrl_ops = {
.write_buf = ttyport_write_buf,
.write_flush = ttyport_write_flush,
@@ -188,6 +210,8 @@ static const struct serdev_controller_ops ctrl_ops = {
.set_flow_control = ttyport_set_flow_control,
.set_baudrate = ttyport_set_baudrate,
.wait_until_sent = ttyport_wait_until_sent,
+ .get_tiocm = ttyport_get_tiocm,
+ .set_tiocm = ttyport_set_tiocm,
};
struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index a308b206d204..e29a270f603c 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/termios.h>
struct serdev_controller;
struct serdev_device;
@@ -82,6 +83,8 @@ struct serdev_controller_ops {
void (*set_flow_control)(struct serdev_controller *, bool);
unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
void (*wait_until_sent)(struct serdev_controller *, long);
+ int (*get_tiocm)(struct serdev_controller *);
+ int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
};
/**
@@ -188,6 +191,8 @@ void serdev_device_close(struct serdev_device *);
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
void serdev_device_set_flow_control(struct serdev_device *, bool);
void serdev_device_wait_until_sent(struct serdev_device *, long);
+int serdev_device_get_tiocm(struct serdev_device *);
+int serdev_device_set_tiocm(struct serdev_device *, int, int);
int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
void serdev_device_write_flush(struct serdev_device *);
int serdev_device_write_room(struct serdev_device *);
@@ -226,6 +231,14 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
}
static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
+static inline int serdev_device_get_tiocm(struct serdev_device *serdev)
+{
+ return -ENOTSUPP;
+}
+static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
+{
+ return -ENOTSUPP;
+}
static inline int serdev_device_write_buf(struct serdev_device *sdev, const unsigned char *buf, size_t count)
{
return -ENODEV;
--
2.11.0
^ permalink raw reply related
* [PATCHv2 11/11] ARM: dts: N9/N950: add bluetooth
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
The Nokia N950 and N9 have a wl1271 (with nokia bootloader) bluetooth
module connected to second UART.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Changes since PATCHv1:
- update compatible string
---
arch/arm/boot/dts/omap3-n950-n9.dtsi | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi
index 5d8c4b4a4205..df3366fa5409 100644
--- a/arch/arm/boot/dts/omap3-n950-n9.dtsi
+++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi
@@ -58,6 +58,13 @@
pinctrl-0 = <&debug_leds>;
};
};
+
+ /* controlled (enabled/disabled) directly by wl1271 */
+ vctcxo: vctcxo {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
};
&omap3_pmx_core {
@@ -125,6 +132,15 @@
OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE4) /* gpio_93 (cmt_apeslpx) */
>;
};
+
+ uart2_pins: pinmux_uart2_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */
+ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts */
+ OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx */
+ OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx */
+ >;
+ };
};
&omap3_pmx_core2 {
@@ -435,3 +451,19 @@
&ssi_port2 {
status = "disabled";
};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+
+ bluetooth {
+ compatible = "ti,wl1271-bluetooth-nokia", "nokia,h4p-bluetooth";
+
+ reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; /* 26 */
+ host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* 101 */
+ bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* 37 */
+
+ clocks = <&vctcxo>;
+ clock-names = "sysclk";
+ };
+};
--
2.11.0
^ permalink raw reply related
* [PATCHv2 10/11] ARM: dts: N900: Add bluetooth
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
Add bcm2048 node and its system clock to the N900 device tree file.
Apart from that a reference to the new clock has been added to
wl1251 (which uses it, too).
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Changes since PATCHv1:
- update compatible string
---
arch/arm/boot/dts/omap3-n900.dts | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index b64cfda8dbb7..49f37084e435 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -155,6 +155,13 @@
compatible = "nokia,n900-ir";
pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
};
+
+ /* controlled (enabled/disabled) directly by bcm2048 and wl1251 */
+ vctcxo: vctcxo {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
};
&omap3_pmx_core {
@@ -162,8 +169,10 @@
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
- OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx */
+ OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */
+ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts */
OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx */
+ OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx */
>;
};
@@ -920,6 +929,8 @@
interrupt-parent = <&gpio2>;
interrupts = <10 IRQ_TYPE_NONE>; /* gpio line 42 */
+
+ clocks = <&vctcxo>;
};
};
@@ -937,9 +948,17 @@
};
&uart2 {
- interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
+
+ bcm2048: bluetooth {
+ compatible = "brcm,bcm2048-nokia", "nokia,h4p-bluetooth";
+ reset-gpios = <&gpio3 27 GPIO_ACTIVE_LOW>; /* 91 */
+ host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* 101 */
+ bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* 37 */
+ clocks = <&vctcxo>;
+ clock-names = "sysclk";
+ };
};
&uart3 {
--
2.11.0
^ permalink raw reply related
* [PATCHv2 09/11] Bluetooth: add nokia driver
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
This adds a driver for the Nokia H4+ protocol, which is used
at least on the Nokia N9, N900 & N950.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Changes since PATCHv1:
* replace __u8 and uint8_t with u8
* replace __u16 and uint16_t with u16
* drop BT_BAUDRATE_DIVIDER and use btdev->sysclk_speed * 10 instead
* fix wording of a sentence
* fix error path of negotation & alive package receive functions
* replaced nokia_wait_for_cts with newly introduced serdev function
* use "nokia,h4p-bluetooth" as compatible string
---
drivers/bluetooth/Kconfig | 12 +
drivers/bluetooth/Makefile | 2 +
drivers/bluetooth/hci_nokia.c | 819 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 833 insertions(+)
create mode 100644 drivers/bluetooth/hci_nokia.c
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c2c14a12713b..2e3e4d3547ad 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -86,6 +86,18 @@ config BT_HCIUART_H4
Say Y here to compile support for HCI UART (H4) protocol.
+config BT_HCIUART_NOKIA
+ tristate "UART Nokia H4+ protocol support"
+ depends on BT_HCIUART
+ depends on SERIAL_DEV_BUS
+ depends on PM
+ help
+ Nokia H4+ is serial protocol for communication between Bluetooth
+ device and host. This protocol is required for Bluetooth devices
+ with UART interface in Nokia devices.
+
+ Say Y here to compile support for Nokia's H4+ protocol.
+
config BT_HCIUART_BCSP
bool "BCSP protocol support"
depends on BT_HCIUART
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index fd571689eed6..a7f237320f4b 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -25,6 +25,8 @@ obj-$(CONFIG_BT_BCM) += btbcm.o
obj-$(CONFIG_BT_RTL) += btrtl.o
obj-$(CONFIG_BT_QCA) += btqca.o
+obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o
+
btmrvl-y := btmrvl_main.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c
new file mode 100644
index 000000000000..c77f04af01bf
--- /dev/null
+++ b/drivers/bluetooth/hci_nokia.c
@@ -0,0 +1,819 @@
+/*
+ * Bluetooth HCI UART H4 driver with Nokia Extensions AKA Nokia H4+
+ *
+ * Copyright (C) 2015 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2015-2017 Sebastian Reichel <sre@kernel.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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/gpio/consumer.h>
+#include <linux/unaligned/le_struct.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <linux/serdev.h>
+
+#include "hci_uart.h"
+#include "btbcm.h"
+
+#define NOKIA_ID_BCM2048 0x04
+#define NOKIA_ID_TI1271 0x31
+
+#define FIRMWARE_BCM2048 "nokia/bcmfw.bin"
+#define FIRMWARE_TI1271 "nokia/ti1273.bin"
+
+#define HCI_NOKIA_NEG_PKT 0x06
+#define HCI_NOKIA_ALIVE_PKT 0x07
+#define HCI_NOKIA_RADIO_PKT 0x08
+
+#define HCI_NOKIA_NEG_HDR_SIZE 1
+#define HCI_NOKIA_MAX_NEG_SIZE 255
+#define HCI_NOKIA_ALIVE_HDR_SIZE 1
+#define HCI_NOKIA_MAX_ALIVE_SIZE 255
+#define HCI_NOKIA_RADIO_HDR_SIZE 2
+#define HCI_NOKIA_MAX_RADIO_SIZE 255
+
+#define NOKIA_PROTO_PKT 0x44
+#define NOKIA_PROTO_BYTE 0x4c
+
+#define NOKIA_NEG_REQ 0x00
+#define NOKIA_NEG_ACK 0x20
+#define NOKIA_NEG_NAK 0x40
+
+#define H4_TYPE_SIZE 1
+
+#define NOKIA_RECV_ALIVE \
+ .type = HCI_NOKIA_ALIVE_PKT, \
+ .hlen = HCI_NOKIA_ALIVE_HDR_SIZE, \
+ .loff = 0, \
+ .lsize = 1, \
+ .maxlen = HCI_NOKIA_MAX_ALIVE_SIZE \
+
+#define NOKIA_RECV_NEG \
+ .type = HCI_NOKIA_NEG_PKT, \
+ .hlen = HCI_NOKIA_NEG_HDR_SIZE, \
+ .loff = 0, \
+ .lsize = 1, \
+ .maxlen = HCI_NOKIA_MAX_NEG_SIZE \
+
+#define NOKIA_RECV_RADIO \
+ .type = HCI_NOKIA_RADIO_PKT, \
+ .hlen = HCI_NOKIA_RADIO_HDR_SIZE, \
+ .loff = 1, \
+ .lsize = 1, \
+ .maxlen = HCI_NOKIA_MAX_RADIO_SIZE \
+
+struct hci_nokia_neg_hdr {
+ u8 dlen;
+} __packed;
+
+struct hci_nokia_neg_cmd {
+ u8 ack;
+ u16 baud;
+ u16 unused1;
+ u8 proto;
+ u16 sys_clk;
+ u16 unused2;
+} __packed;
+
+#define NOKIA_ALIVE_REQ 0x55
+#define NOKIA_ALIVE_RESP 0xcc
+
+struct hci_nokia_alive_hdr {
+ u8 dlen;
+} __packed;
+
+struct hci_nokia_alive_pkt {
+ u8 mid;
+ u8 unused;
+} __packed;
+
+struct hci_nokia_neg_evt {
+ u8 ack;
+ u16 baud;
+ u16 unused1;
+ u8 proto;
+ u16 sys_clk;
+ u16 unused2;
+ u8 man_id;
+ u8 ver_id;
+} __packed;
+
+#define MAX_BAUD_RATE 3692300
+#define SETUP_BAUD_RATE 921600
+#define INIT_BAUD_RATE 120000
+
+struct hci_nokia_radio_hdr {
+ u8 evt;
+ u8 dlen;
+} __packed;
+
+struct nokia_bt_dev {
+ struct hci_uart hu;
+ struct serdev_device *serdev;
+
+ struct gpio_desc *reset;
+ struct gpio_desc *wakeup_host;
+ struct gpio_desc *wakeup_bt;
+ unsigned long sysclk_speed;
+
+ int wake_irq;
+ struct sk_buff *rx_skb;
+ struct sk_buff_head txq;
+ bdaddr_t bdaddr;
+
+ int init_error;
+ struct completion init_completion;
+
+ u8 man_id;
+ u8 ver_id;
+
+ bool initialized;
+ bool tx_enabled;
+ bool rx_enabled;
+};
+
+static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb);
+
+static void nokia_flow_control(struct serdev_device *serdev, bool enable)
+{
+ if (enable) {
+ serdev_device_set_rts(serdev, true);
+ serdev_device_set_flow_control(serdev, true);
+ } else {
+ serdev_device_set_flow_control(serdev, false);
+ serdev_device_set_rts(serdev, false);
+ }
+}
+
+static irqreturn_t wakeup_handler(int irq, void *data)
+{
+ struct nokia_bt_dev *btdev = data;
+ struct device *dev = &btdev->serdev->dev;
+ int wake_state = gpiod_get_value(btdev->wakeup_host);
+
+ if (btdev->rx_enabled == wake_state)
+ return IRQ_HANDLED;
+
+ if (wake_state)
+ pm_runtime_get(dev);
+ else
+ pm_runtime_put(dev);
+
+ btdev->rx_enabled = wake_state;
+
+ return IRQ_HANDLED;
+}
+
+static int nokia_reset(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ int err;
+
+ /* reset routine */
+ gpiod_set_value_cansleep(btdev->reset, 1);
+ gpiod_set_value_cansleep(btdev->wakeup_bt, 1);
+
+ msleep(100);
+
+ /* safety check */
+ err = gpiod_get_value_cansleep(btdev->wakeup_host);
+ if (err == 1) {
+ dev_err(dev, "reset: host wakeup not low!");
+ return -EPROTO;
+ }
+
+ /* flush queue */
+ serdev_device_write_flush(btdev->serdev);
+
+ /* init uart */
+ nokia_flow_control(btdev->serdev, false);
+ serdev_device_set_baudrate(btdev->serdev, INIT_BAUD_RATE);
+
+ gpiod_set_value_cansleep(btdev->reset, 0);
+
+ /* wait for cts */
+ err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
+ if (err < 0) {
+ dev_err(dev, "CTS not received: %d", err);
+ return err;
+ }
+
+ nokia_flow_control(btdev->serdev, true);
+
+ return 0;
+}
+
+static int nokia_send_alive_packet(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ struct hci_nokia_alive_hdr *hdr;
+ struct hci_nokia_alive_pkt *pkt;
+ struct sk_buff *skb;
+ int len;
+
+ init_completion(&btdev->init_completion);
+
+ len = H4_TYPE_SIZE + sizeof(*hdr) + sizeof(*pkt);
+ skb = bt_skb_alloc(len, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ hci_skb_pkt_type(skb) = HCI_NOKIA_ALIVE_PKT;
+ memset(skb->data, 0x00, len);
+
+ hdr = (struct hci_nokia_alive_hdr *)skb_put(skb, sizeof(*hdr));
+ hdr->dlen = sizeof(*pkt);
+ pkt = (struct hci_nokia_alive_pkt *)skb_put(skb, sizeof(*pkt));
+ pkt->mid = NOKIA_ALIVE_REQ;
+
+ nokia_enqueue(hu, skb);
+ hci_uart_tx_wakeup(hu);
+
+ dev_dbg(dev, "Alive sent");
+
+ if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
+ msecs_to_jiffies(1000))) {
+ return -ETIMEDOUT;
+ }
+
+ if (btdev->init_error < 0)
+ return btdev->init_error;
+
+ return 0;
+}
+
+static int nokia_send_negotiation(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ struct hci_nokia_neg_cmd *neg_cmd;
+ struct hci_nokia_neg_hdr *neg_hdr;
+ struct sk_buff *skb;
+ int len, err;
+ u16 baud = DIV_ROUND_CLOSEST(btdev->sysclk_speed * 10, SETUP_BAUD_RATE);
+ int sysclk = btdev->sysclk_speed / 1000;
+
+ len = H4_TYPE_SIZE + sizeof(*neg_hdr) + sizeof(*neg_cmd);
+ skb = bt_skb_alloc(len, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ hci_skb_pkt_type(skb) = HCI_NOKIA_NEG_PKT;
+
+ neg_hdr = (struct hci_nokia_neg_hdr *)skb_put(skb, sizeof(*neg_hdr));
+ neg_hdr->dlen = sizeof(*neg_cmd);
+
+ neg_cmd = (struct hci_nokia_neg_cmd *)skb_put(skb, sizeof(*neg_cmd));
+ neg_cmd->ack = NOKIA_NEG_REQ;
+ neg_cmd->baud = cpu_to_le16(baud);
+ neg_cmd->unused1 = 0x0000;
+ neg_cmd->proto = NOKIA_PROTO_BYTE;
+ neg_cmd->sys_clk = cpu_to_le16(sysclk);
+ neg_cmd->unused2 = 0x0000;
+
+ btdev->init_error = 0;
+ init_completion(&btdev->init_completion);
+
+ nokia_enqueue(hu, skb);
+ hci_uart_tx_wakeup(hu);
+
+ dev_dbg(dev, "Negotiation sent");
+
+ if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
+ msecs_to_jiffies(10000))) {
+ return -ETIMEDOUT;
+ }
+
+ if (btdev->init_error < 0)
+ return btdev->init_error;
+
+ /* Change to previously negotiated speed. Flow Control
+ * is disabled until bluetooth adapter is ready to avoid
+ * broken bytes being received.
+ */
+ nokia_flow_control(btdev->serdev, false);
+ serdev_device_set_baudrate(btdev->serdev, SETUP_BAUD_RATE);
+ err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
+ if (err < 0) {
+ dev_err(dev, "CTS not received: %d", err);
+ return err;
+ }
+ nokia_flow_control(btdev->serdev, true);
+
+ dev_dbg(dev, "Negotiation successful");
+
+ return 0;
+}
+
+static int nokia_setup_fw(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ const char *fwname;
+ const struct firmware *fw;
+ const u8 *fw_ptr;
+ size_t fw_size;
+ int err;
+
+ dev_dbg(dev, "setup firmware");
+
+ if (btdev->man_id == NOKIA_ID_BCM2048) {
+ fwname = FIRMWARE_BCM2048;
+ } else if (btdev->man_id == NOKIA_ID_TI1271) {
+ fwname = FIRMWARE_TI1271;
+ } else {
+ dev_err(dev, "Unsupported bluetooth device!");
+ return -ENODEV;
+ }
+
+ err = request_firmware(&fw, fwname, dev);
+ if (err < 0) {
+ dev_err(dev, "%s: Failed to load Nokia firmware file (%d)",
+ hu->hdev->name, err);
+ return err;
+ }
+
+ fw_ptr = fw->data;
+ fw_size = fw->size;
+
+ while (fw_size >= 4) {
+ u16 pkt_size = get_unaligned_le16(fw_ptr);
+ u8 pkt_type = fw_ptr[2];
+ const struct hci_command_hdr *cmd;
+ u16 opcode;
+ struct sk_buff *skb;
+
+ switch (pkt_type) {
+ case HCI_COMMAND_PKT:
+ cmd = (struct hci_command_hdr *)(fw_ptr + 3);
+ opcode = le16_to_cpu(cmd->opcode);
+
+ skb = __hci_cmd_sync(hu->hdev, opcode, cmd->plen,
+ fw_ptr + 3 + HCI_COMMAND_HDR_SIZE,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ dev_err(dev, "%s: FW command %04x failed (%d)",
+ hu->hdev->name, opcode, err);
+ goto done;
+ }
+ kfree_skb(skb);
+ break;
+ case HCI_NOKIA_RADIO_PKT:
+ case HCI_NOKIA_NEG_PKT:
+ case HCI_NOKIA_ALIVE_PKT:
+ break;
+ }
+
+ fw_ptr += pkt_size + 2;
+ fw_size -= pkt_size + 2;
+ }
+
+done:
+ release_firmware(fw);
+ return err;
+}
+
+static int nokia_setup(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ int err;
+
+ btdev->initialized = false;
+
+ nokia_flow_control(btdev->serdev, false);
+
+ pm_runtime_get_sync(dev);
+
+ if (btdev->tx_enabled) {
+ gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
+ pm_runtime_put(&btdev->serdev->dev);
+ btdev->tx_enabled = false;
+ }
+
+ dev_dbg(dev, "protocol setup");
+
+ /* 0. reset connection */
+ err = nokia_reset(hu);
+ if (err < 0) {
+ dev_err(dev, "Reset failed: %d", err);
+ goto out;
+ }
+
+ /* 1. negotiate speed etc */
+ err = nokia_send_negotiation(hu);
+ if (err < 0) {
+ dev_err(dev, "Negotiation failed: %d", err);
+ goto out;
+ }
+
+ /* 2. verify correct setup using alive packet */
+ err = nokia_send_alive_packet(hu);
+ if (err < 0) {
+ dev_err(dev, "Alive check failed: %d", err);
+ goto out;
+ }
+
+ /* 3. send firmware */
+ err = nokia_setup_fw(hu);
+ if (err < 0) {
+ dev_err(dev, "Could not setup FW: %d", err);
+ goto out;
+ }
+
+ nokia_flow_control(btdev->serdev, false);
+ serdev_device_set_baudrate(btdev->serdev, MAX_BAUD_RATE);
+ nokia_flow_control(btdev->serdev, true);
+
+ if (btdev->man_id == NOKIA_ID_BCM2048) {
+ hu->hdev->set_bdaddr = btbcm_set_bdaddr;
+ set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
+ dev_dbg(dev, "bcm2048 has invalid bluetooth address!");
+ }
+
+ dev_dbg(dev, "protocol setup done!");
+
+ gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
+ pm_runtime_put(dev);
+ btdev->tx_enabled = false;
+ btdev->initialized = true;
+
+ return 0;
+out:
+ pm_runtime_put(dev);
+
+ return err;
+}
+
+static int nokia_open(struct hci_uart *hu)
+{
+ struct device *dev = &hu->serdev->dev;
+
+ dev_dbg(dev, "protocol open");
+
+ serdev_device_open(hu->serdev);
+
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static int nokia_flush(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+
+ dev_dbg(&btdev->serdev->dev, "flush device");
+
+ skb_queue_purge(&btdev->txq);
+
+ return 0;
+}
+
+static int nokia_close(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+
+ dev_dbg(dev, "close device");
+
+ btdev->initialized = false;
+
+ skb_queue_purge(&btdev->txq);
+
+ kfree_skb(btdev->rx_skb);
+
+ /* disable module */
+ gpiod_set_value(btdev->reset, 1);
+ gpiod_set_value(btdev->wakeup_bt, 0);
+
+ pm_runtime_disable(&btdev->serdev->dev);
+ serdev_device_close(btdev->serdev);
+
+ return 0;
+}
+
+/* Enqueue frame for transmittion (padding, crc, etc) */
+static int nokia_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ int err;
+
+ /* Prepend skb with frame type */
+ memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+ /* Packets must be word aligned */
+ if (skb->len % 2) {
+ err = skb_pad(skb, 1);
+ if (err)
+ return err;
+ *skb_put(skb, 1) = 0x00;
+ }
+
+ skb_queue_tail(&btdev->txq, skb);
+
+ return 0;
+}
+
+static int nokia_recv_negotiation_packet(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ struct hci_nokia_neg_hdr *hdr;
+ struct hci_nokia_neg_evt *evt;
+ int ret = 0;
+
+ hdr = (struct hci_nokia_neg_hdr *)skb->data;
+ if (hdr->dlen != sizeof(*evt)) {
+ btdev->init_error = -EIO;
+ ret = -EIO;
+ goto finish_neg;
+ }
+
+ evt = (struct hci_nokia_neg_evt *)skb_pull(skb, sizeof(*hdr));
+
+ if (evt->ack != NOKIA_NEG_ACK) {
+ dev_err(dev, "Negotiation received: wrong reply");
+ btdev->init_error = -EINVAL;
+ ret = -EINVAL;
+ goto finish_neg;
+ }
+
+ btdev->man_id = evt->man_id;
+ btdev->ver_id = evt->ver_id;
+
+ dev_dbg(dev, "Negotiation received: baud=%u:clk=%u:manu=%u:vers=%u",
+ evt->baud, evt->sys_clk, evt->man_id, evt->ver_id);
+
+finish_neg:
+ complete(&btdev->init_completion);
+ kfree_skb(skb);
+ return ret;
+}
+
+static int nokia_recv_alive_packet(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ struct hci_nokia_alive_hdr *hdr;
+ struct hci_nokia_alive_pkt *pkt;
+ int ret = 0;
+
+ hdr = (struct hci_nokia_alive_hdr *)skb->data;
+ if (hdr->dlen != sizeof(*pkt)) {
+ dev_err(dev, "Corrupted alive message");
+ btdev->init_error = -EIO;
+ ret = -EIO;
+ goto finish_alive;
+ }
+
+ pkt = (struct hci_nokia_alive_pkt *)skb_pull(skb, sizeof(*hdr));
+
+ if (pkt->mid != NOKIA_ALIVE_RESP) {
+ dev_err(dev, "Alive received: invalid response: 0x%02x!",
+ pkt->mid);
+ btdev->init_error = -EINVAL;
+ ret = -EINVAL;
+ goto finish_alive;
+ }
+
+ dev_dbg(dev, "Alive received");
+
+finish_alive:
+ complete(&btdev->init_completion);
+ kfree_skb(skb);
+ return ret;
+}
+
+static int nokia_recv_radio(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ /* Packets received on the dedicated radio channel are
+ * HCI events and so feed them back into the core.
+ */
+ hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
+ return hci_recv_frame(hdev, skb);
+}
+
+/* Recv data */
+static const struct h4_recv_pkt nokia_recv_pkts[] = {
+ { H4_RECV_ACL, .recv = hci_recv_frame },
+ { H4_RECV_SCO, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = hci_recv_frame },
+ { NOKIA_RECV_ALIVE, .recv = nokia_recv_alive_packet },
+ { NOKIA_RECV_NEG, .recv = nokia_recv_negotiation_packet },
+ { NOKIA_RECV_RADIO, .recv = nokia_recv_radio },
+};
+
+static int nokia_recv(struct hci_uart *hu, const void *data, int count)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ int err;
+
+ if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
+ return -EUNATCH;
+
+ btdev->rx_skb = h4_recv_buf(hu->hdev, btdev->rx_skb, data, count,
+ nokia_recv_pkts, ARRAY_SIZE(nokia_recv_pkts));
+ if (IS_ERR(btdev->rx_skb)) {
+ err = PTR_ERR(btdev->rx_skb);
+ dev_err(dev, "Frame reassembly failed (%d)", err);
+ btdev->rx_skb = NULL;
+ return err;
+ }
+
+ return count;
+}
+
+static struct sk_buff *nokia_dequeue(struct hci_uart *hu)
+{
+ struct nokia_bt_dev *btdev = hu->priv;
+ struct device *dev = &btdev->serdev->dev;
+ struct sk_buff *result = skb_dequeue(&btdev->txq);
+
+ if (!btdev->initialized)
+ return result;
+
+ if (btdev->tx_enabled == !!result)
+ return result;
+
+ if (result) {
+ pm_runtime_get_sync(dev);
+ gpiod_set_value_cansleep(btdev->wakeup_bt, 1);
+ } else {
+ serdev_device_wait_until_sent(btdev->serdev, 0);
+ gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
+ pm_runtime_put(dev);
+ }
+
+ btdev->tx_enabled = !!result;
+
+ return result;
+}
+
+static const struct hci_uart_proto nokia_proto = {
+ .id = HCI_UART_NOKIA,
+ .name = "Nokia",
+ .open = nokia_open,
+ .close = nokia_close,
+ .recv = nokia_recv,
+ .enqueue = nokia_enqueue,
+ .dequeue = nokia_dequeue,
+ .flush = nokia_flush,
+ .setup = nokia_setup,
+ .manufacturer = 1,
+};
+
+static int nokia_bluetooth_serdev_probe(struct serdev_device *serdev)
+{
+ struct device *dev = &serdev->dev;
+ struct nokia_bt_dev *btdev;
+ struct clk *sysclk;
+ int err = 0;
+
+ btdev = devm_kzalloc(dev, sizeof(*btdev), GFP_KERNEL);
+ if (!btdev)
+ return -ENOMEM;
+
+ btdev->hu.serdev = btdev->serdev = serdev;
+ serdev_device_set_drvdata(serdev, btdev);
+
+ btdev->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(btdev->reset)) {
+ err = PTR_ERR(btdev->reset);
+ dev_err(dev, "could not get reset gpio: %d", err);
+ return err;
+ }
+
+ btdev->wakeup_host = devm_gpiod_get(dev, "host-wakeup", GPIOD_IN);
+ if (IS_ERR(btdev->wakeup_host)) {
+ err = PTR_ERR(btdev->wakeup_host);
+ dev_err(dev, "could not get host wakeup gpio: %d", err);
+ return err;
+ }
+
+ btdev->wake_irq = gpiod_to_irq(btdev->wakeup_host);
+
+ err = devm_request_threaded_irq(dev, btdev->wake_irq, NULL,
+ wakeup_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "wakeup", btdev);
+ if (err) {
+ dev_err(dev, "could request wakeup irq: %d", err);
+ return err;
+ }
+
+ btdev->wakeup_bt = devm_gpiod_get(dev, "bluetooth-wakeup",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(btdev->wakeup_bt)) {
+ err = PTR_ERR(btdev->wakeup_bt);
+ dev_err(dev, "could not get BT wakeup gpio: %d", err);
+ return err;
+ }
+
+ sysclk = devm_clk_get(dev, "sysclk");
+ if (IS_ERR(sysclk)) {
+ err = PTR_ERR(sysclk);
+ dev_err(dev, "could not get sysclk: %d", err);
+ return err;
+ }
+
+ clk_prepare_enable(sysclk);
+ btdev->sysclk_speed = clk_get_rate(sysclk);
+ clk_disable_unprepare(sysclk);
+
+ skb_queue_head_init(&btdev->txq);
+
+ btdev->hu.priv = btdev;
+ btdev->hu.alignment = 2; /* Nokia H4+ is word aligned */
+
+ err = hci_uart_register_device(&btdev->hu, &nokia_proto);
+ if (err) {
+ dev_err(dev, "could not register bluetooth uart: %d", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void nokia_bluetooth_serdev_remove(struct serdev_device *serdev)
+{
+ struct nokia_bt_dev *btdev = serdev_device_get_drvdata(serdev);
+ struct hci_uart *hu = &btdev->hu;
+ struct hci_dev *hdev = hu->hdev;
+
+ cancel_work_sync(&hu->write_work);
+
+ hci_unregister_dev(hdev);
+ hci_free_dev(hdev);
+ hu->proto->close(hu);
+
+ pm_runtime_disable(&btdev->serdev->dev);
+}
+
+static int nokia_bluetooth_runtime_suspend(struct device *dev)
+{
+ struct serdev_device *serdev = to_serdev_device(dev);
+
+ nokia_flow_control(serdev, false);
+ return 0;
+}
+
+static int nokia_bluetooth_runtime_resume(struct device *dev)
+{
+ struct serdev_device *serdev = to_serdev_device(dev);
+
+ nokia_flow_control(serdev, true);
+ return 0;
+}
+
+static const struct dev_pm_ops nokia_bluetooth_pm_ops = {
+ SET_RUNTIME_PM_OPS(nokia_bluetooth_runtime_suspend,
+ nokia_bluetooth_runtime_resume,
+ NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id nokia_bluetooth_of_match[] = {
+ { .compatible = "nokia,h4p-bluetooth", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nokia_bluetooth_of_match);
+#endif
+
+static struct serdev_device_driver nokia_bluetooth_serdev_driver = {
+ .probe = nokia_bluetooth_serdev_probe,
+ .remove = nokia_bluetooth_serdev_remove,
+ .driver = {
+ .name = "nokia-bluetooth",
+ .pm = &nokia_bluetooth_pm_ops,
+ .of_match_table = of_match_ptr(nokia_bluetooth_of_match),
+ },
+};
+
+module_serdev_device_driver(nokia_bluetooth_serdev_driver);
--
2.11.0
^ permalink raw reply related
* [PATCHv2 08/11] dt-bindings: net: bluetooth: Add nokia-bluetooth
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
Add binding document for serial bluetooth chips using
Nokia H4+ protocol.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
Changes since PATCHv1:
* change compatible strings
* mention active high/low state for GPIOs
---
.../devicetree/bindings/net/nokia-bluetooth.txt | 51 ++++++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/nokia-bluetooth.txt
diff --git a/Documentation/devicetree/bindings/net/nokia-bluetooth.txt b/Documentation/devicetree/bindings/net/nokia-bluetooth.txt
new file mode 100644
index 000000000000..42be7dc9a70b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/nokia-bluetooth.txt
@@ -0,0 +1,51 @@
+Nokia Bluetooth Chips
+---------------------
+
+Nokia phones often come with UART connected bluetooth chips from different
+vendors and modified device API. Those devices speak a protocol named H4+
+(also known as h4p) by Nokia, which is similar to the H4 protocol from the
+Bluetooth standard. In addition to the H4 protocol it specifies two more
+UART status lines for wakeup of UART transceivers to improve power management
+and a few new packet types used to negotiate uart speed.
+
+Required properties:
+
+ - compatible: should contain "nokia,h4p-bluetooth" as well as one of the following:
+ * "brcm,bcm2048-nokia"
+ * "ti,wl1271-bluetooth-nokia"
+ - reset-gpios: GPIO specifier, used to reset the BT module (active low)
+ - bluetooth-wakeup-gpios: GPIO specifier, used to wakeup the BT module (active high)
+ - host-wakeup-gpios: GPIO specifier, used to wakeup the host processor (active high)
+ - clock-names: should be "sysclk"
+ - clocks: should contain a clock specifier for every name in clock-names
+
+Optional properties:
+
+ - None
+
+Example:
+
+/ {
+ /* controlled (enabled/disabled) directly by BT module */
+ bluetooth_clk: vctcxo {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+
+ bluetooth {
+ compatible = "ti,wl1271-bluetooth-nokia", "nokia,h4p-bluetooth";
+
+ reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; /* gpio26 */
+ host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* gpio101 */
+ bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* gpio37 */
+
+ clocks = <&bluetooth_clk>;
+ clock-names = "sysclk";
+ };
+};
--
2.11.0
^ permalink raw reply related
* [PATCHv2 07/11] serdev: add helpers for cts and rts handling
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
Add serdev helper functions for handling of cts and rts
lines using the serdev's tiocm functions.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
include/linux/serdev.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 3ad1d695f947..8cdce2ea0d51 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/device.h>
#include <asm-generic/termios.h>
+#include <linux/delay.h>
struct serdev_controller;
struct serdev_device;
@@ -254,6 +255,36 @@ static inline int serdev_device_write_room(struct serdev_device *sdev)
#endif /* CONFIG_SERIAL_DEV_BUS */
+static inline bool serdev_device_get_cts(struct serdev_device *serdev)
+{
+ int status = serdev_device_get_tiocm(serdev);
+ return !!(status & TIOCM_CTS);
+}
+
+static inline int serdev_device_wait_for_cts(struct serdev_device *serdev, bool state, int timeout_ms)
+{
+ unsigned long timeout;
+ bool signal;
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ while (!time_after(jiffies, timeout)) {
+ signal = serdev_device_get_cts(serdev);
+ if (signal == state)
+ return 0;
+ usleep_range(1000, 2000);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enable)
+{
+ if (enable)
+ return serdev_device_set_tiocm(serdev, TIOCM_OUT2 | TIOCM_RTS, 0);
+ else
+ return serdev_device_set_tiocm(serdev, 0, TIOCM_OUT2 | TIOCM_RTS);
+}
+
/*
* serdev hooks into TTY core
*/
--
2.11.0
^ permalink raw reply related
* [PATCHv2 06/11] serdev: implement get/set tiocm
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
Add method for getting and setting tiocm.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
drivers/tty/serdev/core.c | 22 ++++++++++++++++++++++
drivers/tty/serdev/serdev-ttyport.c | 24 ++++++++++++++++++++++++
include/linux/serdev.h | 13 +++++++++++++
3 files changed, 59 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index a63b74031e22..1e1cbae3a0ea 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -184,6 +184,28 @@ void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout)
}
EXPORT_SYMBOL_GPL(serdev_device_wait_until_sent);
+int serdev_device_get_tiocm(struct serdev_device *serdev)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->get_tiocm)
+ return -ENOTSUPP;
+
+ return ctrl->ops->get_tiocm(ctrl);
+}
+EXPORT_SYMBOL_GPL(serdev_device_get_tiocm);
+
+int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->set_tiocm)
+ return -ENOTSUPP;
+
+ return ctrl->ops->set_tiocm(ctrl, set, clear);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_tiocm);
+
static int serdev_drv_probe(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index db2bc601e554..c5bdb901ff11 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -179,6 +179,28 @@ static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout
tty_wait_until_sent(tty, timeout);
}
+static int ttyport_get_tiocm(struct serdev_controller *ctrl)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+
+ if (!tty->ops->tiocmget)
+ return -ENOTSUPP;
+
+ return tty->driver->ops->tiocmget(tty);
+}
+
+static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, unsigned int clear)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+
+ if (!tty->ops->tiocmset)
+ return -ENOTSUPP;
+
+ return tty->driver->ops->tiocmset(tty, set, clear);
+}
+
static const struct serdev_controller_ops ctrl_ops = {
.write_buf = ttyport_write_buf,
.write_flush = ttyport_write_flush,
@@ -188,6 +210,8 @@ static const struct serdev_controller_ops ctrl_ops = {
.set_flow_control = ttyport_set_flow_control,
.set_baudrate = ttyport_set_baudrate,
.wait_until_sent = ttyport_wait_until_sent,
+ .get_tiocm = ttyport_get_tiocm,
+ .set_tiocm = ttyport_set_tiocm,
};
struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index a308b206d204..3ad1d695f947 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <asm-generic/termios.h>
struct serdev_controller;
struct serdev_device;
@@ -82,6 +83,8 @@ struct serdev_controller_ops {
void (*set_flow_control)(struct serdev_controller *, bool);
unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
void (*wait_until_sent)(struct serdev_controller *, long);
+ int (*get_tiocm)(struct serdev_controller *);
+ int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
};
/**
@@ -188,6 +191,8 @@ void serdev_device_close(struct serdev_device *);
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
void serdev_device_set_flow_control(struct serdev_device *, bool);
void serdev_device_wait_until_sent(struct serdev_device *, long);
+int serdev_device_get_tiocm(struct serdev_device *);
+int serdev_device_set_tiocm(struct serdev_device *, int, int);
int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
void serdev_device_write_flush(struct serdev_device *);
int serdev_device_write_room(struct serdev_device *);
@@ -226,6 +231,14 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
}
static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
+static inline int serdev_device_get_tiocm(struct serdev_device *serdev)
+{
+ return -ENOTSUPP;
+}
+static inline int serdev_device_set_tiocm(struct serdev_controller *serdev, int set, int clear)
+{
+ return -ENOTSUPP;
+}
static inline int serdev_device_write_buf(struct serdev_device *sdev, const unsigned char *buf, size_t count)
{
return -ENODEV;
--
2.11.0
^ permalink raw reply related
* [PATCHv2 05/11] serdev: add serdev_device_wait_until_sent
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
Add method, which waits until the transmission buffer has been sent.
Note, that the change in ttyport_write_wakeup is related, since
tty_wait_until_sent will hang without that change.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
drivers/tty/serdev/core.c | 11 +++++++++++
drivers/tty/serdev/serdev-ttyport.c | 15 ++++++++++++++-
include/linux/serdev.h | 3 +++
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index f4c6c90add78..a63b74031e22 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -173,6 +173,17 @@ void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable)
}
EXPORT_SYMBOL_GPL(serdev_device_set_flow_control);
+void serdev_device_wait_until_sent(struct serdev_device *serdev, long timeout)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->wait_until_sent)
+ return;
+
+ ctrl->ops->wait_until_sent(ctrl, timeout);
+}
+EXPORT_SYMBOL_GPL(serdev_device_wait_until_sent);
+
static int serdev_drv_probe(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index d05393594f15..db2bc601e554 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -14,6 +14,7 @@
#include <linux/serdev.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
+#include <linux/poll.h>
#define SERPORT_ACTIVE 1
@@ -47,10 +48,13 @@ static void ttyport_write_wakeup(struct tty_port *port)
struct serport *serport = serdev_controller_get_drvdata(ctrl);
if (!test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &port->tty->flags))
- return;
+ goto out;
if (test_bit(SERPORT_ACTIVE, &serport->flags))
serdev_controller_write_wakeup(ctrl);
+
+out:
+ wake_up_interruptible_poll(&port->tty->write_wait, POLLOUT);
}
static const struct tty_port_client_operations client_ops = {
@@ -167,6 +171,14 @@ static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable
tty_set_termios(tty, &ktermios);
}
+static void ttyport_wait_until_sent(struct serdev_controller *ctrl, long timeout)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+
+ tty_wait_until_sent(tty, timeout);
+}
+
static const struct serdev_controller_ops ctrl_ops = {
.write_buf = ttyport_write_buf,
.write_flush = ttyport_write_flush,
@@ -175,6 +187,7 @@ static const struct serdev_controller_ops ctrl_ops = {
.close = ttyport_close,
.set_flow_control = ttyport_set_flow_control,
.set_baudrate = ttyport_set_baudrate,
+ .wait_until_sent = ttyport_wait_until_sent,
};
struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 9519da6253a8..a308b206d204 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -81,6 +81,7 @@ struct serdev_controller_ops {
void (*close)(struct serdev_controller *);
void (*set_flow_control)(struct serdev_controller *, bool);
unsigned int (*set_baudrate)(struct serdev_controller *, unsigned int);
+ void (*wait_until_sent)(struct serdev_controller *, long);
};
/**
@@ -186,6 +187,7 @@ int serdev_device_open(struct serdev_device *);
void serdev_device_close(struct serdev_device *);
unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
void serdev_device_set_flow_control(struct serdev_device *, bool);
+void serdev_device_wait_until_sent(struct serdev_device *, long);
int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
void serdev_device_write_flush(struct serdev_device *);
int serdev_device_write_room(struct serdev_device *);
@@ -223,6 +225,7 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
return 0;
}
static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
+static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
static inline int serdev_device_write_buf(struct serdev_device *sdev, const unsigned char *buf, size_t count)
{
return -ENODEV;
--
2.11.0
^ permalink raw reply related
* [PATCHv2 04/11] tty: serial: omap: add UPF_BOOT_AUTOCONF flag for DT init
From: Sebastian Reichel @ 2017-03-21 22:32 UTC (permalink / raw)
To: Sebastian Reichel, Marcel Holtmann, Gustavo Padovan,
Johan Hedberg, Rob Herring
Cc: Samuel Thibault, Pavel Machek, Tony Lindgren, Greg Kroah-Hartman,
Jiri Slaby, Mark Rutland, linux-bluetooth, linux-serial,
devicetree, linux-kernel
In-Reply-To: <20170321223216.11733-1-sre@kernel.org>
The UPF_BOOT_AUTOCONF flag is needed for proper
flow control support.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
---
drivers/tty/serial/omap-serial.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6c6f82ad8d5c..a4734649a0f0 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1597,6 +1597,9 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
of_property_read_u32(dev->of_node, "clock-frequency",
&omap_up_info->uartclk);
+
+ omap_up_info->flags = UPF_BOOT_AUTOCONF;
+
return omap_up_info;
}
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox