.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * |
---|
3 | 4 | * Bluetooth HCI UART driver for Broadcom devices |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2015 Intel Corporation |
---|
6 | | - * |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option) any later version. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, |
---|
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | | - * GNU General Public License for more details. |
---|
17 | | - * |
---|
18 | | - * You should have received a copy of the GNU General Public License |
---|
19 | | - * along with this program; if not, write to the Free Software |
---|
20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
21 | | - * |
---|
22 | 7 | */ |
---|
23 | 8 | |
---|
24 | 9 | #include <linux/kernel.h> |
---|
.. | .. |
---|
28 | 13 | #include <linux/module.h> |
---|
29 | 14 | #include <linux/acpi.h> |
---|
30 | 15 | #include <linux/of.h> |
---|
| 16 | +#include <linux/of_irq.h> |
---|
31 | 17 | #include <linux/property.h> |
---|
32 | 18 | #include <linux/platform_data/x86/apple.h> |
---|
33 | 19 | #include <linux/platform_device.h> |
---|
| 20 | +#include <linux/regulator/consumer.h> |
---|
34 | 21 | #include <linux/clk.h> |
---|
35 | 22 | #include <linux/gpio/consumer.h> |
---|
36 | 23 | #include <linux/tty.h> |
---|
.. | .. |
---|
59 | 46 | |
---|
60 | 47 | #define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */ |
---|
61 | 48 | |
---|
| 49 | +#define BCM_NUM_SUPPLIES 2 |
---|
| 50 | + |
---|
| 51 | +/** |
---|
| 52 | + * struct bcm_device_data - device specific data |
---|
| 53 | + * @no_early_set_baudrate: Disallow set baudrate before driver setup() |
---|
| 54 | + */ |
---|
| 55 | +struct bcm_device_data { |
---|
| 56 | + bool no_early_set_baudrate; |
---|
| 57 | + bool drive_rts_on_open; |
---|
| 58 | +}; |
---|
| 59 | + |
---|
62 | 60 | /** |
---|
63 | 61 | * struct bcm_device - device driver resources |
---|
64 | 62 | * @serdev_hu: HCI UART controller struct |
---|
.. | .. |
---|
77 | 75 | * @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power") |
---|
78 | 76 | * @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up") |
---|
79 | 77 | * @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down") |
---|
80 | | - * @clk: clock used by Bluetooth device |
---|
81 | | - * @clk_enabled: whether @clk is prepared and enabled |
---|
| 78 | + * @txco_clk: external reference frequency clock used by Bluetooth device |
---|
| 79 | + * @lpo_clk: external LPO clock used by Bluetooth device |
---|
| 80 | + * @supplies: VBAT and VDDIO supplies used by Bluetooth device |
---|
| 81 | + * @res_enabled: whether clocks and supplies are prepared and enabled |
---|
82 | 82 | * @init_speed: default baudrate of Bluetooth device; |
---|
83 | 83 | * the host UART is initially set to this baudrate so that |
---|
84 | 84 | * it can configure the Bluetooth device for @oper_speed |
---|
.. | .. |
---|
89 | 89 | * @hu: pointer to HCI UART controller struct, |
---|
90 | 90 | * used to disable flow control during runtime suspend and system sleep |
---|
91 | 91 | * @is_suspended: whether flow control is currently disabled |
---|
| 92 | + * @no_early_set_baudrate: don't set_baudrate before setup() |
---|
92 | 93 | */ |
---|
93 | 94 | struct bcm_device { |
---|
94 | 95 | /* Must be the first member, hci_serdev.c expects this. */ |
---|
.. | .. |
---|
108 | 109 | int gpio_int_idx; |
---|
109 | 110 | #endif |
---|
110 | 111 | |
---|
111 | | - struct clk *clk; |
---|
112 | | - bool clk_enabled; |
---|
| 112 | + struct clk *txco_clk; |
---|
| 113 | + struct clk *lpo_clk; |
---|
| 114 | + struct regulator_bulk_data supplies[BCM_NUM_SUPPLIES]; |
---|
| 115 | + bool res_enabled; |
---|
113 | 116 | |
---|
114 | 117 | u32 init_speed; |
---|
115 | 118 | u32 oper_speed; |
---|
.. | .. |
---|
121 | 124 | struct hci_uart *hu; |
---|
122 | 125 | bool is_suspended; |
---|
123 | 126 | #endif |
---|
| 127 | + bool no_early_set_baudrate; |
---|
| 128 | + bool drive_rts_on_open; |
---|
| 129 | + u8 pcm_int_params[5]; |
---|
124 | 130 | }; |
---|
125 | 131 | |
---|
126 | 132 | /* generic bcm uart resources */ |
---|
.. | .. |
---|
221 | 227 | { |
---|
222 | 228 | int err; |
---|
223 | 229 | |
---|
224 | | - if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) { |
---|
225 | | - err = clk_prepare_enable(dev->clk); |
---|
| 230 | + if (powered && !dev->res_enabled) { |
---|
| 231 | + /* Intel Macs use bcm_apple_get_resources() and don't |
---|
| 232 | + * have regulator supplies configured. |
---|
| 233 | + */ |
---|
| 234 | + if (dev->supplies[0].supply) { |
---|
| 235 | + err = regulator_bulk_enable(BCM_NUM_SUPPLIES, |
---|
| 236 | + dev->supplies); |
---|
| 237 | + if (err) |
---|
| 238 | + return err; |
---|
| 239 | + } |
---|
| 240 | + |
---|
| 241 | + /* LPO clock needs to be 32.768 kHz */ |
---|
| 242 | + err = clk_set_rate(dev->lpo_clk, 32768); |
---|
| 243 | + if (err) { |
---|
| 244 | + dev_err(dev->dev, "Could not set LPO clock rate\n"); |
---|
| 245 | + goto err_regulator_disable; |
---|
| 246 | + } |
---|
| 247 | + |
---|
| 248 | + err = clk_prepare_enable(dev->lpo_clk); |
---|
226 | 249 | if (err) |
---|
227 | | - return err; |
---|
| 250 | + goto err_regulator_disable; |
---|
| 251 | + |
---|
| 252 | + err = clk_prepare_enable(dev->txco_clk); |
---|
| 253 | + if (err) |
---|
| 254 | + goto err_lpo_clk_disable; |
---|
228 | 255 | } |
---|
229 | 256 | |
---|
230 | 257 | err = dev->set_shutdown(dev, powered); |
---|
231 | 258 | if (err) |
---|
232 | | - goto err_clk_disable; |
---|
| 259 | + goto err_txco_clk_disable; |
---|
233 | 260 | |
---|
234 | 261 | err = dev->set_device_wakeup(dev, powered); |
---|
235 | 262 | if (err) |
---|
236 | 263 | goto err_revert_shutdown; |
---|
237 | 264 | |
---|
238 | | - if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled) |
---|
239 | | - clk_disable_unprepare(dev->clk); |
---|
| 265 | + if (!powered && dev->res_enabled) { |
---|
| 266 | + clk_disable_unprepare(dev->txco_clk); |
---|
| 267 | + clk_disable_unprepare(dev->lpo_clk); |
---|
240 | 268 | |
---|
241 | | - dev->clk_enabled = powered; |
---|
| 269 | + /* Intel Macs use bcm_apple_get_resources() and don't |
---|
| 270 | + * have regulator supplies configured. |
---|
| 271 | + */ |
---|
| 272 | + if (dev->supplies[0].supply) |
---|
| 273 | + regulator_bulk_disable(BCM_NUM_SUPPLIES, |
---|
| 274 | + dev->supplies); |
---|
| 275 | + } |
---|
| 276 | + |
---|
| 277 | + /* wait for device to power on and come out of reset */ |
---|
| 278 | + usleep_range(100000, 120000); |
---|
| 279 | + |
---|
| 280 | + dev->res_enabled = powered; |
---|
242 | 281 | |
---|
243 | 282 | return 0; |
---|
244 | 283 | |
---|
245 | 284 | err_revert_shutdown: |
---|
246 | 285 | dev->set_shutdown(dev, !powered); |
---|
247 | | -err_clk_disable: |
---|
248 | | - if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) |
---|
249 | | - clk_disable_unprepare(dev->clk); |
---|
| 286 | +err_txco_clk_disable: |
---|
| 287 | + if (powered && !dev->res_enabled) |
---|
| 288 | + clk_disable_unprepare(dev->txco_clk); |
---|
| 289 | +err_lpo_clk_disable: |
---|
| 290 | + if (powered && !dev->res_enabled) |
---|
| 291 | + clk_disable_unprepare(dev->lpo_clk); |
---|
| 292 | +err_regulator_disable: |
---|
| 293 | + if (powered && !dev->res_enabled) |
---|
| 294 | + regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies); |
---|
250 | 295 | return err; |
---|
251 | 296 | } |
---|
252 | 297 | |
---|
.. | .. |
---|
417 | 462 | |
---|
418 | 463 | out: |
---|
419 | 464 | if (bcm->dev) { |
---|
| 465 | + if (bcm->dev->drive_rts_on_open) |
---|
| 466 | + hci_uart_set_flow_control(hu, true); |
---|
| 467 | + |
---|
420 | 468 | hu->init_speed = bcm->dev->init_speed; |
---|
421 | | - hu->oper_speed = bcm->dev->oper_speed; |
---|
| 469 | + |
---|
| 470 | + /* If oper_speed is set, ldisc/serdev will set the baudrate |
---|
| 471 | + * before calling setup() |
---|
| 472 | + */ |
---|
| 473 | + if (!bcm->dev->no_early_set_baudrate) |
---|
| 474 | + hu->oper_speed = bcm->dev->oper_speed; |
---|
| 475 | + |
---|
422 | 476 | err = bcm_gpio_set_power(bcm->dev, true); |
---|
| 477 | + |
---|
| 478 | + if (bcm->dev->drive_rts_on_open) |
---|
| 479 | + hci_uart_set_flow_control(hu, false); |
---|
| 480 | + |
---|
423 | 481 | if (err) |
---|
424 | 482 | goto err_unset_hu; |
---|
425 | 483 | } |
---|
.. | .. |
---|
495 | 553 | static int bcm_setup(struct hci_uart *hu) |
---|
496 | 554 | { |
---|
497 | 555 | struct bcm_data *bcm = hu->priv; |
---|
498 | | - char fw_name[64]; |
---|
499 | | - const struct firmware *fw; |
---|
| 556 | + bool fw_load_done = false; |
---|
500 | 557 | unsigned int speed; |
---|
501 | 558 | int err; |
---|
502 | 559 | |
---|
.. | .. |
---|
505 | 562 | hu->hdev->set_diag = bcm_set_diag; |
---|
506 | 563 | hu->hdev->set_bdaddr = btbcm_set_bdaddr; |
---|
507 | 564 | |
---|
508 | | - err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name), false); |
---|
| 565 | + err = btbcm_initialize(hu->hdev, &fw_load_done); |
---|
509 | 566 | if (err) |
---|
510 | 567 | return err; |
---|
511 | 568 | |
---|
512 | | - err = request_firmware(&fw, fw_name, &hu->hdev->dev); |
---|
513 | | - if (err < 0) { |
---|
514 | | - bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name); |
---|
| 569 | + if (!fw_load_done) |
---|
515 | 570 | return 0; |
---|
516 | | - } |
---|
517 | | - |
---|
518 | | - err = btbcm_patchram(hu->hdev, fw); |
---|
519 | | - if (err) { |
---|
520 | | - bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err); |
---|
521 | | - goto finalize; |
---|
522 | | - } |
---|
523 | 571 | |
---|
524 | 572 | /* Init speed if any */ |
---|
525 | 573 | if (hu->init_speed) |
---|
.. | .. |
---|
535 | 583 | /* Operational speed if any */ |
---|
536 | 584 | if (hu->oper_speed) |
---|
537 | 585 | speed = hu->oper_speed; |
---|
| 586 | + else if (bcm->dev && bcm->dev->oper_speed) |
---|
| 587 | + speed = bcm->dev->oper_speed; |
---|
538 | 588 | else if (hu->proto->oper_speed) |
---|
539 | 589 | speed = hu->proto->oper_speed; |
---|
540 | 590 | else |
---|
.. | .. |
---|
546 | 596 | host_set_baudrate(hu, speed); |
---|
547 | 597 | } |
---|
548 | 598 | |
---|
549 | | -finalize: |
---|
550 | | - release_firmware(fw); |
---|
| 599 | + /* PCM parameters if provided */ |
---|
| 600 | + if (bcm->dev && bcm->dev->pcm_int_params[0] != 0xff) { |
---|
| 601 | + struct bcm_set_pcm_int_params params; |
---|
551 | 602 | |
---|
552 | | - err = btbcm_finalize(hu->hdev); |
---|
| 603 | + btbcm_read_pcm_int_params(hu->hdev, ¶ms); |
---|
| 604 | + |
---|
| 605 | + memcpy(¶ms, bcm->dev->pcm_int_params, 5); |
---|
| 606 | + btbcm_write_pcm_int_params(hu->hdev, ¶ms); |
---|
| 607 | + } |
---|
| 608 | + |
---|
| 609 | + err = btbcm_finalize(hu->hdev, &fw_load_done); |
---|
553 | 610 | if (err) |
---|
554 | 611 | return err; |
---|
| 612 | + |
---|
| 613 | + /* Some devices ship with the controller default address. |
---|
| 614 | + * Allow the bootloader to set a valid address through the |
---|
| 615 | + * device tree. |
---|
| 616 | + */ |
---|
| 617 | + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); |
---|
555 | 618 | |
---|
556 | 619 | if (!bcm_request_irq(bcm)) |
---|
557 | 620 | err = bcm_setup_sleep(hu); |
---|
.. | .. |
---|
591 | 654 | { H4_RECV_ACL, .recv = hci_recv_frame }, |
---|
592 | 655 | { H4_RECV_SCO, .recv = hci_recv_frame }, |
---|
593 | 656 | { H4_RECV_EVENT, .recv = hci_recv_frame }, |
---|
| 657 | + { H4_RECV_ISO, .recv = hci_recv_frame }, |
---|
594 | 658 | { BCM_RECV_LM_DIAG, .recv = hci_recv_diag }, |
---|
595 | 659 | { BCM_RECV_NULL, .recv = hci_recv_diag }, |
---|
596 | 660 | { BCM_RECV_TYPE49, .recv = hci_recv_diag }, |
---|
.. | .. |
---|
796 | 860 | } |
---|
797 | 861 | #endif |
---|
798 | 862 | |
---|
| 863 | +/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */ |
---|
| 864 | +static const struct dmi_system_id bcm_broken_irq_dmi_table[] = { |
---|
| 865 | + { |
---|
| 866 | + .ident = "Meegopad T08", |
---|
| 867 | + .matches = { |
---|
| 868 | + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, |
---|
| 869 | + "To be filled by OEM."), |
---|
| 870 | + DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"), |
---|
| 871 | + DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"), |
---|
| 872 | + }, |
---|
| 873 | + }, |
---|
| 874 | + { } |
---|
| 875 | +}; |
---|
| 876 | + |
---|
| 877 | +#ifdef CONFIG_ACPI |
---|
799 | 878 | static const struct acpi_gpio_params first_gpio = { 0, 0, false }; |
---|
800 | 879 | static const struct acpi_gpio_params second_gpio = { 1, 0, false }; |
---|
801 | 880 | static const struct acpi_gpio_params third_gpio = { 2, 0, false }; |
---|
.. | .. |
---|
814 | 893 | { }, |
---|
815 | 894 | }; |
---|
816 | 895 | |
---|
817 | | -/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */ |
---|
818 | | -static const struct dmi_system_id bcm_broken_irq_dmi_table[] = { |
---|
819 | | - { |
---|
820 | | - .ident = "Meegopad T08", |
---|
821 | | - .matches = { |
---|
822 | | - DMI_EXACT_MATCH(DMI_BOARD_VENDOR, |
---|
823 | | - "To be filled by OEM."), |
---|
824 | | - DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"), |
---|
825 | | - DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"), |
---|
826 | | - }, |
---|
827 | | - }, |
---|
828 | | - { } |
---|
829 | | -}; |
---|
830 | | - |
---|
831 | | -#ifdef CONFIG_ACPI |
---|
832 | 896 | static int bcm_resource(struct acpi_resource *ares, void *data) |
---|
833 | 897 | { |
---|
834 | 898 | struct bcm_device *dev = data; |
---|
.. | .. |
---|
924 | 988 | return 0; |
---|
925 | 989 | } |
---|
926 | 990 | |
---|
| 991 | +/* Try a bunch of names for TXCO */ |
---|
| 992 | +static struct clk *bcm_get_txco(struct device *dev) |
---|
| 993 | +{ |
---|
| 994 | + struct clk *clk; |
---|
| 995 | + |
---|
| 996 | + /* New explicit name */ |
---|
| 997 | + clk = devm_clk_get(dev, "txco"); |
---|
| 998 | + if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) |
---|
| 999 | + return clk; |
---|
| 1000 | + |
---|
| 1001 | + /* Deprecated name */ |
---|
| 1002 | + clk = devm_clk_get(dev, "extclk"); |
---|
| 1003 | + if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) |
---|
| 1004 | + return clk; |
---|
| 1005 | + |
---|
| 1006 | + /* Original code used no name at all */ |
---|
| 1007 | + return devm_clk_get(dev, NULL); |
---|
| 1008 | +} |
---|
| 1009 | + |
---|
927 | 1010 | static int bcm_get_resources(struct bcm_device *dev) |
---|
928 | 1011 | { |
---|
929 | 1012 | const struct dmi_system_id *dmi_id; |
---|
| 1013 | + int err; |
---|
930 | 1014 | |
---|
931 | 1015 | dev->name = dev_name(dev->dev); |
---|
932 | 1016 | |
---|
933 | 1017 | if (x86_apple_machine && !bcm_apple_get_resources(dev)) |
---|
934 | 1018 | return 0; |
---|
935 | 1019 | |
---|
936 | | - dev->clk = devm_clk_get(dev->dev, NULL); |
---|
| 1020 | + dev->txco_clk = bcm_get_txco(dev->dev); |
---|
937 | 1021 | |
---|
938 | 1022 | /* Handle deferred probing */ |
---|
939 | | - if (dev->clk == ERR_PTR(-EPROBE_DEFER)) |
---|
940 | | - return PTR_ERR(dev->clk); |
---|
| 1023 | + if (dev->txco_clk == ERR_PTR(-EPROBE_DEFER)) |
---|
| 1024 | + return PTR_ERR(dev->txco_clk); |
---|
| 1025 | + |
---|
| 1026 | + /* Ignore all other errors as before */ |
---|
| 1027 | + if (IS_ERR(dev->txco_clk)) |
---|
| 1028 | + dev->txco_clk = NULL; |
---|
| 1029 | + |
---|
| 1030 | + dev->lpo_clk = devm_clk_get(dev->dev, "lpo"); |
---|
| 1031 | + if (dev->lpo_clk == ERR_PTR(-EPROBE_DEFER)) |
---|
| 1032 | + return PTR_ERR(dev->lpo_clk); |
---|
| 1033 | + |
---|
| 1034 | + if (IS_ERR(dev->lpo_clk)) |
---|
| 1035 | + dev->lpo_clk = NULL; |
---|
| 1036 | + |
---|
| 1037 | + /* Check if we accidentally fetched the lpo clock twice */ |
---|
| 1038 | + if (dev->lpo_clk && clk_is_match(dev->lpo_clk, dev->txco_clk)) { |
---|
| 1039 | + devm_clk_put(dev->dev, dev->txco_clk); |
---|
| 1040 | + dev->txco_clk = NULL; |
---|
| 1041 | + } |
---|
941 | 1042 | |
---|
942 | 1043 | dev->device_wakeup = devm_gpiod_get_optional(dev->dev, "device-wakeup", |
---|
943 | 1044 | GPIOD_OUT_LOW); |
---|
.. | .. |
---|
951 | 1052 | |
---|
952 | 1053 | dev->set_device_wakeup = bcm_gpio_set_device_wakeup; |
---|
953 | 1054 | dev->set_shutdown = bcm_gpio_set_shutdown; |
---|
| 1055 | + |
---|
| 1056 | + dev->supplies[0].supply = "vbat"; |
---|
| 1057 | + dev->supplies[1].supply = "vddio"; |
---|
| 1058 | + err = devm_regulator_bulk_get(dev->dev, BCM_NUM_SUPPLIES, |
---|
| 1059 | + dev->supplies); |
---|
| 1060 | + if (err) |
---|
| 1061 | + return err; |
---|
954 | 1062 | |
---|
955 | 1063 | /* IRQ can be declared in ACPI table as Interrupt or GpioInt */ |
---|
956 | 1064 | if (dev->irq <= 0) { |
---|
.. | .. |
---|
1039 | 1147 | static int bcm_of_probe(struct bcm_device *bdev) |
---|
1040 | 1148 | { |
---|
1041 | 1149 | device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed); |
---|
| 1150 | + device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params", |
---|
| 1151 | + bdev->pcm_int_params, 5); |
---|
| 1152 | + bdev->irq = of_irq_get_byname(bdev->dev->of_node, "host-wakeup"); |
---|
| 1153 | + bdev->irq_active_low = irq_get_trigger_type(bdev->irq) |
---|
| 1154 | + & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW); |
---|
1042 | 1155 | return 0; |
---|
1043 | 1156 | } |
---|
1044 | 1157 | |
---|
.. | .. |
---|
1058 | 1171 | return ret; |
---|
1059 | 1172 | |
---|
1060 | 1173 | dev->irq = ret; |
---|
| 1174 | + |
---|
| 1175 | + /* Initialize routing field to an unused value */ |
---|
| 1176 | + dev->pcm_int_params[0] = 0xff; |
---|
1061 | 1177 | |
---|
1062 | 1178 | if (has_acpi_companion(&pdev->dev)) { |
---|
1063 | 1179 | ret = bcm_acpi_probe(dev); |
---|
.. | .. |
---|
1305 | 1421 | static int bcm_serdev_probe(struct serdev_device *serdev) |
---|
1306 | 1422 | { |
---|
1307 | 1423 | struct bcm_device *bcmdev; |
---|
| 1424 | + const struct bcm_device_data *data; |
---|
1308 | 1425 | int err; |
---|
1309 | 1426 | |
---|
1310 | 1427 | bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL); |
---|
.. | .. |
---|
1317 | 1434 | #endif |
---|
1318 | 1435 | bcmdev->serdev_hu.serdev = serdev; |
---|
1319 | 1436 | serdev_device_set_drvdata(serdev, bcmdev); |
---|
| 1437 | + |
---|
| 1438 | + /* Initialize routing field to an unused value */ |
---|
| 1439 | + bcmdev->pcm_int_params[0] = 0xff; |
---|
1320 | 1440 | |
---|
1321 | 1441 | if (has_acpi_companion(&serdev->dev)) |
---|
1322 | 1442 | err = bcm_acpi_probe(bcmdev); |
---|
.. | .. |
---|
1339 | 1459 | if (err) |
---|
1340 | 1460 | dev_err(&serdev->dev, "Failed to power down\n"); |
---|
1341 | 1461 | |
---|
| 1462 | + data = device_get_match_data(bcmdev->dev); |
---|
| 1463 | + if (data) { |
---|
| 1464 | + bcmdev->no_early_set_baudrate = data->no_early_set_baudrate; |
---|
| 1465 | + bcmdev->drive_rts_on_open = data->drive_rts_on_open; |
---|
| 1466 | + } |
---|
| 1467 | + |
---|
1342 | 1468 | return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto); |
---|
1343 | 1469 | } |
---|
1344 | 1470 | |
---|
.. | .. |
---|
1350 | 1476 | } |
---|
1351 | 1477 | |
---|
1352 | 1478 | #ifdef CONFIG_OF |
---|
| 1479 | +static struct bcm_device_data bcm4354_device_data = { |
---|
| 1480 | + .no_early_set_baudrate = true, |
---|
| 1481 | +}; |
---|
| 1482 | + |
---|
| 1483 | +static struct bcm_device_data bcm43438_device_data = { |
---|
| 1484 | + .drive_rts_on_open = true, |
---|
| 1485 | +}; |
---|
| 1486 | + |
---|
1353 | 1487 | static const struct of_device_id bcm_bluetooth_of_match[] = { |
---|
1354 | | - { .compatible = "brcm,bcm43438-bt" }, |
---|
| 1488 | + { .compatible = "brcm,bcm20702a1" }, |
---|
| 1489 | + { .compatible = "brcm,bcm4329-bt" }, |
---|
| 1490 | + { .compatible = "brcm,bcm4345c5" }, |
---|
| 1491 | + { .compatible = "brcm,bcm4330-bt" }, |
---|
| 1492 | + { .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data }, |
---|
| 1493 | + { .compatible = "brcm,bcm4349-bt", .data = &bcm43438_device_data }, |
---|
| 1494 | + { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data }, |
---|
| 1495 | + { .compatible = "brcm,bcm4335a0" }, |
---|
| 1496 | + { .compatible = "infineon,cyw55572-bt" }, |
---|
1355 | 1497 | { }, |
---|
1356 | 1498 | }; |
---|
1357 | 1499 | MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match); |
---|