Broadcom bcm4352 added to l4t-23.1

I’m building a custom kernel for my newly purchased Jetson tk1 and I noticed that support for Broadcom dual WiFi/BT bcm4352 was added to the tegra12_android_defconfig. Since I am building for aosp android does this mean this bcm chip is supported?

The module design is based on the bcm4352 and bcm20702 solution.

External Media

I haven’t played with this, but that would be the driver side. There may be other requirements for firmware or user space configuration, but this looks like at least the starting point for making that card work.

Well this is good news for sure! From all the forums and google searching the bcm4352 is a proprietary kernel driver. I’ve got the bcm4352 coming in the mail tomorrow so ill be sure to post some dmesg logs after i test a kernel with support.

Well from building Nvidia github aosp Jetson tk1 (as described here Android L update to Jetson-TK1 - Jetson TK1 - NVIDIA Developer Forums) and Foster tx1 the vendor firmware provided that’s the closest is the bcm43241.

https://drive.google.com/file/d/0B8us3BLI5teObXk5bFJyRUNqRkU/view?usp=docslist_api

And nvram.txt hold board specific info. Here’s a sample from nvidia android source.

#Sample variables file for BCM94324A1 iPA+iLNA FCBGA REF board
devid=0x4374
boardtype=0x5f0
boardrev=0x1110
boardflags=0x201
boardflags2=0x00800000
macaddr=00:90:4c:c5:12:38
sromrev=9
xtalfreq=37400
nocrc=1
ag0=0x2
ag1=0x2
ag2=0xff
ag3=0xff
txchain=0x3
rxchain=0x3
aa2g=3
aa5g=3
ccode=ALL
regrev=0
ledbh0=0xff
ledbh1=0xff
ledbh2=0xff
ledbh3=0xff
leddc=0xffff
pa2gw0a0=0xFFD6
pa2gw1a0=0x1207
pa2gw2a0=0xFF12
pa2gw0a1=0xFFEC
pa2gw1a1=0x1347
pa2gw2a1=0xFF1B
maxp2ga0=66
maxp2ga1=66
maxp5ga0=46
maxp5ga1=46
maxp5gha0=46
maxp5gha1=46
maxp5gla0=46
maxp5gla1=46
pa0itssit=62
pa1itssit=62
antswctl2g=0x9
antswctl5g=0xa
antswitch=0x0
subband5gver=0
pa5gw0a0=0xFFC5
pa5gw1a0=0x10BA
pa5gw2a0=0xFEF2
pa5gw0a1=0xFFBC
pa5gw1a1=0x127A
pa5gw2a1=0xFEE3
pa5glw0a0=0xFFF9
pa5glw1a0=0x101F
pa5glw2a0=0xFF4C
pa5glw0a1=0xFFFD
pa5glw1a1=0x122F
pa5glw2a1=0xFF39
pa5ghw0a0=0xFFCB
pa5ghw1a0=0x0F4F
pa5ghw2a0=0xFF21
pa5ghw0a1=0xFFDB
pa5ghw1a1=0x108C
pa5ghw2a1=0xFF29
extpagain2g=2
extpagain5g=2
pdetrange2g=2
pdetrange5g=2
triso2g=4
triso5g=5
tssipos2g=1
tssipos5g=1
cckbw202gpo=0x1111
cckbw20ul2gpo=0x1111
legofdmbw202gpo=0x22222222
legofdmbw20ul2gpo=0x22222222
mcsbw202gpo=0x44444444
mcsbw20ul2gpo=0x44444444
mcsbw402gpo=0x44444444
mcs32po=0x5555
leg40dup2gpo=0x2
legofdmbw205glpo=0x22220000
legofdmbw20ul5glpo=0x22220000
legofdmbw205gmpo=0x22220000
legofdmbw20ul5gmpo=0x22220000
legofdmbw205ghpo=0x22220000
legofdmbw20ul5ghpo=0x22220000
mcsbw205glpo=0x22200000
mcsbw20ul5glpo=0x22200000
mcsbw405glpo=0x22200000
mcsbw205gmpo=0x22200000
mcsbw20ul5gmpo=0x22200000
mcsbw405gmpo=0x22200000
mcsbw205ghpo=0x22200000
mcsbw20ul5ghpo=0x22200000
mcsbw405ghpo=0x22200000
itt2ga0=0x20
itt5ga0=0x3e
itt2ga1=0x20
itt5ga1=0x3e
tempthresh=120
otpimagesize=232
usbepnum=0x2
muxenab=0x10
noisecaloffset=14
noisecaloffset5g=14
rssicorrnorm_core0=0x2004
rssicorrnorm_core1=0x2004
rssicorrnorm_core0_5g1=0x2203
rssicorrnorm_core0_5g2=0x1f03
rssicorrnorm_core0_5g3=0x1903
rssicorrnorm_core1_5g1=0x2a03
rssicorrnorm_core1_5g2=0x2303
rssicorrnorm_core1_5g3=0x1d03
triso5g_l_c0=5
triso5g_l_c1=5
triso5g_m_c0=5
triso5g_m_c1=5
triso5g_h_c0=5
triso5g_h_c1=5
pa2gw0a0_lo=0xFFFA
pa2gw1a0_lo=0x0766
pa2gw2a0_lo=0xFF7B
pa2gw0a1_lo=0xFFEE
pa2gw1a1_lo=0x07AD
pa2gw2a1_lo=0xFF6E
pa5gw0a0_lo=0xFFF0
pa5gw1a0_lo=0x08D0
pa5gw2a0_lo=0xFF5C
pa5gw0a1_lo=0xFFD4
pa5gw1a1_lo=0x09B0
pa5gw2a1_lo=0xFF3F
pa5glw0a0_lo=0xFFE1
pa5glw1a0_lo=0x0934
pa5glw2a0_lo=0xFF4A
pa5glw0a1_lo=0xFFEA
pa5glw1a1_lo=0x09AD
pa5glw2a1_lo=0xFF4E
pa5ghw0a0_lo=0xFFDD
pa5ghw1a0_lo=0x08DD
pa5ghw2a0_lo=0xFF4D
pa5ghw0a1_lo=0xFFDE
pa5ghw1a1_lo=0x09D1
pa5ghw2a1_lo=0xFF46
disable_spuravoid=1
phycal_tempdelta=30

Looks like the Jetson Pro has the bcm43241:

Wi-Fi 802.11 a/b/g/n, AP; BT 4.0 (AW-AH691A-I5)

http://www.nvidia.com/content/tegra/automotive/pdf/jetson-tk1-brochure-web.pdf

Could anyone here let me know if it is possible to use the kernel source l4t-23.1 for the jetson tk1 even though it was released for the TX1
?

I do not believe R23.1 will work on a TK1. No doubt it could be adapted, but I’m going to guess the effort would be extreme. If the case is that a kernel driver/module is what is needed, then back-porting this individual module from R23.1 to R21.4 would likely be a signifcant but more reasonable effort. So a big question is what would you want to bring to TK1 which is in TX1? This would give a more precise idea of what you would need to do (and how difficult it is).

My ultimate goal would be to back-port the bcm4352 WiFi module support to the tk1 kernel branch. What would be the first steps? I’m comfortable editing code and applying patches so any help on this is greatly appreciated.

That’s a complicated question (and a difficult task, especially since the port is going from a 64-bit architecture to a 32-bit architecture…I wouldn’t recommend it). Back-porting is typically something Santiago does for his Grinch kernels…he’s the expert on this:
[url]https://devtalk.nvidia.com/default/topic/906018/jetson-tk1/-customkernel-the-grinch-21-3-4-for-jetson-tk1-developed/[/url]

In general, there would be an architecture independent directory in the kernel source for that driver (somewhere under “drivers/”). Some Kconfig files would make this available for config setup. One would copy that driver directory branch into the older kernel source, and set up Kconfig.

Firmware would be an additional step for wireless, which has an architecture dependent directory somewhere in the “arch/” subdirectory tree, and would need to be copied into “arm” subdirectory from the “arm64” directory.

There is no telling what would be required to support making the driver compile, as changes from this older kernel to the newer one may make some features used by the driver non-existent when put in the older environment. Basically, the newer infrastructure the module depends upon may require modifying the driver to run on older infrastructure. This could include differences in compilers, and not just code in the driver (especially where arm versus aarch64 is concerned).

The firmware would have to be adjusted for whatever changes are needed in the driver.

To make things more difficult, sometimes there is more than one driver for a device. For example, some wireless devices also have bluetooth…the bluetooth would have its own driver and firmware. If I were you I’d start by learning to back port a simple driver from the same 32-bit ARMv7 driver as close to the near future of the 3.10.40 kernel as possible. Then I would try to just get the driver you are actually working on to compile…but not necessarily be able to load or run. To get further you’d then have to port the firmware. Once the firmware is done, you could work on getting the module to load and then to run.

I’ve been speaking with Barrett from nvidia and he says to try and get a hold of Santyago here in the forum for some help.

In the meantime I’ll work on porting the 4352 to the tk1and post my findings and errors here.

Tried my first compile just copying the bcmdhd directory to the 3.10.40 kernel source and here is my first error:

CC [M]  drivers/net/wireless/bcmdhd/wl_cfgp2p.o
  CC [M]  drivers/net/wireless/bcmdhd/wl_cfg_btcoex.o
  CC [M]  drivers/net/wireless/bcmdhd/wldev_common.o
  CC [M]  drivers/net/wireless/bcmdhd/wl_linux_mon.o
  CC [M]  drivers/net/wireless/bcmdhd/dhd_linux_platdev.o
  CC [M]  drivers/net/wireless/bcmdhd/hnd_pktq.o
  CC [M]  drivers/net/wireless/bcmdhd/hnd_pktpool.o
  CC [M]  drivers/net/wireless/bcmdhd/dhd_pcie.o
  CC [M]  drivers/net/wireless/bcmdhd/dhd_pcie_linux.o
drivers/net/wireless/bcmdhd/dhd_pcie_linux.c: In function 'dhdpcie_suspend_dev':
drivers/net/wireless/bcmdhd/dhd_pcie_linux.c:222:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
  dhdpcie_info_t *pch = pci_get_drvdata(dev);
  ^
drivers/net/wireless/bcmdhd/dhd_pcie_linux.c: In function 'dhdpcie_pci_probe':
drivers/net/wireless/bcmdhd/dhd_pcie_linux.c:369:2: error: implicit declaration of function 'dma_set_mask_and_coherent' [-Werror=implicit-function-declaration]
  if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
  ^
cc1: some warnings being treated as errors
make[4]: *** [drivers/net/wireless/bcmdhd/dhd_pcie_linux.o] Error 1

The dma_set_mask_and_coherent() would be either a feature which exists and just isn’t enabled, or the next thing to copy from the newer kernel and port to the current kernel. This could possibly have had a variation and instead of copy from one kernel to the other it may be that you want to adapt your driver to use something already existing.

The warning won’t hurt, but if you want to get rid of that try:

/* dhdpcie_info_t *pch = pci_get_drvdata(dev); */
dhdpcie_info_t *pch;
pch = pci_get_drvdata(dev);

Thanks linuxdev! I appreciate all the input on this! Ill give that a try right now. Also when it comes to firmware files and nvram.txt would it be possible to adapt the 4354 firmware from the l4t x1 driver package (nvidia_drivers) files:

bcm4354.hcd
brcm/fw_bcmdhd.bin
brcm/nvram.txt

I tried but still get the error. Maybe its my edit to the c file:

#ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
        tegra_sysfs_suspend();
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
        /* dhdpcie_info_t *pch = pci_get_drvdata(dev); */
        dhdpcie_info_t *pch;
        pch = pci_get_drvdata(dev);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */
        DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__));
        pci_save_state(dev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
        pch->state = pci_store_saved_state(dev);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */
        pci_enable_wake(dev, PCI_D0, TRUE);
        if (pci_is_enabled(dev)) {
                pci_disable_device(dev);
        }
        ret = pci_set_power_state(dev, PCI_D3hot);
        if (ret) {
                DHD_ERROR(("%s: pci_set_power_state error %d\n",
                        __FUNCTION__, ret));
        }
        return ret;
}

Maybe ill try to disable:

CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA

I’ll keep trying thanks again friend!

Okay I actually got it to compile by unchecking pcie interface for Broadcom Full Mac Wireless. Now we shall see if it even loads…

I spoke too soon… Might have to make the module built in kernel for android use…

ERROR: "bcmdhd_use_wl_txbf" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_custom_ampdu_mpdu" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_stop" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_iovar_op" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_disable_roam_event" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_watchdog" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_custom_pspretend_thr" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_download_firmware" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_hdrpush" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_wifi_turnoff_delay" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_sync_with_dongle" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_dongle_ramsize" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_dhd_enable_lpc" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_prop_txstatus_vsdb" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_dump" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_use_custom_pspretend_thr" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_txdata" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_hdrlen" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_init" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_ioctl" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_wl11u" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_console_in" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_clearcounts" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_dstats" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_attach" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_detach" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_unregister" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_use_wl_frameburst" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_custom_ampdu_ba_wsize" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_iovar_op" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_wifi_turnon_delay" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_hdrpull" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_dump" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_vsdb_bw_allocate_enable" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_dpc" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_use_custom_ampdu_mpdu" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_bus_init" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "bcmdhd_custom_rxcb" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
ERROR: "dhd_prot_stop" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
make[1]: *** [__modpost] Error 1
make: *** [modules] Error 2

Looks like I may need to get some header files from the kernel/linux directory…

So far as firmware goes, how firmware is divided among the kernel and device would probably help for understanding how to port it. Devices requiring extra firmware tend to download some of that firmware into the device at some binary offset in the device, and then the driver depends on the interface to that device through its own naming…a named value at the kernel side, a binary value at the device side.

An example would be a variable for a voltage setting changing the actual device behavior to increase or decrease power output on the RF end. The device may not care what you name that voltage in the kernel, but the firmware files which the kernel reads will assign the name to value if the driver needs to know about that value. If the name is used by the driver and corresponds to something which is architecture independent, it’ll “just work”. If instead the variable were say 32-bit type in older kernels and 64-bit type in the kernel it is being ported from, then you have a problem and would need to adjust for the 64/32-bit change (suppose the kernel being ported to could not handle that variable as 64-bit, you’d have to make it 32-bit…if 32-bit is enough to contain any value the variable holds, then you don’t have a problem…if the variable needs 64-bit, then you need to redesign a large part of the driver).

So one task would be to track any names in the firmware and see where they are used in the driver (you could just try it first and see if it works, and then if not go through this step). Then see what depends on that naming.