sunxi: board: add a config option to fixup a Bluetooth address
authorAndre Heider <a.heider@gmail.com>
Fri, 1 Oct 2021 18:29:00 +0000 (19:29 +0100)
committerAndre Przywara <andre.przywara@arm.com>
Mon, 11 Jan 2021 23:19:34 +0000 (23:19 +0000)
Some Bluetooth controllers, like the BCM4345C5 of the Orange Pi 3,
ship with the controller default address.

Add a config option to fix it up so it can function properly.

Signed-off-by: Andre Heider <a.heider@gmail.com>
Tested-by: Ondrej Jirman <megous@megous.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
[rebased]
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
arch/arm/mach-sunxi/Kconfig
board/sunxi/board.c

index 49ef217..11e6445 100644 (file)
@@ -1016,4 +1016,15 @@ config PINEPHONE_DT_SELECTION
          Enable this option to automatically select the device tree for the
          correct PinePhone hardware revision during boot.
 
+config BLUETOOTH_DT_DEVICE_FIXUP
+       string "Fixup the Bluetooth controller address"
+       default ""
+       help
+         This option specifies the DT compatible name of the Bluetooth
+         controller for which to set the "local-bd-address" property.
+         Set this option if your device ships with the Bluetooth controller
+         default address.
+         The used address is "bdaddr" if set, and "ethaddr" with the LSB
+         flipped elsewise.
+
 endif
index b7f527a..4f05895 100644 (file)
@@ -39,6 +39,7 @@
 #include <u-boot/crc.h>
 #include <env_internal.h>
 #include <linux/libfdt.h>
+#include <fdt_support.h>
 #include <nand.h>
 #include <net.h>
 #include <spl.h>
@@ -913,6 +914,38 @@ int board_late_init(void)
        return 0;
 }
 
+static void bluetooth_dt_fixup(void *blob)
+{
+       /* Some devices ship with a Bluetooth controller default address.
+        * Set a valid address through the device tree.
+        */
+       uchar tmp[ETH_ALEN], bdaddr[ETH_ALEN];
+       unsigned int sid[4];
+       int i;
+
+       if (!CONFIG_BLUETOOTH_DT_DEVICE_FIXUP[0])
+               return;
+
+       if (eth_env_get_enetaddr("bdaddr", tmp)) {
+               /* Convert between the binary formats of the corresponding stacks */
+               for (i = 0; i < ETH_ALEN; ++i)
+                       bdaddr[i] = tmp[ETH_ALEN - i - 1];
+       } else {
+               if (!get_unique_sid(sid))
+                       return;
+
+               bdaddr[0] = ((sid[3] >>  0) & 0xff) ^ 1;
+               bdaddr[1] = (sid[3] >>  8) & 0xff;
+               bdaddr[2] = (sid[3] >> 16) & 0xff;
+               bdaddr[3] = (sid[3] >> 24) & 0xff;
+               bdaddr[4] = (sid[0] >>  0) & 0xff;
+               bdaddr[5] = 0x02;
+       }
+
+       do_fixup_by_compat(blob, CONFIG_BLUETOOTH_DT_DEVICE_FIXUP,
+                          "local-bd-address", bdaddr, ETH_ALEN, 1);
+}
+
 int ft_board_setup(void *blob, struct bd_info *bd)
 {
        int __maybe_unused r;
@@ -923,6 +956,8 @@ int ft_board_setup(void *blob, struct bd_info *bd)
         */
        setup_environment(blob);
 
+       bluetooth_dt_fixup(blob);
+
 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
        r = sunxi_simplefb_setup(blob);
        if (r)