Merge branch 'pr-13/helios-4/wiki_update'

This commit is contained in:
Gauthier Provost 2019-02-28 16:27:56 +08:00
commit ce7ca6fecb
15 changed files with 482 additions and 15 deletions

View File

@ -1,9 +1,13 @@
# Armbian
Debian based Linux for ARM based single-board computers
Debian & Ubuntu based Linux for ARM based single-board computers
[https://www.armbian.com](https://www.armbian.com "Armbian")
## Pre-built images
You can find pre-built **Armbian** images for Helios4 on our [Download](/download) page or directly on [Armbian website](https://dl.armbian.com/helios4/).
## How to build an image or a kernel?
Supported build environment is **Ubuntu Bionic 18.04 x64** ([minimal iso image](http://archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/mini.iso)).

Binary file not shown.

View File

@ -0,0 +1,23 @@
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts
index 705adfa8c..d5afbfc53 100644
--- a/arch/arm/boot/dts/armada-388-helios4.dts
+++ b/arch/arm/boot/dts/armada-388-helios4.dts
@@ -84,6 +84,18 @@
};
};
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&microsom_phy0_int_pins>;
+
+ wol {
+ label = "Wake-On-LAN";
+ linux,code = <KEY_WAKEUP>;
+ gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+ };
+
io-leds {
compatible = "gpio-leds";
sata1-led {

View File

@ -0,0 +1,90 @@
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 661c5a38f..a25d61d54 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -38,6 +38,7 @@
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
@@ -133,7 +134,7 @@ struct mvebu_gpio_chip {
struct regmap *regs;
u32 offset;
struct regmap *percpu_regs;
- int irqbase;
+ int bank_irq[4];
struct irq_domain *domain;
int soc_variant;
@@ -608,6 +609,33 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * @return This function returns 0 on success.
+ */
+static int mvebu_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ int irq;
+ int bank;
+
+ bank = d->hwirq % 8;
+ irq = mvchip->bank_irq[bank];
+
+ if (enable)
+ enable_irq_wake(irq);
+ else
+ disable_irq_wake(irq);
+
+ return 0;
+}
+
/*
* Functions implementing the pwm_chip methods
*/
@@ -1277,7 +1305,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
err = irq_alloc_domain_generic_chips(
mvchip->domain, ngpios, 2, np->name, handle_level_irq,
- IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
+ IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, IRQ_GC_INIT_NESTED_LOCK);
if (err) {
dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
mvchip->chip.label);
@@ -1295,6 +1323,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
ct->chip.name = mvchip->chip.label;
ct = &gc->chip_types[1];
@@ -1303,6 +1333,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
ct->handler = handle_edge_irq;
ct->chip.name = mvchip->chip.label;
@@ -1318,6 +1350,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
continue;
irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
mvchip);
+ mvchip->bank_irq[i] = irq;
}
/* Some MVEBU SoCs have simple PWM support for GPIO lines */

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/img/wol/schematic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -185,11 +185,11 @@ INTERVAL=10
DEVPATH=hwmon2=devices/platform/j10-pwm hwmon3=devices/platform/j17-pwm hwmon4=devices/platform/soc/soc:internal-regs/f1011000.i2c/i2c-0/0-004c
DEVNAME=hwmon1=armada_thermal
FCTEMPS=hwmon2/pwm1=hwmon1/temp1_input hwmon3/pwm1=hwmon1/temp1_input
MINTEMP=hwmon2/pwm1=70 hwmon3/pwm1=70
MAXTEMP=hwmon2/pwm1=90 hwmon3/pwm1=90
MINTEMP=hwmon2/pwm1=60 hwmon3/pwm1=60
MAXTEMP=hwmon2/pwm1=80 hwmon3/pwm1=80
MINSTART=hwmon2/pwm1=20 hwmon3/pwm1=20
MINSTOP=hwmon2/pwm1=29 hwmon3/pwm1=29
MINPWM=0
MINPWM=20
```
INTERVAL

View File

@ -9,7 +9,7 @@ By default, Helios4 is configured to boot from microSD card. To boot from SPI NO
Refer to [U-Boot](/uboot) page to build the image.
*A prebuilt SPI image of U-Boot 2013.01 for Armbian OS can be downloaded from [here](/files/uboot/u-boot-armbian-2013.01-spi.bin).*
*A prebuilt SPI image of U-Boot for Armbian OS can be downloaded from [here (version 2013.01)](/files/uboot/u-boot-armbian-2013.01-spi.bin) or from [here (version 2018.11)](/files/uboot/u-boot-armbian-2018.11-spi.bin).*
## Write U-Boot to SPI NOR flash
@ -40,19 +40,62 @@ mmcblk0 179:0 0 14.9G 0 disk
└─mmcblk0p1 179:1 0 14.8G 0 part /
```
4) Run **nand-sata-install** utility
4) Get the U-Boot SPI image
***A. Install/Update U-Boot package from Armbian***
```
sudo apt-get update
sudo apt-get -y install linux-u-boot-helios4-next
```
***B. Download the Prebuilt Image from Wiki***
*U-Boot 2018.11*
```
wget https://wiki.kobol.io/files/uboot/u-boot-armbian-2018.11-spi.bin
sudo mv u-boot-armbian-2018.11-spi.bin /usr/lib/linux-u-boot-next-helios4_*/u-boot.flash
```
*Marvell U-Boot 2013.01*
```
wget https://wiki.kobol.io/files/uboot/u-boot-armbian-2013.01-spi.bin
sudo mv u-boot-armbian-2013.01-spi.bin /usr/lib/linux-u-boot-next-helios4_*/u-boot.flash
```
***C. Custom U-Boot SPI Image***
Upload the U-Boot SPI binary that you built on your PC to Helios4 and rename it as **u-boot.flash**.
For example, if the Helios4 IP address is 10.10.10.1 the command would be:
```
scp u-boot-spl.kwb root@10.10.10.1:/usr/lib/linux-u-boot-next-helios4_*/u-boot.flash
```
!!! note
Replace **u-boot-spl.kwb** with **u-boot-a38x-*-spi.bin** if you are using Marvell U-Boot 2013.01
5) Run **nand-sata-install** utility
```
sudo nand-sata-install
```
5) Select option **Install/Update the bootloader on SPI Flash**
6) Select option **Install/Update the bootloader on SPI Flash**
6) If you want to take the opportunity to move your RootFS to another device, jump to this [section](#moving-rootfs-to-other-device). Otherwise you may disable spi_workaround in /boot/armbianEnv.txt
![Install Bootloader menu](/img/spi/armbian_install_u-boot_menu.png)
And confirm the operation
![Bootloader write confirmation](/img/spi/armbian_install_u-boot_write_confirmation.png)
7) If you want to take the opportunity to move your RootFS to another device, jump to this [section](#moving-rootfs-to-other-device). Otherwise you may disable spi_workaround in /boot/armbianEnv.txt
`spi_workaround=off`
7) Set DIP switches **SW1** to SPI Boot and reboot the system.
8) Set DIP switches **SW1** to SPI Boot and reboot the system.
![Boot from SPI](/img/spi/dipswitch_boot_spinor.png)
@ -74,7 +117,7 @@ sudo wget https://wiki.kobol.io/files/uboot/boot_spi_en.scr -O /boot/boot_spi_en
3) Switch to Helios4 serial console, then reboot the system
```
sudo Reboot
sudo reboot
```
4) Press any key to cancel the U-Boot autoboot and execute these commands
@ -113,6 +156,37 @@ BootROM - 1.73
Booting from SPI flash
```
### Under U-Boot
!!! info
You will need to access to Helios4 via Serial Console. Please refer to [Install](/install/#step-4-connect-to-helios4-serial-console) page for instructions.
1) Upload the U-Boot SPI binary to /boot folder on Helios4 and rename it as **u-boot-spi.bin**.
For example, if the Helios4 IP address is 10.10.10.1 the command would be:
```
scp u-boot-spl.kwb root@10.10.10.1:/boot/u-boot-spi.bin
```
2) Switch to Helios4 serial console, login then reboot the system
```
sudo reboot
```
3) Press any key to cancel the U-Boot autoboot and execute these commands
```
load mmc 0:1 ${loaddaddr} /boot/u-boot-spi.bin
sf probe
sf erase 0 100000
sf write ${loadaddr} 0 ${filesize}
reset
```
4) Helios4 would reboot and boot to existing operating system.
## Set Up U-Boot Environment
!!! important
@ -159,6 +233,10 @@ sudo nand-sata-install
3) Select option **Boot from SPI - system on SATA, USB or NVMe**
![Move RootFS menu](/img/spi/armbian_move_rfs_menu.png)
And follow the on screen instructions.
4) When RootFS migration is done, disable spi_workaround.
5) Set DIP switches **SW1** to SPI Boot and reboot the system.

View File

@ -185,3 +185,81 @@ it would produced *u-boot-a38x-**mm**-**d**-mmc.bin* whereas **mm** is month and
it would produced *u-boot-a38x-**mm**-**d**-spi.bin* whereas **mm** is month and **d** is day. For example, building u-boot on October 2nd would produced
*u-boot-a38x-10-2-spi.bin*
## Write U-Boot to Boot Device
### MicroSD Card
!!! note
Replace **u-boot-spl.kwb** with **u-boot-a38x-*-mmc.bin** in command below if you are using Marvell U-Boot 2013.01
#### On Development PC
1) Put SD card to Memory Card Reader
2) Write U-Boot image (u-boot-spl.kwb) to Memory Card Reader (eg. /dev/sdc) and reboot
```
sudo dd if=u-boot-spl.kwb of=/dev/sdc bs=512 seek=1 status=noxfer
sudo sync
```
3) Remove the SD card and put it to Helios4.
#### Live System - Under Armbian
1) Upload the U-Boot SPI binary that you built on your PC to Helios4 and rename it as **u-boot.mmc**.
```
scp u-boot-spl.kwb root@10.10.10.1:/usr/lib/linux-u-boot-next-helios4_*/u-boot.mmc
```
2) SSH to Helios4
```
ssh root@10.10.10.1
```
3) Run **nand-sata-install** utility
```
sudo nand-sata-install
```
4) Select option **Install/Update the bootloader on SD/eMMC**
![armbian install bootloader menu](/img/u-boot/armbian_install_bootloader_sdcard_menu.png)
5) Confirm the operation
![armbian bootloader write confirmation](/img/u-boot/armbian_install_bootloader_sdcard_write_confirmation.png)
6) Reboot the system
#### Live System - Generic Linux
1) Transfer U-Boot image into home folder in Helios4 using scp
```
scp u-boot-spl.kwb root@10.10.10.1:~/
```
2) SSH to Helios4
```
ssh root@10.10.10.1
```
3) Write U-Boot image (u-boot-spl.kwb) to SD Card device (/dev/mmcblk0) and reboot
```
sudo dd if=u-boot-spl.kwb of=/dev/mmcblk0 bs=512 seek=1 status=noxfer
sudo reboot
```
### SPI NOR Flash
Please refer to instructions in [SPI (NOR flash) page](/spi/#write-u-boot-to-spi-nor-flash).

193
docs/wol.md Normal file
View File

@ -0,0 +1,193 @@
![Ethernet PHY](/img/wol/schematic.png)
The Armada 388 SoC provides several trigger options from different peripherals to wake up the system out of power save modes. Some of the options are:
* Wake on GPIO
* Wake on LAN
Currently Helios4 uses the PHY interrupt and 'Wake on GPIO' event to implement Wake-on-LAN.
## Device Tree Support
Linux provides gpio-keys driver to handle GPIO event and can be configured as wakeup source.
```
gpio-keys {
compatible = "gpio-keys";
pinctrl-0 = <&microsom_phy0_int_pins>;
wol {
label = "Wake-On-LAN";
linux,code = <KEY_WAKEUP>;
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
wakeup-source;
};
};
```
Device Tree Patch can be found [here](/files/wol/helios4-dts-add-wake-on-lan-support.patch).
## Kernel Patch
Current gpio-mvebu driver does not implement [irq_set_wake()](https://www.kernel.org/doc/html/v4.14/core-api/genericirq.html?highlight=irq_set_wake#c.irq_chip)
to support GPIO as wakeup source and properly route it to upper interrupt controller (Arm GIC).
This will raise following issues:
- System unable to wake up from Suspend-to-RAM
- System wake up from GPIO interrupts not defined as wakeup source
- Kernel crash during wakeup from standby
```
[ 59.169436] ------------[ cut here ]------------
[ 59.174075] WARNING: CPU: 0 PID: 1535 at kernel/irq/manage.c:623 irq_set_irq_wake+0xe4/0x11c
[ 59.182533] Unbalanced IRQ 50 wake disable
[ 59.186638] Modules linked in: lz4hc lz4hc_compress marvell_cesa zram zsmalloc lm75 pwm_fan ip_tables x_tables
[ 59.196690] CPU: 0 PID: 1535 Comm: bash Not tainted 4.14.94-mvebu+ #14
[ 59.203234] Hardware name: Marvell Armada 380/385 (Device Tree)
[ 59.209183] [<c01118d0>] (unwind_backtrace) from [<c010c7cc>] (show_stack+0x10/0x14)
[ 59.216955] [<c010c7cc>] (show_stack) from [<c095091c>] (dump_stack+0x88/0x9c)
[ 59.224204] [<c095091c>] (dump_stack) from [<c012ab9c>] (__warn+0xe8/0x100)
[ 59.231188] [<c012ab9c>] (__warn) from [<c012abfc>] (warn_slowpath_fmt+0x48/0x6c)
[ 59.238696] [<c012abfc>] (warn_slowpath_fmt) from [<c017bb64>] (irq_set_irq_wake+0xe4/0x11c)
[ 59.247160] [<c017bb64>] (irq_set_irq_wake) from [<c0747594>] (gpio_keys_resume+0xb0/0x11c)
[ 59.255537] [<c0747594>] (gpio_keys_resume) from [<c0654b34>] (dpm_run_callback+0x54/0xec)
[ 59.263826] [<c0654b34>] (dpm_run_callback) from [<c0655180>] (device_resume+0xcc/0x270)
[ 59.271941] [<c0655180>] (device_resume) from [<c0656660>] (dpm_resume+0x100/0x230)
[ 59.279621] [<c0656660>] (dpm_resume) from [<c06569e4>] (dpm_resume_end+0xc/0x18)
[ 59.287128] [<c06569e4>] (dpm_resume_end) from [<c0175af8>] (suspend_devices_and_enter+0x210/0x5e0)
[ 59.296202] [<c0175af8>] (suspend_devices_and_enter) from [<c01761c0>] (pm_suspend+0x2f8/0x380)
[ 59.304927] [<c01761c0>] (pm_suspend) from [<c0174a30>] (state_store+0x70/0xcc)
[ 59.312260] [<c0174a30>] (state_store) from [<c02c80e4>] (kernfs_fop_write+0xe8/0x1c4)
[ 59.320204] [<c02c80e4>] (kernfs_fop_write) from [<c024ce78>] (vfs_write+0xa4/0x1b4)
[ 59.327972] [<c024ce78>] (vfs_write) from [<c024d0b4>] (SyS_write+0x4c/0xac)
[ 59.335045] [<c024d0b4>] (SyS_write) from [<c0108620>] (ret_fast_syscall+0x0/0x54)
[ 59.342633] ---[ end trace c725de247edb5ce9 ]---
[ 59.474369] ata2: SATA link down (SStatus 0 SControl 300)
[ 59.474443] ata3: SATA link down (SStatus 0 SControl 300)
[ 59.638619] ata1: SATA link down (SStatus 0 SControl 300)
[ 59.647170] ata4: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
[ 60.081905] ata1: SATA link down (SStatus 0 SControl 300)
[ 60.087343] ata1: limiting SATA link speed to 1.5 Gbps
[ 60.386518] mvneta f1070000.ethernet eth0: Link is Down
[ 60.578411] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 310)
[ 61.162892] ata4.00: configured for UDMA/100
[ 62.431232] mvneta f1070000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
[ 63.087435] ata1.00: configured for UDMA/100
[ 63.159889] OOM killer enabled.
[ 63.164643] Restarting tasks ... done.
[ 63.181059] PM: suspend exit
```
To fix the issue, gpio-mvebu driver needs to be patched to implement [irq_set_wake()](https://www.kernel.org/doc/html/v4.14/core-api/genericirq.html?highlight=irq_set_wake#c.irq_chip)
and only enable interrupt on GPIO defined as wakeup source.
Patch for Linux Kernel 4.14.x can be found [here](/files/wol/lk4.14-mvebu-gpio-add_wake_on_gpio_support.patch)
## Enabling WOL
Enable the PHY to raise an interrupt when magic packet received :
```
sudo ethtool -s eth0 wol g
```
To make it permanent, create the following file */etc/systemd/system/wol@.service* and copy the following:
```
[Unit]
Description=Wake-on-LAN for %i
Requires=network.target
After=network.target
[Service]
ExecStart=/sbin/ethtool -s %i wol g
Type=oneshot
[Install]
WantedBy=multi-user.target
```
Then enable the service for **eth0**
```
systemctl enable wol@eth0
```
## Suspend System
Use **systemctl** command to put your system in suspend mode.
```
sudo systemctl suspend
```
!!! important
Only execute this command after enabling WOL otherwise there is a risk that Helios4 will not wake up when receiving magic packet. More explanation regarding this issue on [here](/wol/#unexpected-packet).
## Wake up System
To wake up your suspended Helios4 you need to send it a magic packet from a machine on the same network.
Before putting Helios4 in suspend mode, you need to know its MAC address. Use **ip link** command. In example below the MAC address is *02:fc:e7:3d:b8:c8*.
```
ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 532
link/ether 02:fc:e7:3d:b8:c8 brd ff:ff:ff:ff:ff:ff
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
```
From a Linux machine (running Debian/Ubuntu) on the same network :
1. Install **wakeonlan** tool
```
sudo apt-get install wakeonlan
```
2. Send magic packet
```
sudo wakeonlan 02:fc:e7:3d:b8:c8
```
You can refer to this [guide](https://www.cyberciti.biz/tips/linux-send-wake-on-lan-wol-magic-packets.html) from *cyberciti.biz*.
## Power Consumption
Measured using Sonoff POW R2 on AC side
| Power state | Power (Watt) | Current (Ampere) | Remarks |
|---------------|---------------|------------------|---------|
| Idle | 16.18 - 19.87 | 0.14 - 0.17 | |
| Standby | 8.24 - 8.63 | 0.09 - 0.10 | |
| Suspend | 7.46 - 7.71 | 0.07 - 0.08 | |
| Halt/Shutdown | 11.95 | 0.11 | HDDs still active, fans run on full speed |
!!! note
* Nominal Input Voltage: 220V
* HDD: 4x WD Red 2TB (WD20EFRX)
* [I2C OLED screen](/i2c/) attached to the systems
* Variation of power consumption sometimes due to fluctuation of the input voltage
## Issues
### Unexpected Packet
The PHY INT pin is supposed to be handled by the Ethernet controller so when there is an interrupt the driver can respond and acknowledge the interrupt. Without this acknowledgment, the PHY INT pin will stay active and the PHY won't trigger another interrupt.
On specific case that after user enabled the WOL and magic packet received before entering suspend mode, Helios4 will not able to wake up. The reason is PHY interrupt already triggered before entering suspend mode and no other interrupt triggered during suspend mode. The Ethernet controller driver will reset PHY interrupt during resume and when enabling WOL.
Therefore it is advised to always enable WOL (**sudo ethtool -s eth0 wol g**) before entering suspend.
### Thermal
When system is put in suspend mode, the PWM feature controlling the fan speed is stopped. The fans will either spin at their lowest speed ([Batch 1 fan](/pwm/#old-fan-batch-1)) or stop spinning ([Batch 2 fan](/pwm/#new-fan-batch-2)). In the latest case, while this is not an issue for the SoC itself which is designed to run with passive cooling, it might have a negative impact on the HDD peripherals because the ambient temperature inside the case will rise.
Therefore it is advised to ensure that when system is suspended the case ambient temperature will not exceed the operating temperature your HDDs are rated for.

View File

@ -59,8 +59,12 @@ markdown_extensions:
pages:
- Introduction: 'index.md'
- Kit Assembly: 'kit.md'
- Install: 'install.md'
- Download: 'download.md'
- Install: 'install.md'
- O/S:
- Armbian : 'armbian.md'
- FreeBSD : 'freebsd.md'
- U-Boot (bootloader) : 'uboot.md'
- Software:
- Mdadm (RAID) : 'mdadm.md'
- NextCloud : 'nextcloud.md'
@ -75,9 +79,6 @@ pages:
- PWM (Fan) : 'pwm.md'
- SDIO (SD Card) : 'sdcard.md'
- SPI (NOR Flash) : 'spi.md'
- Development:
- Armbian : 'armbian.md'
- FreeBSD : 'freebsd.md'
- U-Boot : 'uboot.md'
- Wake-on-LAN : 'wol.md'
- Documents: 'docs.md'
- About: 'about.md'