Adding support for Mojo Networks C-65

Hi all, my first post here :slight_smile:

Found Mojo Networks C-65 brick and wondering if anyone has messed with it yet.

The SoC is QCA9558, QCA9882 Additional Wireless, AR8035-A PHY, 128 RAM, 2x128MB Flash (updated 5/30/2019)
I got the rs232 TTL (currently in read-only mode, faulty prolific awaits for successor from far-away China)
Looks like an old but still capable device. No stock GUI - meant to be cloud-controlled.
Any Guru want to mess with it?
Boot printout

That it seems to have TFTP capability and a detailed boot log might make it a great device for you to become a guru yourself.

Ehm, maybe so, I'm very far from being a dev... I may try to feed it something with TFTP which it asks for before booting from flash. Is there a build with similar hardware and image layout that I could try? There is an SSH port open on the stock firmware but it is paroled and credentials are unknown...

Do I get it right? The device uses UBoot and prompts for TFTP .bin file to boot from, then falls back to internal memory. In order to make it work with TFTP I have to create an image which can be done with the image builder.
I walked through the guide on setting up a build environment with VirtualBox and have it done on a local machine.
Now I am confused with picking the right options... How do I identify the right hardware driver set and software options that I need? How do I pick the right image format to feed? What information can I fetch from the attached boot log? I am a newbie but I want to learn :smiley:
Please advice!

The image builder is for creating a custom image for a currently supported device quickly.

If your trying to add support for a new device you can't use imagebuilder

Have a read of the documentation

1 Like

Thanks for pointing that out mbo2o,
I guess first I need to get a ramdisk image done and loaded to the device to be able to test without writing and post results. I am not a dev and will need some help doing that.
If anyone willing to do that - time and device are available.

It takes time and patience, a vague understanding of shell scripts, comfort with using git, generally no "C skills", and then a lot more time and patience.

The challenge is that every device is "wired" a little differently, and it takes some time to figure it all out.

Having the OEM's GPL drop is often helpful in figuring out, for example "GPIO 7 is the WAN LED" or the like.

You can't just flash/boot an image from Device X that has the same chips and get things to run safely. Loss of irreplaceable data from flash is common if you write to / allow writes to flash before you can make copies of them for safe keeping. Worst cases (there are many) include that an unfortunate choice of GPIO, clocks, or the like, physically damages one or more portions of the device.

jeff@deb-devel:~/devel/openwrt/target/linux$ fgrep -ri 9557 .

isn't a good omen.

Logging in at that login: prompt may reveal more about the device, as the serial log isn't a typical boot log.

WIkiDevi devices with QCA9557 -- to see if any are supported, to be used as a "place to start your DTS" and not to try to flash.

Appreciate your reply Jeff,

It turns out that there are quite a few devices running on similar hardware and it inspires to give it a try.

The same login prompt in UART CLI appears on SSH too, the issue is that the device is meant to be cloud controlled and configured remotely, so that there is no "reset to default" with username/password available anywhere. There is a reset procedure that can be done if it is connected to a network with management server.

The idea is to create an image that will load via TFTP and run from RAM, that will allow to dump current flash and will allow to perform some trial and error until everything else is figured out.
Is it possible to fetch any information from under Uboot before stock linux boots up? It should be possible to read flash without booting I guess and current flash layout is available in the boot log...

The device has 1 GE, 4 dual color LEDs, (I assume) 3 wireless interfaces, UART, unpopulated USB and additional unpopulated wired port. It is better to have it running without LEDs than trash it.

When it comes to boards, scripting and software builds I have no practical idea where to start and that is why I was wondering if someone has the time and will to walk me through.

An initramfs image is a good approach -- at least you're not writing to flash and can hopefully read from it.

I don't know how close the QCA9557 is to the QCA9556 or QCA9558. Getting the GPL drop for the device would be very helpful. It looks like Mojo Networks, or is it Airtight Networks, or it it Aruba, ... might be something of a challenge, but you might have some luck there. That is perhaps the easiest way to figure out how the device is wired up.

Hmm, don't know why I didn't get results before for supported devices with a QCA9557, but there are a bunch! is on the WikiDevi list, although listed as a QCA9558 on OpenWrt. That might provide some clues as well. I'd look at its DTS and others similar to craft as "safe" a one as you can.

flash_size passed from bootloader = 16
arg 1: console=ttyS0,115200
arg 2: root=31:03
arg 3: rootfstype=jffs2
arg 4: init=/sbin/init
arg 5: mtdparts=ath-nor0:256k(u-boot),128k(uboot-env),2048k(kernel),13888k(rootfs),64k(ART);ath-nor1:16M(opt)
arg 6: mem=128M
CPU revision is: 00019750 (MIPS 74Kc)
Determined physical RAM map:
 memory: 02000000 @ 00000000 (usable)
User-defined physical RAM map:
 memory: 08000000 @ 00000000 (usable)

So there's likely the partitioning of the 16 MB flash, and probably 128 MB of RAM.

The kernel command line (intentionally letting it wrap here)

Kernel command line: console=ttyS0,115200 root=31:03 rootfstype=jffs2 init=/sbin/init mtdparts=ath-nor0:256k(u-boot),128k(uboot-env),2048k(kernel),13888k(rootfs),64k(ART);ath-nor1:16M(opt) mem=128M


Memory: 112356k/131072k available (2199k kernel code, 18544k reserved, 586k data, 164k init, 0k highmem)

help confirm 128 MB of RAM.

The MTD partitioning indicates that there are two, 16 MB flash chips (physical or perhaps just logical) attached

Creating 5 MTD partitions on "ath-nor0":
0x000000000000-0x000000040000 : "u-boot"
0x000000040000-0x000000060000 : "uboot-env"
0x000000060000-0x000000260000 : "kernel"
0x000000260000-0x000000ff0000 : "rootfs"
0x000000ff0000-0x000001000000 : "ART"
1 cmdlinepart partitions found on MTD device ath-nor1
Creating 1 MTD partitions on "ath-nor1":
0x000001000000-0x000002000000 : "opt"

which might help narrow down "similar" devices that already run OpenWrt.

qca955x_GMAC lines look related to the Ethernet

ath_rate_atheros: Copyright (c) 2001-2005 Atheros Communications, Inc, All Rights Reserved
ath_dfs: Version 2.0.0
Copyright (c) 2005-2006 Atheros Communications, Inc. All Rights Reserved
ath_dev: Copyright (c) 2001-2007 Atheros Communications, Inc, All Rights Reserved
ath_ahb: (Atheros/multi-bss)

is probably the wireless portion on the "ahb" bus that QCA uses.

Here's some useful addresses and information related to the wireless chips

SC Callback Registration for wifi0
wifi0: Atheros ???: mem=0xb8100000, irq=2
ath_pci: (Atheros/multi-bss)
PCI device id is 003c :003c
ath_pci 0000:00:00.0: ath DEBUG: sc=0x86afcc00

Much of what follows looks like QCA-proprietary drivers and code bringing up the wireless and some tunnels.

The "crash trace" lets you see what kernel modules are in use

WARNING: at kernel/softirq.c:148 local_bh_enable+0x90/0xec()
Modules linked in:
ifb act_police act_mirred sch_htb sch_tbf sch_ingress cls_u32 ip6_gre ip6_tunnel tunnel6 iptable_WCMASK xt_CONNMARK xt_connmark iptable_PKT_MANGLE(P) nf_nat_pptp nf_nat_proto_gre nf_conntrack_pptp nf_conntrack_proto_gre iptable_CONTANALYTICS(P) ip_gre xt_physdev xt_mark ipt_MASQUERADE ipt_REDIRECT iptable_nat nf_nat_ftp nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT iptable_mangle iptable_filter ip_tables xt_conntrack xt_state nf_conntrack_ftp nf_conntrack nfnetlink_queue xt_tcpudp xt_multiport xt_mac xt_NFQUEUE xt_MARK x_tables nfnetlink reset_sensor(P) ath_pktlog(P) umac ath_dev(P) ath_dfs(P) ath_rate_atheros(P) ath_hal(P) asf(P) adf(P) broadcast_multicast_opt(P) led_driver(P) ipv6 athrs_gmac

Going back to the top

DRAM:  128 MB

cpu_pll_cfg: 0x21480  cpu_pll_dither: 0x3c103f
CFG_PLL_FREQ: 0x2  CFG_HZ: 360000000
CPU Clock: 720MHz    DDR Clock: 680MHz

Flash Manuf Id 0xc2, DeviceId0 0x20, DeviceId1 0x18
flash size 16MB, sector count = 256
flash-2 size 16MB, sector count = 256
Flash: 16 *2 MB

so that I should have caught earlier, but confirms the flash and RAM. Getting to the second flash chip "should be as easy as" adding a second CS and defining the partitions in the DTS. Hopefully they used the "standard" CS line, whatever pin it might be on.

Getting into U-Boot and finding out what options you have there would probably be a good idea, along with trying to guess that password.

I'm still puzzled by

## Booting image at 9f060000 ...
   Image Name:   Linux Kernel Image
   Created:      2019-04-17   7:00:31 UTC

but that gives you some ammo on getting the GPL source, as it was clearly within the last year

I have to correct myself in the first post - the hardware is slightly different, found this on
These are QCA9558-AT4A and QCA9882-BR4A married. Indeed 2 flash pieces MX25L12845EMI-10G (FLASH - NOR Memory IC 128Mb (16M x 8) SPI 104MHz 16-SOP) and single AR8035-A PHY...

1 Like
  • Going through the manuals on creating a new dts, using the info in TP-Link RE350K (exact same CPU/WI/PHY)...
    Used it as a template but removed "keys" section since device does not have any, changed flash mapping with addresses found in the original fw boot log (new addressing is longer). Not sure how to add the second memory chip - not familiar with the syntax so left it alone for now. Trying to create a ramdisk build - not much success - "make" returns syntax errors every time, blaming the created dts. Is there a comprehensive guide?
  • Requested sources from Arista (Airtight/Mojo), exchanging emails with their support.
  • Looking for a way to create a simple probe script to find out correct LED gpio addresses. (Send 1 blink to address 1, 2 blinks for address 2 etc...) and add it to the ramdisk image.
  • Looking for a way to create a flash dump when booted with ramdisk (what modules and tools need to be in the make .config and how to use them to get a full flash memory dump that can be readable and writable later?

I can for sure use some help on the dts creation. Any practical help or advise appreciated.

Since the device is cloud controlled, those images are generated by the controlling server (assumption) so every time any configuration is changed there is a new build with a new date. I have no access to such server. I did contact them with a code request but they are slow :non-potable_water:

With apologies for the terse response as I've got a long meeting coming up shortly:

I collected the DTS references I found useful on (ignore the link title, there's a lot more there now)

An important concept is that DTS files can add/override/delete what has already been included. Here's an example of one that I'm working on right now that deletes the non-existent NAND and changes the LED assignments:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT


#include "qca9531_glinet_gl-ar300m-nor.dts"

/ {
        compatible = "glinet,gl-ar300m-lite", "qca,qca9531";
        model = "GL.iNet GL-AR300M-Lite";

/delete-node/ &nand_flash;

// GL-AR300M-Lite has different LED colors than the non-Lite versions

&led_status {
        label = "gl-ar300m-lite:red:status";

&led_lan {
        label = "gl-ar300m-lite:green:lan";

&led_wlan {
        label = "gl-ar300m-lite:green:wlan";

Flash dump on a NOR device can be done with dd, which should be "stock".

Old-style (deprecated) sysfs export of GPIOs can be used to probe them, as could the newer "cdev" interface. The user-space utilities for the newer method are available as gpiod-tools. Somewhere there's a quick script that I saw that looped through GPIOs by by one, exported them, toggled them, then unexpored them.

Edit: Found it:

and posts following

Thanks for references, alot of reading there :smile:

I used TP-Link RE350K dts as example, corrected partitioning referencing original boot log from the first post, removed "keys" and "leds" to not touch any gpio before I know what it is, (blindly) corrected partition reference within eth0 section.
The addresses there are longer than ones found in the dts file, is it a problem?
There is still gpio reference in "mdio2" definition, is it a problem?
Is the "flash@1" definition done properly?
The plan is to first create a ramdisk image and try to explore and dump the flash, so are the partition names or mounts going to overlap?
This is what I have now, please have a look and tell me if I am on the right way and what should be done next... :slight_smile:

You might consider a Github Gist or Pastebin, as Google Docs is quite a challenge to retrieve from on a headless machine. Also, that file uses DOS line endings, at least from Google Docs.

You probably want to rename it to qca9558_mojo_c-65.dts so that it integrates with the build system, as well as setting the first compatible to "mojo,c-65"

Yes, removing the keys and leds nodes is probably a good idea to free up "unused" GPIOs for early testing. You'll need to remove the led-* aliases, as the label &power won't exist.

&mdio2 is probably needed for Ethernet, so I'd leave that there. Changes in "compex" systems' usage of GPIOs is reasonably rare for boards based on the same reference design. LEDs and switches are pretty common to meet layout needs.

Typo in partition@0 reg line

DTS partitions are start and size, so your partitions should be

  • 0x000000
  • 0x040000
  • 0x060000
  • 0x260000
  • 0xff0000

I'll let you do the math for the sizes

I wouldn't worry about the second flash for now. It will probably come down to changes in &spi, setting num-cs = <2>; and adding the second flash with reg = <1>; (Right now they are both on the same CS value.)


You'll also need to "wire it in" to the build system, probably in image/ Assuming that it doesn't need the TP-Link image format (and, for an initramfs image it won't matter), a "bare bones" version might look something like (check the image size so that you don't overwrite the ART partition)

define Device/mojo_c-65
  ATH_SOC := qca9558
  IMAGE_SIZE := 13760k
  DEVICE_TITLE := Mojo C-65
TARGET_DEVICES += mojo_c-65

I am not sure that creating a fork on GitHub was the right and easiest way to do it )) but that is first thing I was offered while browsing... :rofl:
Here is what I did qca9558_airtight_c-65.dts updated, updated, 02_Network updated, 11-ath10k-caldata updated... did I miss anything?

Might want to do the work on your own branch, as that makes things like

git diff master HEAD -- path/to/some/file

a lot easier, as well as rebasing when openwrt/master changes.

The ART cal-data location won't matter for now. It might be in the serial log (haven't checked) or can be deduced through hexdump -C /dev/mtnNro | less of the ART partition.

Change num-csat line 64 (and don't add the second one)

Change reg at 109 to <1> (otherwise both on the same logic level for the CS line)

Being conservative, I'd mark all partitions read-only for now. Once you have confidence that you've can read from them, easy enough to open up the ones you might want to write later in another build.

The indenting of flash@1 is off, making it hard for me to tell if the braces are properly matched. Maybe it's just line 107.

Shoot, tweak those and give it a build, see what happens!

I add my .config the following to save time and space (since I've got 5-10 build trees on my machine)


BUILD_LOG will let you check logs/target/linux/install.txt for example, when things don't go as expected, without having to rerun with V=s

I also use a git repo in ./env/ and link ./env/dot.config to ./.config and ./env/files/ to .files

git worktree for multiple build trees is great for me, but probably more than you need for now.


As I just reminded myself the hard way

	num-cs = <2>;
	cs-gpios = <0>, <0>;

is what is probably needed to resolve

[    0.384209] ath79-spi 1f000000.spi: cs1 >= max 1
[    0.389049] spi_master spi0: spi_device register error /ahb/spi@1f000000/flash@1
[    0.396688] spi_master spi0: Failed to create SPI device for /ahb/spi@1f000000/flash@1
1 Like

Built and loaded... lots of issues for now, one of them is that my CLI is read-only (prolific issues) so will need to add something to the build so that ssh/scp works out of the box... :slight_smile:


The first things that caught my eye were:

[    0.556139] m25p80 spi0.1: unrecognized JEDEC id bytes: 00, 00, 00
[    0.562430] m25p80: probe of spi0.1 failed with error -2

That's the probe for the second chip, likely getting nothing back when the "Read ID" command was sent. I'd leave that for now.

[    0.568505] libphy: GPIO Bitbanged MDIO: probed
[    0.573329] mdio_bus gpio-0: MDIO device at address 4 is missing.
[    0.579904] libphy: Fixed MDIO Bus: probed
[    0.923652] ag71xx 19000000.eth: Could not connect to PHY device

Those are clues on getting the Ethernet to work. It looks like the phy part isn't answering. Ethernet on SoCs often consists of a MAC, which controls the logical part of the protocols, and a phy, which handles the "wires" -- which may be part of a switch chip, discrete or integral with the SoC. Poking through your "reference" DTS and perhaps some similar ones might help in figuring out what you're missing.

Does it have USB? That is another way to get data off a device without the pain of base64 encoding or the like.

jeff@deb-devel:~/devel/openwrt/target/linux/ath79/dts$ fgrep ethernet-phy * | cut -d ':' -f 3 | sort | uniq -c
     39  ethernet-phy@0 {
      3  ethernet-phy@1 {
      1  ethernet-phy@2 {
     23  ethernet-phy@4 {
      2  ethernet-phy@5 {
      1  ethernet-phy@c {

I'd be trying 0 next :wink:

Yepp, that is something!

In the start of the boot process PHY is brought up as device 5... Should I change the MDIO to 5 for phy0 definition in the dts?

phy0: ethernet-phy@5 {
			reg = <5>;

Besides, the CLI is suppressed by the prompt "To activate this console..." and there is only one Ethernet port on the device itself, how to make it answer to SSH out of the box so that I will have SSH/SCP? Is it available through "make menuconfig" and what needs to be there for that to work?
No USB :frowning:

1 Like