liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

default.nix (7809B)


      1 {
      2   system = {
      3     crossSystem = {
      4       config = "mips-unknown-linux-musl";
      5       gcc = {
      6         abi = "32";
      7         arch = "24kc";          # maybe mips_24kc-
      8       };
      9     };
     10   };
     11 
     12   description = ''
     13     GL.iNet GL-AR750
     14     ****************
     15 
     16     Hardware summary
     17     ================
     18 
     19     The GL-AR750 "Creta" travel router features:
     20 
     21      - QCA9531 @650Mhz SoC
     22      - dual band wireless: IEEE 802.11a/b/g/n/ac
     23      - two 10/100Mbps LAN ports and one WAN
     24      - 128MB DDR2 RAM
     25      - 16MB NOR Flash
     26      - supported in OpenWrt by the "ath79" SoC family
     27 
     28     The GL-AR750 has two distinct sets of wifi hardware. The 2.4GHz
     29     radio is part of the QCA9531 SoC, i.e. it's on the same silicon as
     30     the CPU, the Ethernet, the USB etc. The device is connected to the
     31     host via `AHB <https://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture>`_ and it is
     32     supported in Linux using the ath9k driver. 5GHz wifi
     33     is provided by a QCA9887 PCIe (PCI embedded) WLAN chip,
     34     supported by the ath10k driver.
     35 
     36     Installation
     37     ============
     38 
     39     As with many GL.iNet devices, the stock vendor firmware
     40     is a fork of OpenWrt, meaning that the binary created by
     41     :ref:`system-outputs-mtdimage` can be flashed using the
     42     vendor web UI or the U-Boot emergency "unbrick" routine.
     43 
     44     For flashing from an existing Liminix system (we believe that) it
     45     is necessary to first boot into a :ref:`system-outputs-kexecboot`
     46     system, otherwise you'll be overwriting flash partitions while
     47     they're in use - and that might not end well.
     48 
     49     Vendor web page: https://www.gl-inet.com/products/gl-ar750/
     50 
     51     OpenWrt web page: https://openwrt.org/toh/gl.inet/gl-ar750
     52 
     53   '';
     54 
     55   module = {pkgs, config, lim, ... }:
     56     let
     57       openwrt = pkgs.openwrt;
     58       firmwareBlobs = pkgs.pkgsBuildBuild.fetchFromGitHub {
     59         owner = "kvalo";
     60         repo = "ath10k-firmware";
     61         rev = "5d63529ffc6e24974bc7c45b28fd1c34573126eb";
     62         sha256 = "1bwpifrwl5mvsmbmc81k8l22hmkwk05v7xs8dxag7fgv2kd6lv2r";
     63       };
     64       firmware = pkgs.stdenv.mkDerivation {
     65         name = "wlan-firmware";
     66         phases = ["installPhase"];
     67         installPhase = ''
     68           mkdir -p $out/ath10k/QCA9887/hw1.0/
     69           blobdir=${firmwareBlobs}/QCA9887/hw1.0
     70           cp $blobdir/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00047 $out/ath10k/QCA9887/hw1.0/firmware-5.bin
     71           cp $blobdir/board.bin  $out/ath10k/QCA9887/hw1.0/
     72         '';
     73       };
     74       mac80211 = pkgs.kmodloader.override {
     75         targets = ["ath9k" "ath10k_pci"];
     76         inherit (config.system.outputs) kernel;
     77         dependencies = [ ath10k_cal_data ];
     78       };
     79       ath10k_cal_data =
     80         let
     81           offset = lim.parseInt "0x5000";
     82           size = lim.parseInt "0x844";
     83         in pkgs.liminix.services.oneshot rec  {
     84           name = "ath10k_cal_data";
     85           up = ''
     86             part=$(basename $(dirname $(grep -l art /sys/class/mtd/*/name)))
     87             echo ART partition is ''${part-unset}
     88             test -n "$part" || exit 1
     89             (in_outputs ${name}
     90              dd if=/dev/$part of=data iflag=skip_bytes,fullblock bs=${toString size} skip=${toString offset} count=1
     91             )
     92         '';
     93       };
     94       inherit (pkgs.pseudofile) dir symlink;
     95       inherit (pkgs.liminix.networking) interface;
     96     in {
     97       imports = [
     98         ../../modules/network
     99         ../../modules/arch/mipseb.nix
    100         ../../modules/outputs/tftpboot.nix
    101         ../../modules/outputs/mtdimage.nix
    102         ../../modules/outputs/jffs2.nix
    103       ];
    104 
    105       programs.busybox.options = {
    106         FEATURE_DD_IBS_OBS = "y"; # ath10k_cal_data needs skip_bytes,fullblock
    107       };
    108       hardware = {
    109         defaultOutput = "mtdimage";
    110         loadAddress = lim.parseInt "0x80060000";
    111         entryPoint = lim.parseInt "0x80060000";
    112         flash = {
    113           address = lim.parseInt "0x9F060000";
    114           size = lim.parseInt "0xfa0000";
    115           eraseBlockSize = 65536;
    116         };
    117         rootDevice = "/dev/mtdblock5";
    118         dts = {
    119           src = "${openwrt.src}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
    120           includes =  [
    121             "${openwrt.src}/target/linux/ath79/dts"
    122           ];
    123         };
    124 
    125         networkInterfaces =
    126           let inherit (config.system.service.network) link;
    127           in {
    128             lan = link.build { ifname = "eth0"; };
    129             wan = link.build { ifname = "eth1"; };
    130             wlan = link.build {
    131               ifname = "wlan0";
    132               dependencies = [ mac80211 ];
    133             };
    134             wlan5 = link.build {
    135               ifname = "wlan1";
    136               dependencies = [ ath10k_cal_data mac80211  ];
    137             };
    138           };
    139       };
    140       filesystem = dir {
    141         lib = dir {
    142           firmware = dir {
    143             ath10k = dir {
    144               QCA9887 = symlink "${firmware}/ath10k/QCA9887";
    145               "cal-pci-0000:00:00.0.bin" = symlink "${ath10k_cal_data}/.outputs/data";
    146             };
    147           };
    148         };
    149       };
    150       boot.tftp = {
    151         loadAddress = lim.parseInt "0x00A00000";
    152       };
    153       kernel = {
    154         src = pkgs.pkgsBuildBuild.fetchurl {
    155           name = "linux.tar.gz";
    156           url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.137.tar.gz";
    157           hash = "sha256-PkdzUKZ0IpBiWe/RS70J76JKnBFzRblWcKlaIFNxnHQ=";
    158         };
    159 
    160         # Mainline linux 5.19 doesn't have device-tree support for
    161         # this device or even for the SoC, so we use the extensive
    162         # OpenWrt kernel patches
    163         extraPatchPhase = ''
    164           ${openwrt.applyPatches.ath79}
    165           sed -i.bak -e '\,include <linux/hw_random.h>,a #include <linux/gpio/driver.h>'  drivers/net/wireless/ath/ath9k/ath9k.h # context reqd for next patch
    166           patch -p1 <  ${openwrt.src}/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch
    167         '';
    168 
    169         config = {
    170           ATH79 = "y";
    171           PCI = "y";
    172           PCI_AR724X = "y";
    173 
    174           SERIAL_8250_CONSOLE = "y";
    175           SERIAL_8250 = "y";
    176           SERIAL_CORE_CONSOLE = "y";
    177 
    178           # need this to open console device at boot. dmesg goes from
    179           # [    0.272934] Warning: unable to open an initial console.
    180           # to
    181           # [    0.247413] printk: console [ttyS0] disabled
    182           # [     0.25200] 18020000.uart: ttyS0 at MMIO 0x1802000 (irq = 10, base_baud = 1562500) is a 16550A
    183           SERIAL_OF_PLATFORM = "y";
    184 
    185           CONSOLE_LOGLEVEL_DEFAULT = "8";
    186           CONSOLE_LOGLEVEL_QUIET = "4";
    187 
    188           NET = "y";
    189           ETHERNET = "y";
    190           NET_VENDOR_ATHEROS = "y";
    191           AG71XX = "y";             # ethernet (qca,qca9530-eth)
    192           MFD_SYSCON = "y";         # ethernet (compatible "syscon")
    193           AR8216_PHY = "y";         # eth1 is behind a switch
    194 
    195           MTD_SPI_NOR = "y";
    196 
    197           SPI_ATH79 = "y";      # these are copied from OpenWrt.
    198           SPI_MASTER= "y";      # At least one of them is necessary
    199           SPI_MEM= "y";
    200           SPI_AR934X= "y";
    201           SPI_BITBANG= "y";
    202           SPI_GPIO= "y";
    203 
    204           GPIO_ATH79 = "y";
    205           GPIOLIB = "y";
    206           EXPERT="y";
    207           GPIO_SYSFS = "y"; # required by patches-5.15/0004-phy-add-ath79-usb-phys.patch
    208           OF_GPIO = "y";
    209           SYSFS = "y";
    210           SPI = "y";
    211           MTD = "y";
    212           MTD_BLOCK = "y";          # fix undefined ref to register_mtd_blktrans_devs
    213 
    214           WATCHDOG = "y";
    215           ATH79_WDT = "y";  # watchdog timer
    216 
    217           EARLY_PRINTK = "y";
    218 
    219           PRINTK_TIME = "y";
    220         };
    221         conditionalConfig = {
    222           WLAN = {
    223             WLAN_VENDOR_ATH = "y";
    224             ATH_COMMON = "m";
    225             ATH9K = "m";
    226             ATH9K_AHB = "y";
    227             ATH10K = "m";
    228             ATH10K_PCI = "m";
    229             ATH10K_DEBUG = "y";
    230           };
    231         };
    232       };
    233     };
    234 }