Close

Drivers, Drivers, Drivers!

A project log for Mackerel-68k Linux SBCs

Homebrew Motorola 68k single-board computers running mainline Linux

colin-maykishColin Maykish 05/31/2026 at 21:580 Comments

Mackerel-30 is actually shaping up to be a real Linux machine! I've spent a bunch of time recently building out drivers for all the hardware on the board. It now has persistent storage, a fully implemented serial port, and even networking. I'm pleased that none of the minor design problems with the first prototype PCB have prevented any of this work. Despite the shortcomings, Mackerel-30 (as well as my understanding of Linux kernel development) is progressing really well.

IDE

Mackerel-10 has a functional IDE driver in uClinux, but it's pretty bare bones and built on the older Linux kernel driver API. With Mackerel-30, I was able to implement the IDE interface on top of the more modern libata framework. The idea is still the same - tell the kernel about the memory-mapped registers and setup the proper interrupt lines. The lovely thing about Linux is that once you have the foundational layer working, you get all of the things above it for free. One IDE driver gets you block devices, filesystems, fdisk and other tools without any additional code.

Speaking of IDE, I made a few tweaks to the bootloader IDE/FAT code that reduced the load time of the kernel image from 20 seconds to about 17. That's fine, but hardly noticeable in practice. The massive gains came from enabling the 68030's instruction cache before starting the IDE load command. This change alone dropped the time under 5 seconds for a 5MB kernel file. That's over 1 MB/s! Doing the math, there's still some performance on the table, but I don't think it's really worth the time to rewrite the IDE code in assembly.

PPP

I took a short detour to set up what turned out to be a terrible first network connection for Mackerel-30. PPP is a point-to-point protocol for handling network traffic over a simple serial port. I patched up the XR68C681 driver to handle the second port on the DUART and implement proper baud selection logic. With that in place, there's a config in the kernel to enable the protocol and then a simple cross-compile of the pppd binary itself.

The second serial port (/dev/ttyXR1) is connected to my Linux PC, pppd is started on both ends. Tada! Network connection...

~ # pppd /dev/ttyXR1 9600 noauth local nodetach 10.0.0.2:10.0.0.1 &
Using interface ppp0
Connect: ppp0 <--> /dev/ttyXR1
local  IP address 10.0.0.2
remote IP address 10.0.0.1
~ # ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1): 56 data bytes
64 bytes from 10.0.0.1: seq=0 ttl=64 time=210.000 ms
64 bytes from 10.0.0.1: seq=1 ttl=64 time=210.000 ms

This is extremely limited out of the box. The host PC and the Mackerel board can both ping eachother, but that's about it, not to mention the baud rate limit. I was only able to get the connection stable at 9600 bps.

It's also possible to set up routing, iptables, and DNS and I did actually get Mackerel pinging the external internet, but this whole exercise was more of a proof-of-concept of the Linux networking stack on Mackerel than a practical result. Still fun to see though!

SPI + ENC28J60 Networking

DUART GPIO <-> level shifter <-> ENC28J60 ethernet

And now for the fun one... There are so many peripherals that communicate over SPI. Having that interface available on the board opens up a world of options for connectivity, storage, sensors, etc.

The only problem is that nothing on Mackerel-30 actually speaks SPI right now. Fortunately, Linux has a really solid bitbang SPI controller that can be easily implemented on top of just about any GPIO. I wired up the SPI code to the DUART I/O registers and, as with the IDE driver, every layer above it just falls into place.

The cheap ENC28J60-based ethernet breakout board I have requires only a SPI connection plus a single interrupt line. There's a driver already available in the Linux kernel and it's one config option away.

~ # uname -a
Linux mackerel 6.17.1-multi-00028-g5b42c9f55f18-dirty #1 Mon May 25 11:28:54 EDT 2026 m68k GNU/Linux
~ # ping -c 4 google.com
PING google.com (142.250.65.78): 56 data bytes
64 bytes from 142.250.65.78: seq=0 ttl=119 time=110.000 ms
64 bytes from 142.250.65.78: seq=1 ttl=119 time=120.000 ms
64 bytes from 142.250.65.78: seq=2 ttl=119 time=120.000 ms
64 bytes from 142.250.65.78: seq=3 ttl=119 time=120.000 ms

--- google.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 110.000/117.500/120.000 ms
~ # wget http://example.com
Connecting to example.com (172.66.147.243:80)
saving to 'index.html'
index.html           100% |********************************|   528  0:00:00 ETA
'index.html' saved
~ # cat index.html 
<!doctype html><html lang="en"><head><title>Example Domain</title><meta name="viewport" content="width=device-width, initial-scale=1"><style>body{background:#eee;width:60vw;margin:15vh auto;font-family:system-ui,sans-serif}h1{font-size:1.5em}div{opacity:0.8}a:link,a:visited{color:#348}</style></head><body><div><h1>Example Domain</h1><p>This domain is for use in documentation examples without needing permission. Avoid use in operations.</p><p><a href="https://iana.org/domains/example">Learn more</a></p></div></body></html>

Mackerel-30 is online (for real this time)! There are some caveats... Because the underlying SPI controller is bitbanged by the CPU, when network traffic is happening, the CPU is pegged at 100%. There is noticeable lag in the console at that point. The good news is that because the driver is interrupt driven and not polling-based, the CPU is only bottlenecked when it's actually handling network activity, not constantly.

There's also the issue of throughput. Again, as a consequence of the bitbang overhead, download speeds are around 5 KB/s. Not amazing, but a significant upgrade from the PPP network. It's enough that basic network activity like downloading text files is practical. I was hoping to set up ssh/scp as an alternative to pulling the CF card every time I need to transfer new binaries, but it's too slow for that.

Regardless, this feels much more like a real ethernet connection. For one thing, it's not tethered to my PC like with PPP - it can run independently. Ultimately, when I do implement a SPI controller in hardware, all I have to do is swap out the bitbang implementation for a real one and the speed should go through the roof while also freeing up the CPU load dramatically.

Next Steps

I have a few more items on the board bring-up checklist including validating the FPU and the expansion header. I've started thinking about the next PCB revision for Mackerel-30. There is a short list of known issues and optimizations that I can fix right now, but I do want to spend some time designing a SPI controller in hardware.
If I can find the board real estate, my ideal next version would include a third CPLD that acts not just as a SPI master, but as a sort of general I/O controller. Having a bunch of SPI, I2C, and GPIO in hardware would be amazing. Maybe it makes more sense to put all this on an expansion card instead. I'll have to think about it.

Discussions