kernel: import series to support Renesas Bluetooth HCI
[openwrt/staging/dangole.git] / target / linux / generic / pending-6.1 / 900-0002-Adding-DA16600-reset-by-GPIO.patch
1 From 03b82d621adb7145d008eabb8995f14ad9582d56 Mon Sep 17 00:00:00 2001
2 From: Alvin Park <alvin.park.pv@renesas.com>
3 Date: Wed, 4 May 2022 17:02:26 +0900
4 Subject: [PATCH] Adding DA16600 reset by GPIO
5
6 ---
7 drivers/bluetooth/hci_renesas.c | 51 ++++++++++++++++++++++++++++++++-
8 1 file changed, 50 insertions(+), 1 deletion(-)
9
10 --- a/drivers/bluetooth/hci_renesas.c
11 +++ b/drivers/bluetooth/hci_renesas.c
12 @@ -18,6 +18,7 @@
13 #include <linux/module.h>
14 #include <linux/of.h>
15 #include <linux/serdev.h>
16 +#include <linux/gpio/consumer.h>
17 #include <net/bluetooth/bluetooth.h>
18 #include <net/bluetooth/hci_core.h>
19
20 @@ -37,6 +38,10 @@ enum {
21 STATE_FW_BOOTED
22 };
23
24 +#define VERSION "0.1"
25 +
26 +#define FIRMWARE_DA14531 "renesas/hci_531.bin"
27 +
28 #define STX 0x02
29 #define SOH 0x01
30 #define ACK 0x06
31 @@ -45,6 +50,8 @@ enum {
32
33 struct renesas_serdev {
34 struct hci_uart hu;
35 +
36 + struct gpio_desc *reset;
37 };
38
39 struct renesas_data {
40 @@ -161,6 +168,32 @@ static int renesas_send_fw_size(struct h
41 return 0;
42 }
43
44 +static void reset_device(struct gpio_desc *gpio)
45 +{
46 + if (gpiod_get_value(gpio) == 0) {
47 + gpiod_set_value_cansleep(gpio, 1);
48 + usleep_range(1000, 2000);
49 + }
50 + gpiod_set_value_cansleep(gpio, 0);
51 + usleep_range(5000, 10000);
52 + gpiod_direction_input(gpio);
53 +}
54 +
55 +static void renesas_reset(struct hci_uart *hu)
56 +{
57 + struct serdev_device *serdev = hu->serdev;
58 + if (serdev) {
59 + struct renesas_serdev *rdatadev = serdev_device_get_drvdata(serdev);
60 + if (rdatadev && rdatadev->reset) {
61 + reset_device(rdatadev->reset);
62 + } else {
63 + bt_dev_warn(hu->hdev, "Reset pin is not available!");
64 + }
65 + } else {
66 + bt_dev_warn(hu->hdev, "Reset is required!");
67 + }
68 +}
69 +
70 static int renesas_load_firmware(struct hci_dev *hdev, const char *name)
71 {
72 struct hci_uart *hu = hci_get_drvdata(hdev);
73 @@ -189,6 +222,9 @@ static int renesas_load_firmware(struct
74 rdata->state = STATE_FW_INIT;
75 set_bit(STATE_FW_STX_PENDING, &rdata->flags);
76
77 + /* reset */
78 + renesas_reset(hu);
79 +
80 while (rdata->state != STATE_FW_DONE) {
81 struct sk_buff *skb;
82
83 @@ -296,7 +332,7 @@ static int renesas_setup(struct hci_uart
84
85 hci_uart_set_flow_control(hu, true);
86
87 - err = renesas_load_firmware(hu->hdev, "renesas/hci_531.bin");
88 + err = renesas_load_firmware(hu->hdev, FIRMWARE_DA14531);
89 if (err)
90 return err;
91
92 @@ -432,6 +468,13 @@ static int renesas_serdev_probe(struct s
93 rdatadev->hu.serdev = serdev;
94 serdev_device_set_drvdata(serdev, rdatadev);
95
96 + rdatadev->reset = devm_gpiod_get(&serdev->dev, "reset", GPIOD_OUT_HIGH);
97 + if (IS_ERR(rdatadev->reset)) {
98 + int err = 0;
99 + err = PTR_ERR(rdatadev->reset);
100 + dev_warn(&serdev->dev, "could not get reset gpio: %d", err);
101 + }
102 +
103 return hci_uart_register_device(&rdatadev->hu, &renesas_proto);
104 }
105
106 @@ -472,3 +515,9 @@ int __exit renesas_deinit(void)
107
108 return hci_uart_unregister_proto(&renesas_proto);
109 }
110 +
111 +MODULE_AUTHOR("Alvin Park <alvin.park.pv@renesas.com>");
112 +MODULE_DESCRIPTION("Renesas Bluetooth Serial driver ver " VERSION);
113 +MODULE_VERSION(VERSION);
114 +MODULE_LICENSE("GPL");
115 +MODULE_FIRMWARE(FIRMWARE_DA14531);