This page provides an overview of the Broadcom BCM63xx series soc , which share many similarities with the BCM33xx SoCs (with the exception of the BCM3302, which is a standalone CPU). The difference between the two being that the DSL core in the BCM63xx is replaced with a DOCSIS/EuroDOCSIS core in the BCM33xx series.
The Broadcom BCM63xx SoC integrates ADSL/ADSL2+ capabilities, routing functions, and support for external Wireless NICs.
This SoC family is widely adopted in xDSL platforms globally and is considered one of the most successful xDSL platforms. Its success is attributed to the ease of transitioning older platforms (e.g., BCM6345) to newer ones with minimal software changes.
Architecture information:
Older BCM63xx SoCs are based on the MIPS32 Big Endian instruction set, with architectural similarities to the R4000 microprocessor.
Newer BCM63xx SoCs have transitioned to the ARMv7a Little Endian instruction set, exemplified by chips like the BCM63138.
The support for Broadcom 63xx is at this state :
Certain Broadcom SoCs, including the BCM6358, BCM6361, BCM6362, and BCM6368, feature dual cores. However, the BCM6358 is limited to using only one core. While the kernel includes SMP support (see smp-bmips.c), fully utilizing both cores is complex. The second CPU must be explicitly initialized, and the current interrupt (IRQ) code only enables interrupts on the first CPU. Consequently, only userspace processes can access the second core, while all interrupt handlers remain tied to the first core.
SoC | CPU MHz | Dual Core | RAM | NAND | USB Device | USB Host | PCMCIA / PCCARD | PCI | PCIe | Wireless NIC | Switch | ADSL2 | ADSL2+ | VDSL | VDSL2 | Fiber | OpenWrt |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
bcm6318 | 333 | ☐ | DDR | ☐ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ☐ | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ | |
bcm6328 | 320 | ☐ | DDR2 | ✔ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ☐ | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ | 12.09 |
bcm6329 | 320 | ✔ | DDR2 | ✔ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | ☐ | |
bcm6335 | 140 | ☐ | SDR | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | |
bcm6338 | 240 | ☐ | SDR | ☐ | 1.1 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ✔ | ✔ | ☐ | ☐ | ☐ | 10.03 |
bcm6345 | 140 | ☐ | SDR | ☐ | 1.1 | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | 10.03 |
bcm6348 | 256 | ☐ | SDR | ☐ | 1.1 | 1.1 | ✔ | ✔ | ☐ | ☐ | ☐ | ✔ | ✔ | ☐ | ☐ | ☐ | 10.03 |
bcm6358 | 300 | ✔ | DDR | ☐ | 1.1 | 2.0 | ✔ | ✔ | ☐ | ☐ | ☐ | ✔ | ✔ | ☐ | ☐ | ☐ | 10.03 |
bcm6359 | 300 | ✔ | DDR | ☐ | 2.0 | 2.0 | ✔ | ✔ | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | 10.03 |
bcm6361 bcm6362 | 400 | ✔ | DDR2 | ✔ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ✔ | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ | r32923 |
bcm6367 | 400 | ✔ | DDR | ✔ | 2.0 | 2.0 | ✔ | ✔ | ☐ | ☐ | ✔ | ✔ | ✔ | ✔ | ☐ | ☐ | 12.09 |
bcm6368 | 400 | ✔ | DDR | ✔ | 2.0 | 2.0 | ✔ | ✔ | ☐ | ☐ | ✔ | ✔ | ✔ | ✔ | ✔ | ☐ | 12.09 |
bcm6369 | 400 | ✔ | DDR | ✔ | 2.0 | 2.0 | ✔ | ✔ | ☐ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | ☐ | |
bcm63167 bcm63168 bcm63268 | 400 | ✔ | DDR2/3 | ✔ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ☐ | |
bcm63169 bcm63269 | 400 | ✔ | DDR2 | ✔ | 2.0 | 2.0 | ☐ | ☐ | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ | ☐ | ☐ | |
bcm6816 | 400 | ✔ | DDR2 | ✔ | 2.0 | 2.0 | ✔ | ✔ | ✔ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | ✔ | |
bcm6818 | 400 | ✔ | DDR2 | ✔ | 2.0 | 2.0 | ✔ | ✔ | ✔ | ☐ | ✔ | ☐ | ☐ | ☐ | ☐ | ✔ | |
bcm63138 | 1000 | ✔ | DDR3 | ✔ | 3.0 | 3.0 | ☐ | ☐ | ✔ | ☐ | ? | ✔ | ✔ | ✔ | ✔ | ☐ | |
bcm63139 | 1000 | ✔ | DDR3 | ✔ | 3.0 | 3.0 | ☐ | ☐ | ? | ☐ | ✔ | ? | ? | ? | ? | ☐ |
icache | dcache | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
SoC | CPU version | Core | Size (kB) | Associativity | Linesize (bytes) | Cache policy | Size (kB) | Associativity | Aliases | Linesize (bytes) | Cache policy |
BCM6348 | BMIPS3300 V0.7 | 0 | 16 | 2-way | 16 | VIPT | 8 | 2-way | ☐ | 16 | VIPT |
BCM6318 | BMIPS3300 v3.3 | 0 | 64 | 4-way | 16 | VIPT | 32 | 2-way | ✔ | 16 | VIPT |
BCM6358 | BMIPS4350 V1.0 | 0 | 32 | 2-way | 16 | VIPT | 16 | 2-way | ✔ | 16 | VIPT |
1 | 16 | 2-way | 16 | VIPT | |||||||
BCM6368 | BMIPS4350 V3.1 | 0 | 64 | 4-way | 16 | VIPT | 32 | 2-way | ✔ | 16 | VIPT |
1 | 64 | 4-way | 16 | VIPT | |||||||
BCM6361 | BMIPS4350 V7.0 | 0 | 32 | 4-way | 16 | VIPT | 32 | 2-way | ✔ | 16 | VIPT |
1 | 32 | 4-way | 16 | VIPT | |||||||
BCM6328 | BMIPS4350 v7.5 | 0 | 32 | 4-way | 16 | VIPT | 32 | 2-way | ✔ | 16 | VIPT |
BCM63168 | BMIPS4350 V8.0 | 0 | 64 | 4-way | 16 | VIPT | 32 | 2-way | ✔ | 16 | VIPT |
1 | 64 | 4-way | 16 | VIPT |
VIPT = Virtually indexed, physically tagged
Hardware random number generator
Only available in BCM6362, BCM6368, BCM6816. GPL supported. bcm63xx-rng.c dev-rng.c
To take advantage of this hardware feature, rng-tools should be installed.
BCM63xx SoCs have cryptographic hardware accelerators. The Cipher engine accelerates the IPSec protocol by using dedicated hardware blocks. BCM63XX SoCs (all family? ) are implemented with the Encapsulating Security Payload (ESP) and Authentication Header (AH) IPSec protocols:
This what Broadcom calls SPU (Secure Processing Unit). The driver is available with GPL
http://code.google.com/p/gfiber-gflt100/source/browse/bcmdrivers/opensource/char/spudd/impl2/
The SPU drivers has been added since Linux kernel v4.11 → https://github.com/torvalds/linux/commit/9d12ba8
But there isn't still support for SPU under OpenWrt/LEDE.
Two types of SPI controllers are present in BCM63xx:
By default only one or two (more in newer SoCs) Slave Selects are available. Additional Slave Selects are at GPIO lines, but they need to be enabled.
(SPI) | Slave Select 0 | Slave Select 1 | Slave Select 2 | Slave Select 3 | Slave Select 4 | Slave Select 5 |
BCM6338 | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ |
BCM6348 | ✔ | GPIO29 | GPIO30 | GPIO31 | ☐ | ☐ |
BCM6358 | ✔ | ✔ | GPIO32 | GPIO33 | ☐ | ☐ |
BCM6368 BCM6816 BCM6818 | ✔ | ✔ | GPIO28 | GPIO29 | GPIO30 | GPIO31 |
BCM6362 | ✔ | ✔ | GPIO9 | GPIO10 | ☐ | ☐ |
(HSSPI) | Slave Select 0 | Slave Select 1 | Slave Select 2 | Slave Select 3 | Slave Select 4 | Slave Select 5 | Slave Select 6 | Slave Select 7 |
BCM6328 | ✔ | ✔ | ✔ | ✔ | ☐ | ☐ | ☐ | ☐ |
BCM6828 | ✔ | ✔ | GPIO16 | GPIO17 | GPIO9 | ☐ | ☐ | ☐ |
BCM63268 | ✔ | ✔ | ✔ | ✔ | GPIO16 | GPIO17 | GPIO8 | GPIO9 |
Snippet code example for enabling these extra slave-selects at GPIOs:
/* BCM6348 */ u32 val; /* Enable Extra SPI CS */ /* GPIO 29 is SS1, GPIO 30 is SS2, GPIO 31 is SS2 */ val = bcm_gpio_readl(GPIO_MODE_REG); val |= GPIO_MODE_6348_G1_SPI_MASTER; bcm_gpio_writel(val, GPIO_MODE_REG); /* BCM6358 */ u32 val; /* Enable Overlay for SPI SS Pins */ val = bcm_gpio_readl(GPIO_MODE_REG); val |= GPIO_MODE_6358_EXTRA_SPI_SS; bcm_gpio_writel(val, GPIO_MODE_REG); /* Enable SPI Slave Select as Output Pins */ /* GPIO 32 is SS2, GPIO 33 is SS3 */ val = bcm_gpio_readl(GPIO_CTL_HI_REG); val |= 0x0003; bcm_gpio_writel(val, GPIO_CTL_HI_REG); /* BCM6368 */ u32 val; /* Enable Extra SPI CS */ val = bcm_gpio_readl(GPIO_MODE_REG); val |= (GPIO_MODE_6368_SPI_SSN2 | GPIO_MODE_6368_SPI_SSN3 | GPIO_MODE_6368_SPI_SSN4 | GPIO_MODE_6368_SPI_SSN5); bcm_gpio_writel(val, GPIO_MODE_REG); /* Enable SPI Slave Select as Output Pins */ /* GPIO 28 is SS2, GPIO 29 is SS3, GPIO 30 is SS4, GPIO 31 is SS5*/ val = bcm_gpio_readl(GPIO_CTL_LO_REG); val |= (GPIO_MODE_6368_SPI_SSN2 | GPIO_MODE_6368_SPI_SSN3 | GPIO_MODE_6368_SPI_SSN4 | GPIO_MODE_6368_SPI_SSN5); bcm_gpio_writel(val, GPIO_CTL_LO_REG); /* BCM6328 */ #define SEL_SPI2 8 #define PINMUX_SEL_SPI2_MASK (3 << SEL_SPI2) #define PINMUX_SEL_SPI2 (2 << SEL_SPI2) u32 val; /* configure pinmux to SPI extra Slave Select */ val = bcm_gpio_readl(GPIO_PINMUX_OTHR_REG); val &= ~PINMUX_SEL_SPI2_MASK; bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG); val = bcm_gpio_readl(GPIO_PINMUX_OTHR_REG); val |= PINMUX_SEL_SPI2; bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG); /* BCM63268 */ #define GPIO_MODE_63268_HSSPI_SSN4 (1 << 16) #define GPIO_MODE_63268_HSSPI_SSN5 (1 << 17) #define GPIO_MODE_63268_HSSPI_SSN6 (1 << 8) #define GPIO_MODE_63268_HSSPI_SSN7 (1 << 9) u32 val; /* GPIO 16 is SS4, GPIO 17 is SS5, GPIO 8 is SS6, GPIO 9 is SS7*/ val = bcm_gpio_readl(GPIO_MODE_REG); val |= (GPIO_MODE_63268_HSSPI_SSN4 | GPIO_MODE_63268_HSSPI_SSN5 | GPIO_MODE_63268_HSSPI_SSN6 | GPIO_MODE_63268_HSSPI_SSN7); bcm_gpio_writel(val, GPIO_MODE_REG);
We can locate slave selects on the board by toggling the state of them.
devmem
enabled in busybox and kernel#!/bin/sh # Toggle the SPI_SS_POLARITY, "blink" the SPI chip select # Example: "blink" the chip select 2 # ./sstoggle.sh 2 #6318 #SPIBASE=0x10003000 #6328 6362 63268 SPIBASE=0x10001000 DEFAULT=`devmem $SPIBASE` OFF=`printf "0x%x" "$(( $DEFAULT | (1 << $1) ))"` ON=`printf "0x%x" "$(( $DEFAULT & ~(1 << $1) ))"` while true; do devmem $SPIBASE 32 $OFF echo "[OFF]: $SPIBASE 32 $OFF" sleep 1 devmem $SPIBASE 32 $ON echo "[ON ]: $SPIBASE 32 $ON" sleep 1 done
The script is only valid for HSSPI.
On bcm63xx boards the GPIOs are used for diferent purposes:
The amount of GPIOs of each SoC model is different:
BCM6333 | BCM6338 | BCM6345 | BCM6348 | BCM6358 | BCM6368 | BCM6318 | BCM6328 | BCM6362 | BCM63268 | |
GPIO count | 5 | 8 | 16 | 37 | 38 | 38 | 50 | 32 | 48 | 52 |
When having more than 32 GPIOs they are splitted between 2 gpiochips. The labels in the Linux kernel are:
bcm63xx-gpio.0
bcm63xx-gpio.1
A few GPIOs are shared with external IRQs on most SoCs except BCM6338
External interrupts | IRQ_EXT_0 | IRQ_EXT_1 | IRQ_EXT_2 | IRQ_EXT_3 | IRQ_EXT_4 | IRQ_EXT_5 |
BCM6318 | GPIO32 | GPIO33 | ? | ? | ☐ | ☐ |
BCM6328 | GPIO23 | GPIO24 | GPIO15 | GPIO12 | ☐ | ☐ |
BCM6338 | ✔ | ✔ | ☐ | ☐ | ☐ | ☐ |
BCM6345 | ? | ? | ? | ? | ☐ | ☐ |
BCM6348 | GPIO32 | GPIO33 | GPIO34 | GPIO35 | GPIO36 | ☐ |
BCM6358 | GPIO34 | GPIO35 | GPIO36 | GPIO37 | GPIO32 | GPIO33 |
BCM6368 | ||||||
BCM6362 | GPIO24 | GPIO25 | GPIO26 | GPIO27 | ☐ | ☐ |
BCM63268 | GPIO32 | GPIO33 | GPIO34 | GPIO35 | ☐ | ☐ |
*) Guessed
Caveats:
Since LEDE Reboot there is full support for external IRQs with “gpio to irq” translation. → https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=dd7079e79a
Snippet kernel code example: a button press triggers an IRQ, printing something on the console. Tested on BCM6348, Openwrt 12.09 and GPIO33 connected to an external button.
#include <linux/kernel.h> #include <linux/err.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <bcm63xx_cpu.h> #include <bcm63xx_io.h> #include <bcm63xx_regs.h> #include <bcm63xx_irq.h> static irqreturn_t gpio_interrupt(int irq, void *dev_id) { printk("my IRQ triggered!!!!\n"); return IRQ_HANDLED; } int bcm63xx_button_init(void) { int ret, irq; printk("TEST IRQ (GPIO-button)\n"); irq = IRQ_EXT_1; ret = request_irq(irq, gpio_interrupt, 0, "bcm63xx_extIRQ", NULL); if (ret) { printk(KERN_ERR "bcm63xx-extIRQ: failed to register irq %d\n",irq); return ret; } printk("Mapped IRQ %d\n", irq ); return 0; } arch_initcall(bcm63xx_button_init);
bootloader: Some devices use redboot such as Inventel Liveboxes. Most of the others use cfe with a built-in LZMA decompressor. CFE is not using standard LZMA compression arguments, and most noticeably, changes the dictionary size, so beware. Thomson routers have their own bootloader.
There is released source code for RedBoot (Inventel Livebox), and probably can be modified to work with other routers. Also there is some source code for uboot.
On several CPE (Customer-premises equipment) hardware devices and especially on smart phones, the OEM bootloaders are feature poor (no netboot, no booting from a USB stick, etc.), obfuscated (require some magic values to be correct) or completely messed up and make it cumbersome, difficult or impossible to install free software on the device. It is thus paramount to always have at least some products available, that have OEM bootloaders that keep installing free software easy (cf. generic.flashing). And it could be interesting to port such bootloaders to devices, which happen to come with a restricted bootloader. Compare the available bootloader out there, their license, available code and feature sets. Please also remember that available source code it NOT enough, it has to be under some license, that allow for modification and redistribution.
bcm63xx boards have U-boot support thanks to the developer Álvaro Fernández (Noltari). Currently only available for the RAM bootloader version. The ROM version requires low level initialisations to be integrated into U-Boot (TODO).
https://github.com/Noltari/u-boot/commits/master?author=noltari
There is an official broadcom u-boot port for 63137/63138, 63158, and 63178; it is able to replace cfe, but there is no GPL release of this yet.
There exists an utility to backup the entire flash:
cfetool
You must connect your PC with the bcm63xx router via serial TTL port while CFE is running. Then execute cfetool with a command like this, maybe different with different boot address / flash sizes.
./cfetool.py --read=dump.bin --addr=0xB8000000 --size=0x1000000 --block=0x10000 --addr=0xB8000000 -> Flash Memory Address (see CFE bootlog --> Boot Address) --size=0x1000000 -> 16Mb Flash --block=0x10000 -> Memory dumped each iteration (default is 10Kb 0x2800)
cfetool expects the serial port used is /dev/ttyUSB0 in your PC, but you can change it with “--serial=/dev/ttyUSB1”.
Note: not all CFEs have internally the dm/sm command, as a result of this cfetool may not work with some devices. Alternatively you can dump the flash via traditional methods like JTAG or with an OpenWrt ramdisk firmware version.
On the BCM6348 the MPI interface is wired to both the flash chip and the miniPCI interface. The CPU clock configuration is strapped from 5 pins on this interface. These 5 pins use pulldown resistors (4.7 or 10 kohm) to configure the CPU clock:
Flash pin | DQ0 | DQ8 | DQ1 | DQ9 | DQ10 | CPU clock (MHz) |
---|---|---|---|---|---|---|
mPCI pin | AD27 | AD28 | AD29 | AD30 | AD31 | |
Pulldown resistor | ☐ | ✔ | ✔ | ✔ | ✔ | 200 |
☐ | ✔ | ☐ | ✔ | ✔ | 240 | |
✔ | ☐ | ☐ | ✔ | ✔ | 256 | |
☐ | ☐ | ☐ | ✔ | ✔ | 264 | |
☐ | ✔ | ✔ | ☐ | ✔ | 300 |
Example of CPU clock modification → Comtrend CT5361 overclocking
Note: only tested on BCM6348KPBG
The same pins used in BCM6348 are also used in the BCM6368 SoC. 4.7 kohm pull down resistors are also used to configure the CPU frequency.
Flash pin | DQ0 | DQ8 | DQ1 | DQ9 | DQ10 | CPU clock (MHz) |
---|---|---|---|---|---|---|
mPCI pin | AD27 | AD28 | AD29 | AD30 | AD31 | |
Pulldown resistor | ☐ | ☐ | ✔ | ☐ | ✔ | 266 |
☐ | ☐ | ☐ | ☐ | ✔ | 320 | |
☐ | ☐ | ☐ | ✔ | ☐ | 384 | |
☐ | ☐ | ☐ | ☐ | ☐ | 400 | |
☐ | ☐ | ✔ | ☐ | ☐ | 426 | |
☐ | ☐ | ✔ | ✔ | ✔ | 533 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|