| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2016, Linaro Ltd. |
|---|
| 3 | 4 | * Copyright (c) 2015, Sony Mobile Communications Inc. |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 and |
|---|
| 7 | | - * only version 2 as published by the Free Software Foundation. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | 5 | */ |
|---|
| 14 | 6 | |
|---|
| 15 | 7 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 28 | 20 | struct btqcomsmd { |
|---|
| 29 | 21 | struct hci_dev *hdev; |
|---|
| 30 | 22 | |
|---|
| 31 | | - bdaddr_t bdaddr; |
|---|
| 32 | 23 | struct rpmsg_endpoint *acl_channel; |
|---|
| 33 | 24 | struct rpmsg_endpoint *cmd_channel; |
|---|
| 34 | 25 | }; |
|---|
| .. | .. |
|---|
| 116 | 107 | |
|---|
| 117 | 108 | static int btqcomsmd_setup(struct hci_dev *hdev) |
|---|
| 118 | 109 | { |
|---|
| 119 | | - struct btqcomsmd *btq = hci_get_drvdata(hdev); |
|---|
| 120 | 110 | struct sk_buff *skb; |
|---|
| 121 | | - int err; |
|---|
| 122 | 111 | |
|---|
| 123 | 112 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); |
|---|
| 124 | 113 | if (IS_ERR(skb)) |
|---|
| 125 | 114 | return PTR_ERR(skb); |
|---|
| 126 | 115 | kfree_skb(skb); |
|---|
| 127 | 116 | |
|---|
| 128 | | - /* Devices do not have persistent storage for BD address. If no |
|---|
| 129 | | - * BD address has been retrieved during probe, mark the device |
|---|
| 130 | | - * as having an invalid BD address. |
|---|
| 117 | + /* Devices do not have persistent storage for BD address. Retrieve |
|---|
| 118 | + * it from the firmware node property. |
|---|
| 131 | 119 | */ |
|---|
| 132 | | - if (!bacmp(&btq->bdaddr, BDADDR_ANY)) { |
|---|
| 133 | | - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); |
|---|
| 134 | | - return 0; |
|---|
| 135 | | - } |
|---|
| 120 | + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); |
|---|
| 136 | 121 | |
|---|
| 137 | | - /* When setting a configured BD address fails, mark the device |
|---|
| 138 | | - * as having an invalid BD address. |
|---|
| 122 | + return 0; |
|---|
| 123 | +} |
|---|
| 124 | + |
|---|
| 125 | +static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) |
|---|
| 126 | +{ |
|---|
| 127 | + int ret; |
|---|
| 128 | + |
|---|
| 129 | + ret = qca_set_bdaddr_rome(hdev, bdaddr); |
|---|
| 130 | + if (ret) |
|---|
| 131 | + return ret; |
|---|
| 132 | + |
|---|
| 133 | + /* The firmware stops responding for a while after setting the bdaddr, |
|---|
| 134 | + * causing timeouts for subsequent commands. Sleep a bit to avoid this. |
|---|
| 139 | 135 | */ |
|---|
| 140 | | - err = qca_set_bdaddr_rome(hdev, &btq->bdaddr); |
|---|
| 141 | | - if (err) { |
|---|
| 142 | | - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); |
|---|
| 143 | | - return 0; |
|---|
| 144 | | - } |
|---|
| 145 | | - |
|---|
| 136 | + usleep_range(1000, 10000); |
|---|
| 146 | 137 | return 0; |
|---|
| 147 | 138 | } |
|---|
| 148 | 139 | |
|---|
| .. | .. |
|---|
| 171 | 162 | goto destroy_acl_channel; |
|---|
| 172 | 163 | } |
|---|
| 173 | 164 | |
|---|
| 174 | | - /* The local-bd-address property is usually injected by the |
|---|
| 175 | | - * bootloader which has access to the allocated BD address. |
|---|
| 176 | | - */ |
|---|
| 177 | | - if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address", |
|---|
| 178 | | - (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) { |
|---|
| 179 | | - dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree", |
|---|
| 180 | | - &btq->bdaddr); |
|---|
| 181 | | - } |
|---|
| 182 | | - |
|---|
| 183 | 165 | hdev = hci_alloc_dev(); |
|---|
| 184 | 166 | if (!hdev) { |
|---|
| 185 | 167 | ret = -ENOMEM; |
|---|
| .. | .. |
|---|
| 195 | 177 | hdev->close = btqcomsmd_close; |
|---|
| 196 | 178 | hdev->send = btqcomsmd_send; |
|---|
| 197 | 179 | hdev->setup = btqcomsmd_setup; |
|---|
| 198 | | - hdev->set_bdaddr = qca_set_bdaddr_rome; |
|---|
| 180 | + hdev->set_bdaddr = btqcomsmd_set_bdaddr; |
|---|
| 199 | 181 | |
|---|
| 200 | 182 | ret = hci_register_dev(hdev); |
|---|
| 201 | 183 | if (ret < 0) |
|---|