Products > Networking & Wireless

Configuring OpenWRT

<< < (4/4)

Nominal Animal:

--- Quote from: soldar on September 19, 2019, 07:59:17 pm ---Pardon my ignorance but it seems many routers are not prepared for OpenWRT although they are running Linux internally. I take it this is because nobody has taken the trouble of adapting OpenWRT to that specific router but, in my limited understanding, this should not be difficult, more or less like installing an OS in a computer and letting it detect the configuration. Right?
--- End quote ---
Good question, but no.

These are embedded devices, whose internal structure varies a lot. A major part of the configuration is Device Tree, which describes how the processor/microcontroller accesses its integrated parts.  For example, on Asus RT-AC51U, the device tree is described in source form as RT-AC51U.dts:

--- Code: ---/dts-v1/;

 #include "mt7620a.dtsi"

 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>

/ {
compatible = "asus,rt-ac51u", "ralink,mt7620a-soc";
model = "Asus RT-AC51U";

gpio-leds {
compatible = "gpio-leds";

power {
label = "rt-ac51u:blue:power";
gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
};

usb {
label = "rt-ac51u:blue:usb";
gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
};

wifi {
label = "rt-ac51u:blue:wifi";
gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
};
};

gpio-keys-polled {
compatible = "gpio-keys-polled";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <20>;

reset {
label = "reset";
gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};

wps {
label = "wps";
gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
};
};

gpio_export {
compatible = "gpio-export";
#size-cells = <0>;

enable-leds {
gpio-export,name = "enable-leds";
gpio-export,output = <1>;
gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
};
};
};

&spi0 {
status = "okay";

m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <10000000>;

partition@0 {
label = "u-boot";
reg = <0x0 0x30000>;
read-only;
};

partition@30000 {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};

factory: partition@40000 {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
};

partition@50000 {
label = "firmware";
reg = <0x50000 0xfb0000>;
};
};
};

&ehci {
status = "okay";
};

&ohci {
status = "okay";
};

&gpio3 {
status = "okay";
};

&ethernet {
status = "okay";
mtd-mac-address = <&factory 0x4>;
mediatek,portmap = "wllll";
};

&wmac {
ralink,mtd-eeprom = <&factory 0>;
};

&pinctrl {
state_default: pinctrl0 {
gpio {
ralink,group = "i2c", "wled", "uartf";
ralink,function = "gpio";
};
};
};

--- End code ---

You'll see that it uses JEDEC/SPI-NOR flash at max. 10 MHz, with four partitions. spi0 itself is defined in the include file mt7620a.dts, which contains the device tree internal to the processor/microcontroller used (Mediatek MT7620a):

--- Code: ---/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "ralink,mt7620a-soc";

cpus {
cpu@0 {
compatible = "mips,mips24KEc";
};
};

chosen {
bootargs = "console=ttyS0,57600";
};

cpuintc: cpuintc@0 {
#address-cells = <0>;
-cells = <1>;
interrupt-controller;
compatible = "mti,cpu-interrupt-controller";
};

aliases {
spi0 = &spi0;
spi1 = &spi1;
serial0 = &uartlite;
};

palmbus: palmbus@10000000 {
compatible = "palmbus";
reg = <0x10000000 0x200000>;
ranges = <0x0 0x10000000 0x1FFFFF>;

#address-cells = <1>;
#size-cells = <1>;

sysc: sysc@0 {
compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc", "syscon";
reg = <0x0 0x100>;
};

timer: timer@100 {
compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer";
reg = <0x100 0x20>;

interrupt-parent = <&intc>;
interrupts = <1>;
};

watchdog: watchdog@120 {
compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt";
reg = <0x120 0x10>;

resets = <&rstctrl 8>;
reset-names = "wdt";

interrupt-parent = <&intc>;
interrupts = <1>;
};

intc: intc@200 {
compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc";
reg = <0x200 0x100>;

resets = <&rstctrl 19>;
reset-names = "intc";

interrupt-controller;
-cells = <1>;

interrupt-parent = <&cpuintc>;
interrupts = <2>;
};

memc: memc@300 {
compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc";
reg = <0x300 0x100>;

resets = <&rstctrl 20>;
reset-names = "mc";

interrupt-parent = <&intc>;
interrupts = <3>;
};

uart: uart@500 {
compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0x500 0x100>;

resets = <&rstctrl 12>;
reset-names = "uart";

interrupt-parent = <&intc>;
interrupts = <5>;

reg-shift = <2>;

status = "disabled";
};

gpio0: gpio@600 {
compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
reg = <0x600 0x34>;

resets = <&rstctrl 13>;
reset-names = "pio";

interrupt-parent = <&intc>;
interrupts = <6>;

gpio-controller;
-cells = <2>;

ralink,gpio-base = <0>;
ralink,num-gpios = <24>;
ralink,register-map = [ 00 04 08 0c
20 24 28 2c
30 34 ];
};

gpio1: gpio@638 {
compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
reg = <0x638 0x24>;

interrupt-parent = <&intc>;
interrupts = <6>;

gpio-controller;
-cells = <2>;

ralink,gpio-base = <24>;
ralink,num-gpios = <16>;
ralink,register-map = [ 00 04 08 0c
10 14 18 1c
20 24 ];

status = "disabled";
};

gpio2: gpio@660 {
compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
reg = <0x660 0x24>;

interrupt-parent = <&intc>;
interrupts = <6>;

gpio-controller;
-cells = <2>;

ralink,gpio-base = <40>;
ralink,num-gpios = <32>;
ralink,register-map = [ 00 04 08 0c
10 14 18 1c
20 24 ];

status = "disabled";
};

gpio3: gpio@688 {
compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
reg = <0x688 0x24>;

interrupt-parent = <&intc>;
interrupts = <6>;

gpio-controller;
-cells = <2>;

ralink,gpio-base = <72>;
ralink,num-gpios = <1>;
ralink,register-map = [ 00 04 08 0c
10 14 18 1c
20 24 ];

status = "disabled";
};

i2c: i2c@900 {
compatible = "ralink,rt2880-i2c";
reg = <0x900 0x100>;

resets = <&rstctrl 16>;
reset-names = "i2c";

#address-cells = <1>;
#size-cells = <0>;

status = "disabled";

pinctrl-names = "default";
pinctrl-0 = <&i2c_pins>;
};

i2s: i2s@a00 {
compatible = "mediatek,mt7620-i2s";
reg = <0xa00 0x100>;

resets = <&rstctrl 17>;
reset-names = "i2s";

interrupt-parent = <&intc>;
interrupts = <10>;

txdma-req = <2>;
rxdma-req = <3>;

dmas = <&gdma 4>,
<&gdma 6>;
dma-names = "tx", "rx";

status = "disabled";
};

spi0: spi@b00 {
compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
reg = <0xb00 0x40>;

resets = <&rstctrl 18>;
reset-names = "spi";

#address-cells = <1>;
#size-cells = <0>;

status = "disabled";

pinctrl-names = "default";
pinctrl-0 = <&spi_pins>;
};

spi1: spi@b40 {
compatible = "ralink,rt2880-spi";
reg = <0xb40 0x60>;

resets = <&rstctrl 18>;
reset-names = "spi";

#address-cells = <1>;
#size-cells = <0>;

status = "disabled";

pinctrl-names = "default";
pinctrl-0 = <&spi_cs1>;
};

uartlite: uartlite@c00 {
compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;

resets = <&rstctrl 19>;
reset-names = "uartl";

interrupt-parent = <&intc>;
interrupts = <12>;

reg-shift = <2>;

pinctrl-names = "default";
pinctrl-0 = <&uartlite_pins>;
};

systick: systick@d00 {
compatible = "ralink,mt7620a-systick", "ralink,cevt-systick";
reg = <0xd00 0x10>;

resets = <&rstctrl 28>;
reset-names = "intc";

interrupt-parent = <&cpuintc>;
interrupts = <7>;
};

pcm: pcm@2000 {
compatible = "ralink,mt7620a-pcm";
reg = <0x2000 0x800>;

resets = <&rstctrl 11>;
reset-names = "pcm";

interrupt-parent = <&intc>;
interrupts = <4>;

status = "disabled";
};

gdma: gdma@2800 {
compatible = "ralink,mt7620a-gdma", "ralink,rt3883-gdma";
reg = <0x2800 0x800>;

resets = <&rstctrl 14>;
reset-names = "dma";

interrupt-parent = <&intc>;
interrupts = <7>;

-cells = <1>;
-channels = <16>;
-requests = <16>;

status = "disabled";
};
};

pinctrl: pinctrl {
compatible = "ralink,rt2880-pinmux";
pinctrl-names = "default";
pinctrl-0 = <&state_default>;

state_default: pinctrl0 {
};

pcm_i2s_pins: pcm_i2s {
pcm_i2s {
ralink,group = "uartf";
ralink,function = "pcm i2s";
};
};

uartf_gpio_pins: uartf_gpio {
uartf_gpio {
ralink,group = "uartf";
ralink,function = "gpio uartf";
};
};

gpio_i2s_pins: gpio_i2s {
gpio_i2s {
ralink,group = "uartf";
ralink,function = "gpio i2s";
};
};

spi_pins: spi {
spi {
ralink,group = "spi";
ralink,function = "spi";
};
};

spi_cs1: spi1 {
spi1 {
ralink,group = "spi_cs1";
ralink,function = "spi_cs1";
};
};

i2c_pins: i2c {
i2c {
ralink,group = "i2c";
ralink,function = "i2c";
};
};

uartlite_pins: uartlite {
uart {
ralink,group = "uartlite";
ralink,function = "uartlite";
};
};

mdio_pins: mdio {
mdio {
ralink,group = "mdio";
ralink,function = "mdio";
};
};

mdio_refclk_pins: mdio_refclk {
mdio_refclk {
ralink,group = "mdio";
ralink,function = "refclk";
};
};

ephy_pins: ephy {
ephy {
ralink,group = "ephy";
ralink,function = "ephy";
};
};

wled_pins: wled {
wled {
ralink,group = "wled";
ralink,function = "wled";
};
};

rgmii1_pins: rgmii1 {
rgmii1 {
ralink,group = "rgmii1";
ralink,function = "rgmii1";
};
};

rgmii2_pins: rgmii2 {
rgmii2 {
ralink,group = "rgmii2";
ralink,function = "rgmii2";
};
};

pcie_pins: pcie {
pcie {
ralink,group = "pcie";
ralink,function = "pcie rst";
};
};

pa_pins: pa {
pa {
ralink,group = "pa";
ralink,function = "pa";
};
};
};

rstctrl: rstctrl {
compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset";
-cells = <1>;
};

clkctrl: clkctrl {
compatible = "ralink,rt2880-clock";
-cells = <1>;
};

usbphy: usbphy {
compatible = "mediatek,mt7620-usbphy";
-cells = <0>;

ralink,sysctl = <&sysc>;
resets = <&rstctrl 22 &rstctrl 25>;
reset-names = "host", "device";

clocks = <&clkctrl 22 &clkctrl 25>;
clock-names = "host", "device";
};

ethernet: ethernet@10100000 {
compatible = "mediatek,mt7620-eth";
reg = <0x10100000 0x10000>;

#address-cells = <1>;
#size-cells = <0>;

interrupt-parent = <&cpuintc>;
interrupts = <5>;

resets = <&rstctrl 21 &rstctrl 23>;
reset-names = "fe", "esw";

mediatek,switch = <&gsw>;

port@4 {
compatible = "mediatek,mt7620a-gsw-port", "mediatek,eth-port";
reg = <4>;

status = "disabled";
};

port@5 {
compatible = "mediatek,mt7620a-gsw-port", "mediatek,eth-port";
reg = <5>;

status = "disabled";
};

mdio-bus {
#address-cells = <1>;
#size-cells = <0>;

status = "disabled";
};
};

gsw: gsw@10110000 {
compatible = "mediatek,mt7620-gsw";
reg = <0x10110000 0x8000>;

resets = <&rstctrl 23>;
reset-names = "esw";

interrupt-parent = <&intc>;
interrupts = <17>;
};

sdhci: sdhci@10130000 {
compatible = "ralink,mt7620-sdhci";
reg = <0x10130000 0x4000>;

interrupt-parent = <&intc>;
interrupts = <14>;

status = "disabled";
};

ehci: ehci@101c0000 {
compatible = "generic-ehci";
reg = <0x101c0000 0x1000>;

interrupt-parent = <&intc>;
interrupts = <18>;

phys = <&usbphy>;
phy-names = "usb";

status = "disabled";
};

ohci: ohci@101c1000 {
compatible = "generic-ohci";
reg = <0x101c1000 0x1000>;

interrupt-parent = <&intc>;
interrupts = <18>;

phys = <&usbphy>;
phy-names = "usb";

status = "disabled";
};

pcie: pcie@10140000 {
compatible = "mediatek,mt7620-pci";
reg = <0x10140000 0x100
0x10142000 0x100>;

#address-cells = <3>;
#size-cells = <2>;

resets = <&rstctrl 26>;
reset-names = "pcie0";

clocks = <&clkctrl 26>;
clock-names = "pcie0";

interrupt-parent = <&cpuintc>;
interrupts = <4>;

pinctrl-names = "default";
pinctrl-0 = <&pcie_pins>;

device_type = "pci";

bus-range = <0 255>;
ranges = <
0x02000000 0 0x00000000 0x20000000 0 0x10000000 /* pci memory */
0x01000000 0 0x00000000 0x10160000 0 0x00010000 /* io space */
>;

status = "disabled";

pcie-bridge {
reg = <0x0000 0 0 0 0>;

#address-cells = <3>;
#size-cells = <2>;

device_type = "pci";
};
};

wmac: wmac@10180000 {
compatible = "ralink,rt7620-wmac", "ralink,rt2880-wmac";
reg = <0x10180000 0x40000>;

interrupt-parent = <&cpuintc>;
interrupts = <6>;

ralink,eeprom = "soc_wmac.eeprom";
};
};

--- End code ---


Edited to add: Some of the above lines are garbled (-cells:), because Dave feels HASHTAG support is more important than reproducing code in code snippets correctly.  Way to go, @dave!  :--
Edited to add further: You cannot even post hashtag-hashtag; the forum software silently eats it.  Nice!

The device tree system was designed exactly because it is not possible to autodetect these features (and system integrators started to bake-in these settings to the source code, which would have bloated the kernel itself to unmanageable sizes very, very fast).

Note that you cannot see the contents of device tree source files in the firmware images (or ramdisk images), because they are compiled to binary (.dtb) form. (The device tree compiler package includes a decompiler, fdtdump, though.)


--- Quote from: soldar on September 19, 2019, 07:59:17 pm ---Maybe it would detect some IC for which it does not have driver but otherwise it would "autoconfigure".  Why not?
--- End quote ---
These things do not have any sort of detection mechanisms.  There is no way to detect that spi0 is connected to the flash, that it works reliably at up to 10 MHz SPI clock rates.

Even if you manage to create a kernel that does autodetect all these features reliably, it would be too large to fit in the typical 8 MiB flash most current routers have, much less the 4 MiB on your TP-Link router.


--- Quote from: soldar on September 19, 2019, 07:59:17 pm ---Is there any easy way of adapting OpenWRT to a specific router for which there is not a version in the repository?
--- End quote ---
Define "easy".

Many routers are just OEM models rebadged and re-enclosured, with basically the same circuit inside.  Sometimes they have slightly newer external chips or ethernet PHYs, but an existing router firmware image for the same device works, except for some features.  Then, it is a matter of finding how to support the unsupported parts.  For very new system-on-chips, you may need to backport device support from the vanilla (kernel.org) kernels to support that processor.  (Processor manufacturers are nowadays pretty good at pushing the support into upstream Linux; it just makes sense, because it reduces the effort and time needed to get support on the market.  Though, there are still vendors who insist on forking a specific version of Linux, and creating their own "SDK" on top of it, which means they're frozen in time at that point, and won't get support for new devices (radios and such) unless the vendor backports the support -- and they won't.)

(Conversely, many routers may completely change their hardware between minor revisions! Usually the revision is shown on some sticker at the bottom of the device, but otherwise may look exactly the same -- but internally, are completely different devices.)

If the router already runs some variant of Linux, it may have a device tree representation in the official firmware image.  Decompiling those, one can examine how the subsystems are wired; then, it is just a matter of finding the proper kernel device drivers to use.  It is a lot of work, but relatively straightforward; mostly searching and verification.

Most routers have an UART on the board configured as a serial console, providing the kernel messages.  (This is useful for development, and debugging malfunctioning units, so it makes sense to leave it enabled.)  These messages provide helpful information about the subsystems and drivers used.

Physical examination of the chips on the board can tell where to start; this is why you can find board images of many routers.

soldar:
I have several Chinese routers with all the configuration menus in Chinese. Navigating menus in Chinese seems much easier to me than trying to flash firmware in English so I guess I will leave them as they are.

Navigation

[0] Message Index

[*] Previous page

There was an error while thanking
Thanking...
Go to full version