Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: hci_mrvl: Add serdev support for 88W8997

Add serdev support for the 88W8997 from NXP (previously Marvell). It
includes support for changing the baud rate. The command to change the
baud rate is taken from the user manual UM11483 Rev. 9 in section 7
(Bring-up of Bluetooth interfaces) from NXP.

Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Stefan Eichenberger and committed by
Luiz Augusto von Dentz
a860c50f 069690a9

+79 -7
+79 -7
drivers/bluetooth/hci_mrvl.c
··· 27 27 #define MRVL_ACK 0x5A 28 28 #define MRVL_NAK 0xBF 29 29 #define MRVL_RAW_DATA 0x1F 30 + #define MRVL_SET_BAUDRATE 0xFC09 30 31 31 32 enum { 32 33 STATE_CHIP_VER_PENDING, 33 34 STATE_FW_REQ_PENDING, 35 + STATE_FW_LOADED, 34 36 }; 35 37 36 38 struct mrvl_data { ··· 256 254 if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) 257 255 return -EUNATCH; 258 256 257 + /* We might receive some noise when there is no firmware loaded. Therefore, 258 + * we drop data if the firmware is not loaded yet and if there is no fw load 259 + * request pending. 260 + */ 261 + if (!test_bit(STATE_FW_REQ_PENDING, &mrvl->flags) && 262 + !test_bit(STATE_FW_LOADED, &mrvl->flags)) 263 + return count; 264 + 259 265 mrvl->rx_skb = h4_recv_buf(hu->hdev, mrvl->rx_skb, data, count, 260 266 mrvl_recv_pkts, 261 267 ARRAY_SIZE(mrvl_recv_pkts)); ··· 364 354 static int mrvl_setup(struct hci_uart *hu) 365 355 { 366 356 int err; 357 + struct mrvl_data *mrvl = hu->priv; 367 358 368 359 hci_uart_set_flow_control(hu, true); 369 360 ··· 378 367 hci_uart_wait_until_sent(hu); 379 368 380 369 if (hu->serdev) 381 - serdev_device_set_baudrate(hu->serdev, 3000000); 370 + serdev_device_set_baudrate(hu->serdev, hu->oper_speed); 382 371 else 383 - hci_uart_set_baudrate(hu, 3000000); 372 + hci_uart_set_baudrate(hu, hu->oper_speed); 384 373 385 374 hci_uart_set_flow_control(hu, false); 386 375 ··· 388 377 if (err) 389 378 return err; 390 379 380 + set_bit(STATE_FW_LOADED, &mrvl->flags); 381 + 391 382 return 0; 392 383 } 393 384 394 - static const struct hci_uart_proto mrvl_proto = { 385 + static int mrvl_set_baudrate(struct hci_uart *hu, unsigned int speed) 386 + { 387 + int err; 388 + struct mrvl_data *mrvl = hu->priv; 389 + __le32 speed_le = cpu_to_le32(speed); 390 + 391 + /* The firmware might be loaded by the Wifi driver over SDIO. We wait 392 + * up to 10s for the CTS to go up. Afterward, we know that the firmware 393 + * is ready. 394 + */ 395 + err = serdev_device_wait_for_cts(hu->serdev, true, 10000); 396 + if (err) { 397 + bt_dev_err(hu->hdev, "Wait for CTS failed with %d\n", err); 398 + return err; 399 + } 400 + 401 + set_bit(STATE_FW_LOADED, &mrvl->flags); 402 + 403 + err = __hci_cmd_sync_status(hu->hdev, MRVL_SET_BAUDRATE, 404 + sizeof(speed_le), &speed_le, 405 + HCI_INIT_TIMEOUT); 406 + if (err) { 407 + bt_dev_err(hu->hdev, "send command failed: %d", err); 408 + return err; 409 + } 410 + 411 + serdev_device_set_baudrate(hu->serdev, speed); 412 + 413 + /* We forcefully have to send a command to the bluetooth module so that 414 + * the driver detects it after a baudrate change. This is foreseen by 415 + * hci_serdev by setting HCI_UART_VND_DETECT which then causes a dummy 416 + * local version read. 417 + */ 418 + set_bit(HCI_UART_VND_DETECT, &hu->hdev_flags); 419 + 420 + return 0; 421 + } 422 + 423 + static const struct hci_uart_proto mrvl_proto_8897 = { 395 424 .id = HCI_UART_MRVL, 396 425 .name = "Marvell", 397 426 .init_speed = 115200, 427 + .oper_speed = 3000000, 398 428 .open = mrvl_open, 399 429 .close = mrvl_close, 400 430 .flush = mrvl_flush, ··· 445 393 .dequeue = mrvl_dequeue, 446 394 }; 447 395 396 + static const struct hci_uart_proto mrvl_proto_8997 = { 397 + .id = HCI_UART_MRVL, 398 + .name = "Marvell 8997", 399 + .init_speed = 115200, 400 + .oper_speed = 3000000, 401 + .open = mrvl_open, 402 + .close = mrvl_close, 403 + .flush = mrvl_flush, 404 + .set_baudrate = mrvl_set_baudrate, 405 + .recv = mrvl_recv, 406 + .enqueue = mrvl_enqueue, 407 + .dequeue = mrvl_dequeue, 408 + }; 409 + 448 410 static int mrvl_serdev_probe(struct serdev_device *serdev) 449 411 { 450 412 struct mrvl_serdev *mrvldev; 413 + const struct hci_uart_proto *mrvl_proto = device_get_match_data(&serdev->dev); 451 414 452 415 mrvldev = devm_kzalloc(&serdev->dev, sizeof(*mrvldev), GFP_KERNEL); 453 416 if (!mrvldev) 454 417 return -ENOMEM; 455 418 419 + mrvldev->hu.oper_speed = mrvl_proto->oper_speed; 420 + if (mrvl_proto->set_baudrate) 421 + of_property_read_u32(serdev->dev.of_node, "max-speed", &mrvldev->hu.oper_speed); 422 + 456 423 mrvldev->hu.serdev = serdev; 457 424 serdev_device_set_drvdata(serdev, mrvldev); 458 425 459 - return hci_uart_register_device(&mrvldev->hu, &mrvl_proto); 426 + return hci_uart_register_device(&mrvldev->hu, mrvl_proto); 460 427 } 461 428 462 429 static void mrvl_serdev_remove(struct serdev_device *serdev) ··· 486 415 } 487 416 488 417 static const struct of_device_id __maybe_unused mrvl_bluetooth_of_match[] = { 489 - { .compatible = "mrvl,88w8897" }, 418 + { .compatible = "mrvl,88w8897", .data = &mrvl_proto_8897}, 419 + { .compatible = "mrvl,88w8997", .data = &mrvl_proto_8997}, 490 420 { }, 491 421 }; 492 422 MODULE_DEVICE_TABLE(of, mrvl_bluetooth_of_match); ··· 505 433 { 506 434 serdev_device_driver_register(&mrvl_serdev_driver); 507 435 508 - return hci_uart_register_proto(&mrvl_proto); 436 + return hci_uart_register_proto(&mrvl_proto_8897); 509 437 } 510 438 511 439 int __exit mrvl_deinit(void) 512 440 { 513 441 serdev_device_driver_unregister(&mrvl_serdev_driver); 514 442 515 - return hci_uart_unregister_proto(&mrvl_proto); 443 + return hci_uart_unregister_proto(&mrvl_proto_8897); 516 444 }