Skip to content

Commit 3718055

Browse files
robherringholtmann
authored andcommitted
bluetooth: hci_uart: add LL protocol serdev driver support
Turns out that the LL protocol and the TI-ST are the same thing AFAICT. The TI-ST adds firmware loading, GPIO control, and shared access for NFC, FM radio, etc. For now, we're only implementing what is needed for BT. This mirrors other drivers like BCM and Intel, but uses the new serdev bus. The firmware loading is greatly simplified by using existing infrastructure to send commands. It may be a bit slower than the original code using synchronous functions, but the real bottleneck is likely doing firmware load at 115.2kbps. Signed-off-by: Rob Herring <[email protected]> Cc: Marcel Holtmann <[email protected]> Cc: Gustavo Padovan <[email protected]> Cc: Johan Hedberg <[email protected]> Cc: [email protected] Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 31927e5 commit 3718055

File tree

1 file changed

+261
-1
lines changed

1 file changed

+261
-1
lines changed

drivers/bluetooth/hci_ll.c

Lines changed: 261 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,24 @@
3434
#include <linux/sched.h>
3535
#include <linux/types.h>
3636
#include <linux/fcntl.h>
37+
#include <linux/firmware.h>
3738
#include <linux/interrupt.h>
3839
#include <linux/ptrace.h>
3940
#include <linux/poll.h>
4041

4142
#include <linux/slab.h>
42-
#include <linux/tty.h>
4343
#include <linux/errno.h>
4444
#include <linux/string.h>
4545
#include <linux/signal.h>
4646
#include <linux/ioctl.h>
47+
#include <linux/of.h>
48+
#include <linux/serdev.h>
4749
#include <linux/skbuff.h>
50+
#include <linux/ti_wilink_st.h>
4851

4952
#include <net/bluetooth/bluetooth.h>
5053
#include <net/bluetooth/hci_core.h>
54+
#include <linux/gpio/consumer.h>
5155

5256
#include "hci_uart.h"
5357

@@ -76,6 +80,12 @@ struct hcill_cmd {
7680
u8 cmd;
7781
} __packed;
7882

83+
struct ll_device {
84+
struct hci_uart hu;
85+
struct serdev_device *serdev;
86+
struct gpio_desc *enable_gpio;
87+
};
88+
7989
struct ll_struct {
8090
unsigned long rx_state;
8191
unsigned long rx_count;
@@ -136,6 +146,9 @@ static int ll_open(struct hci_uart *hu)
136146

137147
hu->priv = ll;
138148

149+
if (hu->serdev)
150+
serdev_device_open(hu->serdev);
151+
139152
return 0;
140153
}
141154

@@ -164,6 +177,13 @@ static int ll_close(struct hci_uart *hu)
164177

165178
kfree_skb(ll->rx_skb);
166179

180+
if (hu->serdev) {
181+
struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
182+
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
183+
184+
serdev_device_close(hu->serdev);
185+
}
186+
167187
hu->priv = NULL;
168188

169189
kfree(ll);
@@ -505,9 +525,245 @@ static struct sk_buff *ll_dequeue(struct hci_uart *hu)
505525
return skb_dequeue(&ll->txq);
506526
}
507527

528+
#if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
529+
static int read_local_version(struct hci_dev *hdev)
530+
{
531+
int err = 0;
532+
unsigned short version = 0;
533+
struct sk_buff *skb;
534+
struct hci_rp_read_local_version *ver;
535+
536+
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT);
537+
if (IS_ERR(skb)) {
538+
bt_dev_err(hdev, "Reading TI version information failed (%ld)",
539+
PTR_ERR(skb));
540+
err = PTR_ERR(skb);
541+
goto out;
542+
}
543+
if (skb->len != sizeof(*ver)) {
544+
err = -EILSEQ;
545+
goto out;
546+
}
547+
548+
ver = (struct hci_rp_read_local_version *)skb->data;
549+
if (le16_to_cpu(ver->manufacturer) != 13) {
550+
err = -ENODEV;
551+
goto out;
552+
}
553+
554+
version = le16_to_cpu(ver->lmp_subver);
555+
556+
out:
557+
if (err) bt_dev_err(hdev, "Failed to read TI version info: %d", err);
558+
kfree_skb(skb);
559+
return err ? err : version;
560+
}
561+
562+
/**
563+
* download_firmware -
564+
* internal function which parses through the .bts firmware
565+
* script file intreprets SEND, DELAY actions only as of now
566+
*/
567+
static int download_firmware(struct ll_device *lldev)
568+
{
569+
unsigned short chip, min_ver, maj_ver;
570+
int version, err, len;
571+
unsigned char *ptr, *action_ptr;
572+
unsigned char bts_scr_name[40]; /* 40 char long bts scr name? */
573+
const struct firmware *fw;
574+
struct sk_buff *skb;
575+
struct hci_command *cmd;
576+
577+
version = read_local_version(lldev->hu.hdev);
578+
if (version < 0)
579+
return version;
580+
581+
chip = (version & 0x7C00) >> 10;
582+
min_ver = (version & 0x007F);
583+
maj_ver = (version & 0x0380) >> 7;
584+
if (version & 0x8000)
585+
maj_ver |= 0x0008;
586+
587+
snprintf(bts_scr_name, sizeof(bts_scr_name),
588+
"ti-connectivity/TIInit_%d.%d.%d.bts",
589+
chip, maj_ver, min_ver);
590+
591+
err = request_firmware(&fw, bts_scr_name, &lldev->serdev->dev);
592+
if (err || !fw->data || !fw->size) {
593+
bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s",
594+
err, bts_scr_name);
595+
return -EINVAL;
596+
}
597+
ptr = (void *)fw->data;
598+
len = fw->size;
599+
/* bts_header to remove out magic number and
600+
* version
601+
*/
602+
ptr += sizeof(struct bts_header);
603+
len -= sizeof(struct bts_header);
604+
605+
while (len > 0 && ptr) {
606+
bt_dev_dbg(lldev->hu.hdev, " action size %d, type %d ",
607+
((struct bts_action *)ptr)->size,
608+
((struct bts_action *)ptr)->type);
609+
610+
action_ptr = &(((struct bts_action *)ptr)->data[0]);
611+
612+
switch (((struct bts_action *)ptr)->type) {
613+
case ACTION_SEND_COMMAND: /* action send */
614+
bt_dev_dbg(lldev->hu.hdev, "S");
615+
cmd = (struct hci_command *)action_ptr;
616+
if (cmd->opcode == 0xff36) {
617+
/* ignore remote change
618+
* baud rate HCI VS command */
619+
bt_dev_warn(lldev->hu.hdev, "change remote baud rate command in firmware");
620+
break;
621+
}
622+
if (cmd->prefix != 1)
623+
bt_dev_dbg(lldev->hu.hdev, "command type %d\n", cmd->prefix);
624+
625+
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
626+
if (IS_ERR(skb)) {
627+
bt_dev_err(lldev->hu.hdev, "send command failed\n");
628+
goto out_rel_fw;
629+
}
630+
kfree_skb(skb);
631+
break;
632+
case ACTION_WAIT_EVENT: /* wait */
633+
/* no need to wait as command was synchronous */
634+
bt_dev_dbg(lldev->hu.hdev, "W");
635+
break;
636+
case ACTION_DELAY: /* sleep */
637+
bt_dev_info(lldev->hu.hdev, "sleep command in scr");
638+
mdelay(((struct bts_action_delay *)action_ptr)->msec);
639+
break;
640+
}
641+
len -= (sizeof(struct bts_action) +
642+
((struct bts_action *)ptr)->size);
643+
ptr += sizeof(struct bts_action) +
644+
((struct bts_action *)ptr)->size;
645+
}
646+
647+
out_rel_fw:
648+
/* fw download complete */
649+
release_firmware(fw);
650+
return err;
651+
}
652+
653+
static int ll_setup(struct hci_uart *hu)
654+
{
655+
int err, retry = 3;
656+
struct ll_device *lldev;
657+
struct serdev_device *serdev = hu->serdev;
658+
u32 speed;
659+
660+
if (!serdev)
661+
return 0;
662+
663+
lldev = serdev_device_get_drvdata(serdev);
664+
665+
serdev_device_set_flow_control(serdev, true);
666+
667+
do {
668+
/* Configure BT_EN to HIGH state */
669+
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
670+
msleep(5);
671+
gpiod_set_value_cansleep(lldev->enable_gpio, 1);
672+
msleep(100);
673+
674+
err = download_firmware(lldev);
675+
if (!err)
676+
break;
677+
678+
/* Toggle BT_EN and retry */
679+
bt_dev_err(hu->hdev, "download firmware failed, retrying...");
680+
} while (retry--);
681+
682+
if (err)
683+
return err;
684+
685+
/* Operational speed if any */
686+
if (hu->oper_speed)
687+
speed = hu->oper_speed;
688+
else if (hu->proto->oper_speed)
689+
speed = hu->proto->oper_speed;
690+
else
691+
speed = 0;
692+
693+
if (speed) {
694+
struct sk_buff *skb = __hci_cmd_sync(hu->hdev, 0xff36, sizeof(speed), &speed, HCI_INIT_TIMEOUT);
695+
if (!IS_ERR(skb)) {
696+
kfree_skb(skb);
697+
serdev_device_set_baudrate(serdev, speed);
698+
}
699+
}
700+
701+
return 0;
702+
}
703+
704+
static const struct hci_uart_proto llp;
705+
706+
static int hci_ti_probe(struct serdev_device *serdev)
707+
{
708+
struct hci_uart *hu;
709+
struct ll_device *lldev;
710+
u32 max_speed = 3000000;
711+
712+
lldev = devm_kzalloc(&serdev->dev, sizeof(struct ll_device), GFP_KERNEL);
713+
if (!lldev)
714+
return -ENOMEM;
715+
hu = &lldev->hu;
716+
717+
serdev_device_set_drvdata(serdev, lldev);
718+
lldev->serdev = hu->serdev = serdev;
719+
720+
lldev->enable_gpio = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW);
721+
if (IS_ERR(lldev->enable_gpio))
722+
return PTR_ERR(lldev->enable_gpio);
723+
724+
of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
725+
hci_uart_set_speeds(hu, 115200, max_speed);
726+
727+
return hci_uart_register_device(hu, &llp);
728+
}
729+
730+
static void hci_ti_remove(struct serdev_device *serdev)
731+
{
732+
struct ll_device *lldev = serdev_device_get_drvdata(serdev);
733+
struct hci_uart *hu = &lldev->hu;
734+
struct hci_dev *hdev = hu->hdev;
735+
736+
cancel_work_sync(&hu->write_work);
737+
738+
hci_unregister_dev(hdev);
739+
hci_free_dev(hdev);
740+
hu->proto->close(hu);
741+
}
742+
743+
static const struct of_device_id hci_ti_of_match[] = {
744+
{ .compatible = "ti,wl1831-st" },
745+
{ .compatible = "ti,wl1835-st" },
746+
{ .compatible = "ti,wl1837-st" },
747+
{},
748+
};
749+
MODULE_DEVICE_TABLE(of, hci_ti_of_match);
750+
751+
static struct serdev_device_driver hci_ti_drv = {
752+
.driver = {
753+
.name = "hci-ti",
754+
.of_match_table = of_match_ptr(hci_ti_of_match),
755+
},
756+
.probe = hci_ti_probe,
757+
.remove = hci_ti_remove,
758+
};
759+
#else
760+
#define ll_setup NULL
761+
#endif
762+
508763
static const struct hci_uart_proto llp = {
509764
.id = HCI_UART_LL,
510765
.name = "LL",
766+
.setup = ll_setup,
511767
.open = ll_open,
512768
.close = ll_close,
513769
.recv = ll_recv,
@@ -518,10 +774,14 @@ static const struct hci_uart_proto llp = {
518774

519775
int __init ll_init(void)
520776
{
777+
serdev_device_driver_register(&hci_ti_drv);
778+
521779
return hci_uart_register_proto(&llp);
522780
}
523781

524782
int __exit ll_deinit(void)
525783
{
784+
serdev_device_driver_unregister(&hci_ti_drv);
785+
526786
return hci_uart_unregister_proto(&llp);
527787
}

0 commit comments

Comments
 (0)