[PATCH 01/19] ARM: mvebu: add board support for Netgear RN102

Luca Lauro <[email protected]>
Newsgroups org.kernel.feeds.b4-sent,org.infradead.lists.barebox
Message-ID <[email protected]>
---
 arch/arm/boards/Makefile               |   1 +
 arch/arm/boards/netgear-rn102/Makefile |   4 +
 arch/arm/boards/netgear-rn102/board.c  | 243 +++++++++++++++++++++++++++++++++
 rebuild-series.sh                      |  39 ++++++
 4 files changed, 287 insertions(+)

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index dd2f2c324e..aca1b45a81 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_MACH_MARVELL_ARMADA_XP_DB)		+= marvell-armada-xp-db/
 obj-$(CONFIG_MACH_MX23EVK)			+= freescale-mx23-evk/
 obj-$(CONFIG_MACH_MX28EVK)			+= freescale-mx28-evk/
 obj-$(CONFIG_MACH_MYIRTECH_X335X)		+= myirtech-x335x/
+obj-$(CONFIG_MACH_NETGEAR_RN102)		+= netgear-rn102/
 obj-$(CONFIG_MACH_NETGEAR_RN104)		+= netgear-rn104/
 obj-$(CONFIG_MACH_NETGEAR_RN2120)		+= netgear-rn2120/
 obj-$(CONFIG_MACH_NVIDIA_BEAVER)		+= nvidia-beaver/
diff --git a/arch/arm/boards/netgear-rn102/Makefile b/arch/arm/boards/netgear-rn102/Makefile
new file mode 100644
index 0000000000..da63d2625f
--- /dev/null
+++ b/arch/arm/boards/netgear-rn102/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += board.o
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/netgear-rn102/board.c b/arch/arm/boards/netgear-rn102/board.c
new file mode 100644
index 0000000000..c6673e9356
--- /dev/null
+++ b/arch/arm/boards/netgear-rn102/board.c
@@ -0,0 +1,243 @@
+// 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 rn102_disk_bay {
+    int gpio_detect;        /* input, active-low */
+    int gpio_power;         /* output */
+    int gpio_led;           /* output, active-low */
+    enum disk_state state;
+};
+
+#define RN102_NUM_DISK_BAYS 2
+
+static struct rn102_disk_bay rn102_bays[RN102_NUM_DISK_BAYS] = {
+    { 12, 13, 15, DISK_ABSENT }, /* Bay 1, default to disk absent */
+    { 10, 11, 14, DISK_ABSENT }, /* Bay 2, default to disk absent */
+};
+
+static void setup_bays(void) {
+    pr_info("Early disk power-on...\n");
+
+    for (int i = 0; i < RN102_NUM_DISK_BAYS; i++) {
+        int present;
+
+        gpio0_set_input(rn102_bays[i].gpio_detect);
+        present = (gpio0_read(rn102_bays[i].gpio_detect) == 0);
+
+        gpio0_set_output(rn102_bays[i].gpio_power);
+
+        if (present) {
+            pr_info("Bay %d: disk detected, powering on\n", i + 1);
+            gpio0_blink(rn102_bays[i].gpio_led, 500, 500);
+            gpio0_write(rn102_bays[i].gpio_power, 1);
+            rn102_bays[i].state = DISK_PRESENT;
+        } else {
+            pr_info("Bay %d empty\n", i + 1);
+            gpio0_write(rn102_bays[i].gpio_led, 0);
+            gpio0_write(rn102_bays[i].gpio_power, 0);
+            rn102_bays[i].state = DISK_ABSENT;
+        }
+    }
+}
+
+/*
+ * After waiting for present disks spinup,
+ * we ask explicitly for corresponding ATA devices probe.
+ */
+static void init_disks(void) {
+    pr_info("Waiting for disks spinup...\n");
+    mdelay(8000);
+
+    pr_info("Detecting ATA devices:\n");
+    for (int i = 0; i < RN102_NUM_DISK_BAYS; i++) {
+        char name[8];
+        struct device *dev;
+
+        if (rn102_bays[i].state != DISK_PRESENT) {
+            gpio0_write(rn102_bays[i].gpio_power, 0);
+            gpio0_blink_disable(rn102_bays[i].gpio_led);
+            gpio0_write(rn102_bays[i].gpio_led, 0);
+            continue;
+        }
+
+        snprintf(name, sizeof(name), "ata%d", i);
+
+        dev = get_device_by_name(name);
+        if (!dev) {
+            pr_warn("%s not found\n", name);
+            gpio0_write(rn102_bays[i].gpio_power, 0);
+            gpio0_blink(rn102_bays[i].gpio_led, 1000, 1000);
+            continue;
+        }
+
+        pr_info("Connecting %s to disk %d\n", name, i + 1);
+        device_detect(dev);
+        gpio0_blink_disable(rn102_bays[i].gpio_led);
+        gpio0_write(rn102_bays[i].gpio_led, 1);
+        rn102_bays[i].state = DISK_READY;
+    }
+}
+
+/*
+ *  USB0 → DRAM MBUS windows
+ *
+ * frontal USB 2.0 port of RN102 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 rn102_early_poweron(void)
+{
+    writel(0xC6, 0xf1020228); /* CFU configuration */
+    setup_usb0();
+    setup_bays();
+
+    return 0;
+}
+postcore_initcall(rn102_early_poweron);
+
+static int rn102_init(void)
+{
+    init_disks();
+
+    return 0;
+}
+device_initcall(rn102_init);
+
+
+/* BareBox Update handlers */
+static int rn102_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(rn102_register_bbu);
diff --git a/rebuild-series.sh b/rebuild-series.sh
new file mode 100755
index 0000000000..aad99bc296
--- /dev/null
+++ b/rebuild-series.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+set -e
+
+# Torna al punto base
+git checkout v2026.01.0
+git branch -D rn102-rn104-series 2>/dev/null || true
+git checkout -b rn102-rn104-series
+
+# Applica ogni patch e crea commit
+apply_patch() {
+    PATCH="$1"
+    MSG="$2"
+    echo "Applying $PATCH..."
+    git apply "$PATCH"
+    git add -A
+    git commit -m "$MSG"
+}
+
+apply_patch 0001-*.patch "ARM: mvebu: add board support for Netgear RN102"
+apply_patch 0002-*.patch "ARM: mvebu: add lowlevel support for Netgear RN102"
+apply_patch 0003-*.patch "ARM: dts: add barebox device tree for Netgear RN102"
+apply_patch 0004-*.patch "ARM: dts: update RN102 Linux DTS"
+apply_patch 0005-*.patch "ARM: mvebu: add Kconfig entry for Netgear RN102"
+apply_patch 0006-*.patch "ARM: mvebu: add RN102 image support"
+apply_patch 0007-*.patch "ARM: mvebu: enable RN102 in mvebu_defconfig"
+apply_patch 0008-*.patch "ARM: mvebu: rn104: placeholder bay management"
+apply_patch 0009-*.patch "ARM: mvebu: add lowlevel support for Netgear RN104"
+apply_patch 0010-*.patch "ARM: dts: update RN104 Linux DTS"
+apply_patch 0011-*.patch "ARM: mvebu: adapt RN104 image support"
+apply_patch 0012-*.patch "ARM: mvebu: rename PUTC_LL to MVEBU_PUTC_LL"
+apply_patch 0013-*.patch "drivers: fan: add fan framework and API"
+apply_patch 0014-*.patch "commands: add fan control command"
+apply_patch 0015-*.patch "commands: integrate fan command into Kconfig and Makefile"
+apply_patch 0016-*.patch "usb: ehci: add Marvell EHCI host controller driver"
+apply_patch 0017-*.patch "usb: ehci: minor fixes for Marvell compatibility"
+apply_patch 0018-*.patch "ata: ahci: fixes and updates for Marvell SATA controller"
+apply_patch 0019-*.patch "drivers: integrate USB/AHCI changes"
+
+echo "Serie ricostruita con successo!"

-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.