Porting guide ar71xx to ath79?

Than you for the explanation,

should the offset not be 0x20084 ?
( 0x18040028 + 0x20084 = 0x180600AC )

is the offset /shift calculated from the base address of the GPIO functions ( 0x18004000 ) or from the address of the pinmux entry as in the dts " pinmux: pinmux@18040028... " - it points to GPIO_FUNCTION_1

I've added the pinmux snippet and it compiles without issue but it doesn't set the bits as expected, could this be because offset is larger than the the pinmux "size" of 8 , but we're asking it to jump a lot further than that.

from ar9300.dtsi :

pinmux: pinmux@18040028 { 
   compatible = "pinctrl-single";
   reg = <0x18040028 0x8>;

should map to a valid range of 0x18040028 - 0x1804002F which seems to cover the general GPIO mux and settings registers GPIO_FUNCTION_1, GPIO_IN_ETH_SWITCH_LED and GPIO_FUNCTION_2

( only realized now I'm using the datasheets form your github repo, thank you for those... )

Actual, you have wrong calculate the value.
Value bit18 must be:

0b100000000000000000 = 0x20000 (hex)
  ^          <<< 321

Use this: https://ostermiller.org/calc/calculator.html

I.e. that value waht you read via io 0006220e (ar71xx) cantent one other custom bits for other needs (0b1100010001000001110 = bit19, bi18...)
Formula to write here the same as in example above.

    0b10001000001110 = your previous ATH79 value 0x220e
0b100010001000001110 = must be this 0x2220e value when bit18 is set.

In short:

&pinmux {
		pinmux_mdio_gpio {
				pinctrl-single,bits = <0x200D4 0x20000 0x20000>;

It did not work for you, because it was waiting for the mention of the link mdio_gpio
Use corrected example without link.
Now it must write this bit18 as it should.

I built it with your corrected version it still does not set the bit in the register at 0x180600AC , ( I used the mdio_gpio refrence in my gpio-export part before but get the same behaviour)

My built devicetree pinmux section looks like this ( you can decompile the dtb in openwrt/build_dir/target-mips*/linux-ath79* )

pinmux@18040028 {
compatible = "pinctrl-single";
	reg = <0x18040028 0x8>;
	pinctrl-single,register-width = <0x20>;
	pinctrl-single,function-mask = <0x1>;
	#pinctrl-cells = <0x2>;

	pinmux_jtag_disable_pins {
		pinctrl-single,bits = <0x0 0x1 0x1>;

	pinmux_switch_led_pins {
		pinctrl-single,bits = <0x0 0x0 0xf8>;
		linux,phandle = <0xb>;
		phandle = <0xb>;

	pinmux_mdio_gpio {
		pinctrl-single,bits = <0x200d4 0x20000 0x20000>;
  • disabled eJTAG ( bit 0 is "1" ),
  • switch LED pins are GPIO (bit 3,4,5,6 are "0")
  • Reset control register > RST_BOOT_STRAP bit 18 is set to enable GPIO - i think 0x20000 sets bit 17 ( counting form 0 ), but it won't cause any issue here as it doesn't seem to get written to the register at all.

could this be related to the size given in the pinmux definition ( only 8 )

pinmux: pinmux@18040028 { 
   compatible = "pinctrl-single";
   reg = <0x18040028 0x8>;
  • I don't know how the system behaves when you offset further than the size, whether it wraps around, undefined, or simply does an out of bounds access ( my background is OS-less embedded, and they don't care for boundaries much ).

I tested pinmux on my own ath79 platform and I can confirm, that is there limit of register address by 0x8*8:

root@OpenWrt:~# dmesg | grep pin
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 8128
[    0.135282] pinctrl core: initialized pinctrl subsystem
[    0.361419] pinctrl-single 18040028.pinmux: 64 pins at pa b8040028 size 8

Any way, if you want to do a pull request /or/ patch for Openwrt(for your platform), then your mentor will be will ask you to create bootstrap: bootstrap@180400ac(or he/she will do it) - it will be correct way.

Buy the way:
You were right about the correct address(0x20084).
But the bit18 value must be 0x20000 0x20000(instead 0x40000):smiley:

in the end the only way i found to "elegantly" ( for a given definition of elegant ) enable GPIO 26 and 27 by setting MDIO_GPIO_EN bit in the BOOT_STRAP register ( 0x180600AC ) was to add another pinmux entry into ar9330.dtsi with a named node, so that it will not get used unless its explicitly included in the board specific dts.

I added this snippet to ar9330.dtsi

pinmux_mdio: pinmux_mdio@180600ac {
		compatible = "pinctrl-single";
		reg = <0x180600AC 0x4>
		pinctrl-single,register-width = <32>;
		pinctrl-single,function-mask = <0x1>;
		#pinctrl-cells = <2>;

		mdio_gpio: pinmux_mdio_gpio {
			pinctrl-single,bits = <0x0 0x40000 0x40000>;


in the board specific dts one would inlcude this to enable pins 26 and 27 as GPIO.
pinctrl-0 = <&mdio_gpio>;

in a similar manner to using jtag_disable_pins or switch_led_pins to enable the use of GPIO 11, or set GPIOs 13,14,15,16 as Switch LEDs ( this PR sets them as GPIO by default rather than switch controlled )

it seems a bit hackey, but might do a PR to add it to the ar9330.dtsi file, unless there's a way of me adding something to the apb node from the device specific dtsi, but that feels like heading back to the ar71xx way of very large custom board definitions.

1 Like


the TP-Link Archer C5 v1, which is indeed the same as Archer C7 v2 https://openwrt.org/toh/tp-link/archer-c5-c7-wdr7500 only appears on the ar71xx list.

Also I only see an image for archer-c5-v1-squashfs-factory.bin on https://downloads.openwrt.org/snapshots/targets/ar71xx/generic/ so I think this device is not migrated from ar71xx to ath79. Since the device is the same as C7 v2 which is already on ath79: what is needed to migrate the C5 v1 to ath79 also?

If it is really the same, then someone needs to port it to ath79 the same way as the other one.
For instance you can do it.

1 Like

I made a new test build for WNDR3700 and included the patch for speedying up the eeprom firmware extraction from @Pilot6 (and being tested by @chunkeey in his staging tree). That enables for the first time a functioning ath9k wifi right after the flashing. No need for a separate reboot for getting wifi to work. :wink: :wink:



Many thanks for that.

1 Like

Reboot wasn't needed before. wifi command was enough. But it really fixes the annoying bug.

1 Like

@hnyman I suggest posting your tested-by to the mailing list.

Not needed any more, as chunkeey has now merged it into master:


1 Like

Hi, I am trying to port Yuncore830 (and by the same way KuWfi 830D) to Ath79 (see PR https://github.com/openwrt/openwrt/pull/1966 )

However, even if I put IMAGE_SIZE = 16000k in generik.mk, the generated image is 16384k

Does anyone know why ?

Thank you

Your PR has;

IMAGE/sysupgrade.bin := append-rootfs | pad-to 14528k | append-kernel | pad-to 16000k | check-size $$$$(IMAGE_SIZE)

What existing ported subtarget did you base it on?

Yuncore830 (Kuwfi 830) was ar71xx. Trying to move it to ath79

Please send me a PM when you've finished it. I'm currently adding support for Yunlink T740 which is very similar.

For the kernel after partition, is the line below the solution ?

IMAGE/sysupgrade.bin := append-rootfs | pad-to 14528k | append-kernel | pad-to 16000k | check-size $$(IMAGE_SIZE)

Where to find a proper documentation of generating the DTS file ?
Also, why such need ? The kernel shall detect the proper module to activate at boot time

fgrep qca9533 ./target/linux/ath79/dts/* | cut -d':' -f1
cat ./target/linux/ath79/image/* | grep -A10 qca9533
cat ./target/linux/ath79/image/generic.mk | grep -A5 yuncore

@wulfy23 and ?

I believe he’s saying “look at the source” as there are plenty of running examples there at this time.

1 Like