[PATCH v2 03/10] ARM: mvebu: add Netgear RN104 support
Luca Lauro via B4 Relay <[email protected]> Tue, 28 Jul 2026 19:43:15 +0200
| Newsgroups | org.infradead.lists.barebox,org.kernel.feeds.b4-sent |
|---|---|
| Message-ID | <[email protected]> |
From: Luca Lauro <[email protected]> This updates full support for the Netgear ReadyNAS 104, including: - board driver matching on "netgear,rn104" - bay management placeholder - lowlevel initialization - barebox device tree - barebox overlay with environment and state backend - NAND partition layout - image support Signed-off-by: Luca Lauro <[email protected]> --- arch/arm/boards/netgear-rn104/board.c | 193 +++++++++++++++++++++++ arch/arm/boards/netgear-rn104/lowlevel.c | 43 +++-- arch/arm/dts/armada-370-rn104-bb.dts | 75 ++++++++- dts/src/arm/marvell/armada-370-netgear-rn104.dts | 173 ++++++++++++-------- images/Makefile.mvebu | 3 +- 5 files changed, 403 insertions(+), 84 deletions(-) diff --git a/arch/arm/boards/netgear-rn104/board.c b/arch/arm/boards/netgear-rn104/board.c new file mode 100644 index 0000000000..29c112ec9e --- /dev/null +++ b/arch/arm/boards/netgear-rn104/board.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <init.h> +#include <gpio.h> +#include <driver.h> +#include <linux/device.h> +#include <linux/mbus.h> +#include <mach/mvebu/armada-370-xp-regs.h> +#include <bbu.h> + +/* + * Early GPIO0 MMIO + * + * GPIO driver arrives too late for the disks to be + * ready in time for AHCI driver probe. + * So we use GPIO0 direct access for: + * - reading disk presence monitoring pins + * - enable powerup for bays that detect disk presence + * - display bay status with dedicated LEDs + */ +#define GPIO0_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x18100) +#define GPIO_OUT 0x00 +#define GPIO_OUT_EN 0x04 +#define GPIO_BLINK_EN 0x08 +#define GPIO_IN 0x10 +#define GPIO_BLINK_CNT_SEL 0x20 +#define GPIO_BLINK_CNT_A_ON 0xc0 +#define GPIO_BLINK_CNT_A_OFF 0xc4 + +static inline void gpio0_set_output(int pin) +{ + u32 v = readl(GPIO0_BASE + GPIO_OUT_EN); + + v &= ~(1 << pin); + writel(v, GPIO0_BASE + GPIO_OUT_EN); +} + +static inline void gpio0_set_input(int pin) +{ + u32 v = readl(GPIO0_BASE + GPIO_OUT_EN); + + v |= (1 << pin); + writel(v, GPIO0_BASE + GPIO_OUT_EN); +} + +static inline void gpio0_write(int pin, int val) +{ + u32 v = readl(GPIO0_BASE + GPIO_OUT); + + if (val) + v |= (1 << pin); + else + v &= ~(1 << pin); + + writel(v, GPIO0_BASE + GPIO_OUT); +} + +static inline int gpio0_read(int pin) +{ + return !!(readl(GPIO0_BASE + GPIO_IN) & (1 << pin)); +} + +static void gpio0_blink(int pin, int on_ms, int off_ms) +{ + u32 v; + + gpio0_set_output(pin); + + /* set blink counter A on and off time in core clok cycles */ + writel(10*on_ms, GPIO0_BASE + GPIO_BLINK_CNT_A_ON); + writel(10*off_ms, GPIO0_BASE + GPIO_BLINK_CNT_A_OFF); + + /* use blink counter A for selected pin */ + v = readl(GPIO0_BASE + GPIO_BLINK_CNT_SEL); + v &= ~(1 << pin); + writel(v, GPIO0_BASE + GPIO_BLINK_CNT_SEL); + + /* enable blink for selected pin */ + v = readl(GPIO0_BASE + GPIO_BLINK_EN); + v |= (1 << pin); + writel(v, GPIO0_BASE + GPIO_BLINK_EN); +} + +static void gpio0_blink_disable(int pin) +{ + u32 v; + + v = readl(GPIO0_BASE + GPIO_BLINK_EN); + v &= ~(1 << pin); + writel(v, GPIO0_BASE + GPIO_BLINK_EN); +} + +/* HDD bays description */ + +enum disk_state { + DISK_ABSENT = 0, + DISK_PRESENT, + DISK_READY, +}; + +struct rn104_disk_bay { + int gpio_detect; /* input, active-low */ + int gpio_power; /* output */ + int gpio_led; /* output, active-low */ + enum disk_state state; +}; + +#define rn104_NUM_DISK_BAYS 1 + +static struct rn104_disk_bay rn104_bays[rn104_NUM_DISK_BAYS] = { + { -1, -1, -1, DISK_ABSENT }, /* placeholder */ +}; + +static void setup_bays(void) +{ + pr_info("RN104: bay management not implemented (PCA9554-based)\n"); +} + +/* + * After waiting for present disks spinup, + * we ask explicitly for corresponding ATA devices probe. + */ +static void init_disks(void) +{ + pr_info("RN104: disk spin-up logic not implemented\n"); +} + +/* + * USB0 → DRAM MBUS windows + * + * frontal USB 2.0 port of rn104 is connected to the SoC usb0. + * Here we enable MBUS windows toward all the DRAM using + * informations already gathered by mvebu_mbus_dram_info(). + */ +// #define USB0_BRIDGE_BASE (ARMADA_370_XP_USB_BASE + 0x300) +// #define USB_WIN_CTRL(n) (USB0_BRIDGE_BASE + 0x20 + (n) * 0x10) +// #define USB_WIN_BASE(n) (USB0_BRIDGE_BASE + 0x24 + (n) * 0x10) + +static void setup_usb0(void) { + // /* Window0: 512MB @ 0x00000000 */ + // writel(0x00000000, USB_WIN_BASE(0)); + // writel(0x1FFF0E01, USB_WIN_CTRL(0)); + + // /* Window1: 512MB @ 0xB0000000 (placeholder) */ + // writel(0xB0000000, USB_WIN_BASE(1)); + // writel(0x1FFE841, USB_WIN_CTRL(1)); + + writel(0x2, 0xf1051404); /* enable force suspend */ + u32 pwr = readl(0xf1051400); + pwr &= ~BIT(2); + writel(pwr, 0xf1051400); /* force SUSPENDM=0 */ +} + + +/* Early init: setup specific hardware without blocking initialization. */ +static int rn104_early_poweron(void) +{ + writel(0xC6, 0xf1020228); /* CFU configuration */ + setup_usb0(); + setup_bays(); + + return 0; +} +postcore_initcall(rn104_early_poweron); + +static int rn104_init(void) +{ + init_disks(); + + return 0; +} +device_initcall(rn104_init); + + +/* BareBox Update handlers */ +static int rn104_register_bbu(void) +{ + bbu_register_std_file_update("bootloader", 0, + "/dev/nand0.bootloader", + filetype_kwbimage_v1); + + bbu_register_std_file_update("kernel", 0, + "/dev/nand0.kernel", + filetype_arm_zimage); + + bbu_register_std_file_update("minirootfs", 0, + "/dev/nand0.minirootfs", + filetype_gzip); + + return 0; +} +late_initcall(rn104_register_bbu); diff --git a/arch/arm/boards/netgear-rn104/lowlevel.c b/arch/arm/boards/netgear-rn104/lowlevel.c index e693d13993..4fb5b6432b 100644 --- a/arch/arm/boards/netgear-rn104/lowlevel.c +++ b/arch/arm/boards/netgear-rn104/lowlevel.c @@ -1,24 +1,49 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Uwe Kleine-Koenig <[email protected]> - */ - #include <common.h> #include <asm/barebox-arm.h> -#include <mach/mvebu/barebox-arm-head.h> #include <mach/mvebu/lowlevel.h> +#include <mach/mvebu/barebox-arm-head.h> +#include <mach/mvebu/armada-370-xp-regs.h> extern char __dtb_armada_370_rn104_bb_start[]; -ENTRY_FUNCTION_MVEBU(start_netgear_rn104, r0, r1, r2) +#define INTERNAL_REG_BASE_ADDR 0x20080 + +static __always_inline void mvebu_remap_registers(void) +{ + void __iomem *base = mvebu_get_initial_int_reg_base(); + + writel(MVEBU_REMAP_INT_REG_BASE, base + INTERNAL_REG_BASE_ADDR); +} + +static unsigned long armada_370_xp_memory_find(void) { - void *fdt; + unsigned long mem_size = 0; + + for (int cs = 0; cs < 4; cs++) { + u32 ctrl = readl(ARMADA_370_XP_SDRAM_BASE + DDR_SIZE_CSn(cs)); + + /* Skip non-enabled CS */ + if ((ctrl & DDR_SIZE_ENABLED) != DDR_SIZE_ENABLED) + continue; + + mem_size += (ctrl | ~DDR_SIZE_MASK) + 1; + } - arm_cpu_lowlevel_init(); + return mem_size; +} + +ENTRY_FUNCTION_MVEBU(start_netgear_rn104, r0, r1, r2) +{ + void *fdt; + arm_cpu_lowlevel_init(); + fdt = __dtb_armada_370_rn104_bb_start + get_runtime_offset(); - armada_370_xp_barebox_entry(fdt); + mvebu_remap_registers(); + barebox_arm_entry(0, armada_370_xp_memory_find(), fdt); + // armada_370_xp_barebox_entry(fdt); } diff --git a/arch/arm/dts/armada-370-rn104-bb.dts b/arch/arm/dts/armada-370-rn104-bb.dts index b786ef350a..2649ede4f4 100644 --- a/arch/arm/dts/armada-370-rn104-bb.dts +++ b/arch/arm/dts/armada-370-rn104-bb.dts @@ -5,9 +5,76 @@ #include "arm/marvell/armada-370-netgear-rn104.dts" / { - barebox,disable-deep-probe; + chosen { + stdout-path = &uart0; + }; - chosen { - stdout-path = &uart0; - }; + aliases { + state = &state_nand; + }; + + environment { + compatible = "barebox,environment"; + device-path = &nand_controller, "partname:environment"; + }; + + state_nand: nand_state_memory { + #address-cells = <1>; + #size-cells = <1>; + compatible = "barebox,state"; + magic = <0xab67421f>; + backend-type = "raw"; + backend = <&backend_state_nand>; + backend-storage-type = "circular"; + backend-stridesize = <32>; + + variable@0 { + reg = <0x0 0x1>; + type = "uint8"; + default = <0x1>; + }; + }; +}; + +&nand_controller { + compatible = "marvell,armada370-nand", "marvell,pxa3xx-nand"; + status = "okay"; + + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "environment"; + reg = <0x400000 0x80000>; + }; + + backend_state_nand: partition@480000 { + label = "state"; + reg = <0x480000 0x80000>; + }; + + partition@500000 { + label = "kernel"; + reg = <0x500000 0x1400000>; + }; + + partition@1900000 { + label = "minirootfs"; + reg = <0x1900000 0x6000000>; + }; + }; }; diff --git a/dts/src/arm/marvell/armada-370-netgear-rn104.dts b/dts/src/arm/marvell/armada-370-netgear-rn104.dts index d752ac1d7b..d7cc0549f4 100644 --- a/dts/src/arm/marvell/armada-370-netgear-rn104.dts +++ b/dts/src/arm/marvell/armada-370-netgear-rn104.dts @@ -15,6 +15,10 @@ / { model = "NETGEAR ReadyNAS 104"; compatible = "netgear,readynas-104", "marvell,armada370", "marvell,armada-370-xp"; + aliases { + state = &state_nand; + }; + chosen { stdout-path = "serial0:115200n8"; }; @@ -40,6 +44,12 @@ serial@12000 { status = "okay"; }; + /* eSATA interface */ + sata@a0000 { + nr-ports = <1>; + status = "okay"; + }; + ethernet@70000 { pinctrl-0 = <&ge0_rgmii_pins>; pinctrl-names = "default"; @@ -103,15 +113,10 @@ g762_clk: g762-oscillator { gpio-leds { compatible = "gpio-leds"; - pinctrl-0 = <&backup_led_pin &power_led_pin>; + pinctrl-0 = <&power_led_pin + &backup_led_pin>; pinctrl-names = "default"; - blue-backup-led { - label = "rn104:blue:backup"; - gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; - blue-power-led { label = "rn104:blue:pwr"; gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; @@ -141,6 +146,12 @@ blue-sata4-led { gpios = <&pca9554 3 GPIO_ACTIVE_LOW>; default-state = "off"; }; + + blue-backup-led { + label = "rn104:blue:backup"; + gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; }; auxdisplay { @@ -159,17 +170,11 @@ auxdisplay { gpio-keys { compatible = "gpio-keys"; - pinctrl-0 = <&backup_button_pin - &power_button_pin - &reset_button_pin>; + pinctrl-0 = <&power_button_pin + &reset_button_pin + &backup_button_pin>; pinctrl-names = "default"; - backup-button { - label = "Backup Button"; - linux,code = <KEY_COPY>; - gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; - }; - power-button { label = "Power Button"; linux,code = <KEY_POWER>; @@ -181,6 +186,12 @@ reset-button { linux,code = <KEY_RESTART>; gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; }; + + backup-button { + label = "Backup Button"; + linux,code = <KEY_COPY>; + gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; + }; }; gpio-poweroff { @@ -189,18 +200,43 @@ gpio-poweroff { pinctrl-names = "default"; gpios = <&gpio1 28 GPIO_ACTIVE_LOW>; }; + + /* configure nand partition to store barebox environment */ + environment { + compatible = "barebox,environment"; + device-path = &nand_controller, "partname:environment"; + }; + + /* configure nand partition to store barebox-state backend */ + state_nand: nand_state_memory { + #address-cells = <1>; + #size-cells = <1>; + compatible = "barebox,state"; + magic = <0xab67421f>; + backend-type = "raw"; + backend = <&backend_state_nand>; + backend-storage-type = "circular"; + backend-stridesize = <32>; + + + variable@0 { + reg = <0x0 0x1>; + type ="uint8"; + default = <0x1>; + }; + }; }; &pciec { status = "okay"; - /* Connected to FL1009 USB 3.0 controller */ + /* Connected to Marvell 88SE9170 SATA controller */ pcie@1,0 { /* Port 0, Lane 0 */ status = "okay"; }; - /* Connected to Marvell 88SE9215 SATA controller */ + /* Connected to FL1009 USB 3.0 controller */ pcie@2,0 { /* Port 1, Lane 0 */ status = "okay"; @@ -220,8 +256,13 @@ phy1: ethernet-phy@1 { /* Marvell 88E1318 */ }; &pinctrl { - poweroff: poweroff { - marvell,pins = "mpp60"; + power_led_pin: power-led-pin { + marvell,pins = "mpp64"; + marvell,function = "gpio"; + }; + + backup_led_pin: backup-led-pin { + marvell,pins = "mpp63"; marvell,function = "gpio"; }; @@ -235,68 +276,62 @@ power_button_pin: power-button-pin { marvell,function = "gpio"; }; - backup_led_pin: backup-led-pin { - marvell,pins = "mpp63"; - marvell,function = "gpio"; - }; - - power_led_pin: power-led-pin { - marvell,pins = "mpp64"; + reset_button_pin: reset-button-pin { + marvell,pins = "mpp65"; marvell,function = "gpio"; }; - reset_button_pin: reset-button-pin { - marvell,pins = "mpp65"; + poweroff_pin: poweroff-pin { + marvell,pins = "mpp60"; marvell,function = "gpio"; }; }; &nand_controller { + compatible = "marvell,armada370-nand", "marvell,pxa3xx-nand"; status = "okay"; - nand@0 { - reg = <0>; - label = "pxa3xx_nand-0"; - nand-rb = <0>; - marvell,nand-keep-config; - nand-on-flash-bbt; - - /* Use Hardware BCH ECC */ - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0000000 0x180000>; /* 1.5MB */ - read-only; - }; + label = <&nand_controller>; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; - partition@180000 { - label = "u-boot-env"; - reg = <0x180000 0x20000>; /* 128KB */ - read-only; - }; + /* Use Hardware BCH ECC */ + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; - partition@200000 { - label = "uImage"; - reg = <0x0200000 0x600000>; /* 6MB */ - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - partition@800000 { - label = "minirootfs"; - reg = <0x0800000 0x400000>; /* 4MB */ - }; + partition@0 { + label = "bootloader"; + reg = <0x0 0x400000>; /* 4MB */ + //read-only; + }; - /* Last MB is for the BBT, i.e. not writable */ - partition@c00000 { - label = "ubifs"; - reg = <0x0c00000 0x7400000>; /* 116MB */ - }; + partition@0x400000 { + label = "environment"; + reg = <0x400000 0x80000>; /* 0.5MB */ + //read-only; }; + + backend_state_nand: partition@0x480000 { + label = "state"; + reg = <0x480000 0x80000>; /* 0.5MB */ + }; + + partition@0x500000 { + label = "kernel"; + reg = <0x500000 0x1400000>; /* 20MB */ + }; + + partition@0x1900000 { + label = "minirootfs"; + reg = <0x1900000 0x6000000>; /* 100MB */ + }; + + /* Last MB is for the BBT, i.e. not writable */ }; -}; +}; \ No newline at end of file diff --git a/images/Makefile.mvebu b/images/Makefile.mvebu index 1741f0e9a5..106a302cfa 100644 --- a/images/Makefile.mvebu +++ b/images/Makefile.mvebu @@ -37,10 +37,9 @@ image-$(CONFIG_MACH_NETGEAR_RN102) += barebox-netgear-rn102.img FILE_barebox-netgear-rn102-2nd.img = start_netgear_rn102.pblb image-$(CONFIG_MACH_NETGEAR_RN102) += barebox-netgear-rn102-2nd.img -FLAGS_start_netgear_rn104.pblb.mvebu1img = -d 0x600000 -e 0x6e0000 BOOTSRC_start_netgear_rn104.pblb.mvebu1img = nand BINHDR_start_netgear_rn104.pblb.mvebu1img = $(board)/netgear-rn104/binary.0 -FLAGS_start_netgear_rn104.pblb.mvebu1img = -B 0x20000:1 +FLAGS_start_netgear_rn104.pblb.mvebu1img = -B 0x20000:1 -d 0x0 -e 0x0 FILE_barebox-netgear-rn104.img = start_netgear_rn104.pblb.mvebu1img pblb-$(CONFIG_MACH_NETGEAR_RN104) += start_netgear_rn104 image-$(CONFIG_MACH_NETGEAR_RN104) += barebox-netgear-rn104.img -- 2.47.3