[openwrt/openwrt] x86: add support for Meraki MX100

LEDE Commits lede-commits at lists.infradead.org
Sun Oct 10 07:48:25 PDT 2021


chunkeey pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/fe9e5fbd7527ad4ff4f5b955823216038a80557d

commit fe9e5fbd7527ad4ff4f5b955823216038a80557d
Author: Chris Blake <chrisrblake93 at gmail.com>
AuthorDate: Fri Oct 1 09:38:56 2021 -0500

    x86: add support for Meraki MX100
    
    This commit will add support for the Meraki MX100 in OpenWRT.
    
    Specs:
    * CPU: Intel Xeon E3-1200 Series 1.5GHz 2C/4T
    * Memory: 4GB DDR3 1600 ECC
    * Storage: 1GB USB NAND, 1TB SATA HDD
    * Wireless: None
    * Wired: 10x 1Gb RJ45, 2x 1Gb SFP
    
    UART:
    The UART header is named CONN11 and is found in the
    center of the mainboard. The pinout from Pin 1 (marked
    with a black triangle) to pin 4 is below:
    Pin 1: VCC
    Pin 2: TX
    Pin 3: RX
    Pin 4: GND
    Note that VCC is not required for UART on this device.
    
    Booting:
    1. Flash/burn one of the images from this repo to a
    flash drive.
    2. Take the top off the MX100, and unplug the SATA
    cable from the HDD.
    3. Hook up UART to the MX100, plug in the USB drive,
    and then power up the device.
    4. At the BIOS prompt, quickly press F7 and then
    scroll to the Save & Exit tab.
    5. Scroll down to Boot Override, and select the
    UEFI entry for your jumpdrive.
    
    Note: UEFI booting will fail if the SATA cable for
    the HDD is plugged in.
    The issue is explained under the Flashing instructions.
    
    Flashing:
    1. Ensure the MX100 is powered down, and not plugged
    into power.
    2. Take the top off the MX100, and unplug the SATA
    cable from the HDD.
    3. Using the Mini USB female port found by the SATA
    port on the motherboard,
    flash one of the images to the system. Example:
    `dd if=image of=/dev/sdb conv=fdatasync` where sdb
    is the USB device for the MX100's NAND.
    4. Unplug the Mini USB, hook up UART to the MX100,
    and then power up the device.
    5. At the BIOS prompt, quickly press F7 and then
    scroll to the Boot tab.
    6. Change the boot order and set UEFI: USB DISK 2.0
    as first, and USB DISK 2.0 as second.
    Disable the other boot options.
    7. Go to Save & Exit, and then select Save Changes and
    Reset
    
    Note that OpenWRT will fail to boot in UEFI mode when
    the SATA hard drive is plugged in. To fix this, boot
    with the SATA disk unplugged and then run the following
    command:
    `sed -i "s|hd0,gpt1|hd1,gpt1|g" boot/grub/grub.cfg`
    Once the above is ran, OpenWRT will boot when the HDD
    is plugged into SATA. The reason this happens is the
    UEFI implementation for the MX100 will always set
    anything on SATA to HD0 instead of the onboard USB
    storage, so we have to accomidate it since OpenWRT's
    GRUB does not support detecting a boot disk via UUID.
    
    Signed-off-by: Chris Blake <chrisrblake93 at gmail.com>
---
 target/linux/x86/base-files/etc/board.d/01_leds    |   4 +
 target/linux/x86/base-files/etc/board.d/02_network |   3 +
 .../linux/x86/base-files/lib/upgrade/platform.sh   |  10 +
 target/linux/x86/modules.mk                        |  20 ++
 ...d-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch |  32 +++
 ...form-x86-add-meraki-mx100-platform-driver.patch | 300 +++++++++++++++++++++
 6 files changed, 369 insertions(+)

diff --git a/target/linux/x86/base-files/etc/board.d/01_leds b/target/linux/x86/base-files/etc/board.d/01_leds
index 79e1191080..74ad2d59fe 100644
--- a/target/linux/x86/base-files/etc/board.d/01_leds
+++ b/target/linux/x86/base-files/etc/board.d/01_leds
@@ -7,6 +7,10 @@
 board_config_update
 
 case "$(board_name)" in
+cisco-mx100-hw)
+	ucidef_set_led_usbport "usb" "USB" "mx100:green:usb" "1-1-port2"
+	ucidef_set_led_default "diag" "DIAG" "mx100:green:tricolor" "1"
+	;;
 pc-engines-apu1|pc-engines-apu2|pc-engines-apu3)
 	ucidef_set_led_netdev "wan" "WAN" "apu:green:3" "eth0"
 	ucidef_set_led_netdev "lan" "LAN" "apu:green:2" "br-lan"
diff --git a/target/linux/x86/base-files/etc/board.d/02_network b/target/linux/x86/base-files/etc/board.d/02_network
index 30035dcbe9..2a07518096 100644
--- a/target/linux/x86/base-files/etc/board.d/02_network
+++ b/target/linux/x86/base-files/etc/board.d/02_network
@@ -8,6 +8,9 @@
 board_config_update
 
 case "$(board_name)" in
+cisco-mx100-hw)
+	ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth4 eth5 eth7 eth8 eth9 eth10 eth11" "eth6"
+	;;
 pc-engines-apu1|pc-engines-apu2|pc-engines-apu3)
 	ucidef_set_interfaces_lan_wan "eth1 eth2" "eth0"
 	;;
diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
index d8f2eba97e..94bf80b144 100644
--- a/target/linux/x86/base-files/lib/upgrade/platform.sh
+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
@@ -65,6 +65,16 @@ platform_do_bootloader_upgrade() {
 			"/dev/$diskdev" \
 		&& touch /tmp/boot/boot/grub/upgraded
 
+        case "$(board_name)" in
+        cisco-mx100-hw)
+            # If the MX100 is booted UEFI AND the SATA HDD exists, we need to change
+            # grub's root= to hd1 for it to boot correctly, otherwise we can keep it hd0.
+            if [ -d /sys/firmware/efi ] && [ "$(ls -a /dev/sd[a-z] | wc -w)" -gt 1 ] ; then
+                sed -i "s|hd0,${parttable}1|hd1,${parttable}1|g" /tmp/boot/boot/grub/grub.cfg
+            fi
+            ;;
+        esac
+
 		umount /tmp/boot
 	fi
 }
diff --git a/target/linux/x86/modules.mk b/target/linux/x86/modules.mk
index d31e4535df..0071ebda41 100644
--- a/target/linux/x86/modules.mk
+++ b/target/linux/x86/modules.mk
@@ -82,3 +82,23 @@ define KernelPackage/pcengines-apuv2/description
 endef
 
 $(eval $(call KernelPackage,pcengines-apuv2))
+
+
+define KernelPackage/meraki-mx100
+  SUBMENU:=$(OTHER_MENU)
+  TITLE:=Cisco Meraki MX100 Platform Driver
+  DEPENDS:=@TARGET_x86 @!LINUX_5_4 +kmod-tg3 +kmod-gpio-button-hotplug +kmod-leds-gpio \
+    +kmod-usb-ledtrig-usbport +nu801 +kmod-itco-wdt
+  KCONFIG:=CONFIG_MERAKI_MX100
+  FILES:=$(LINUX_DIR)/drivers/platform/x86/meraki-mx100.ko
+  AUTOLOAD:=$(call AutoLoad,60,meraki-mx100,1)
+endef
+
+define KernelPackage/meraki-mx100/description
+  This driver provides support for the front button and LEDs on
+  the Cisco Meraki MX100 (Tinkerbell) 1U appliance. Note this also
+  selects the gpio-cdev nu801 userspace driver to support the Status
+  LED, as well as other required platform drivers.
+endef
+
+$(eval $(call KernelPackage,meraki-mx100))
diff --git a/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch b/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch
new file mode 100644
index 0000000000..0f0a3958da
--- /dev/null
+++ b/target/linux/x86/patches-5.10/101-v5.15-mfd-lpc_ich-Enable-GPIO-driver-for-DH89xxCC.patch
@@ -0,0 +1,32 @@
+From ef0eea5b151aefe1efea78e2fa7c507ff3c56bf0 Mon Sep 17 00:00:00 2001
+From: Chris Blake <chrisrblake93 at gmail.com>
+Date: Mon, 7 Jun 2021 18:35:35 -0500
+Subject: mfd: lpc_ich: Enable GPIO driver for DH89xxCC
+
+Based on the Intel Datasheet for the DH89xxCC PCH, the GPIO driver
+is the same as ICH_v5_GPIO, minus the fact the DH89xxCC also has
+blink support. However, blink support isn't supported by the GPIO
+driver so we should use ICH_v5_GPIO. Tested and working on a Meraki
+MX100-HW.
+
+Signed-off-by: Chris Blake <chrisrblake93 at gmail.com>
+Co-developed-by: Christian Lamparter <chunkeey at gmail.com>
+Signed-off-by: Lee Jones <lee.jones at linaro.org>
+---
+ drivers/mfd/lpc_ich.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
+index 3bbb29a7e7a57..f10e53187f67a 100644
+--- a/drivers/mfd/lpc_ich.c
++++ b/drivers/mfd/lpc_ich.c
+@@ -489,6 +489,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
+ 	[LPC_DH89XXCC] = {
+ 		.name = "DH89xxCC",
+ 		.iTCO_version = 2,
++		.gpio_version = ICH_V5_GPIO,
+ 	},
+ 	[LPC_PPT] = {
+ 		.name = "Panther Point",
+-- 
+cgit 1.2.3-1.el7
diff --git a/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch b/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch
new file mode 100644
index 0000000000..c05b61a994
--- /dev/null
+++ b/target/linux/x86/patches-5.10/102-v5.15-platform-x86-add-meraki-mx100-platform-driver.patch
@@ -0,0 +1,300 @@
+From 636a1e697555e73c28cdd6952a409edbfdd16475 Mon Sep 17 00:00:00 2001
+From: Chris Blake <chrisrblake93 at gmail.com>
+Date: Mon, 9 Aug 2021 19:40:21 -0500
+Subject: platform/x86: add meraki-mx100 platform driver
+
+This adds platform support for the Cisco Meraki MX100 (Tinkerbell)
+network appliance. This sets up the network LEDs and Reset
+button.
+
+Depends-on: ef0eea5b151ae ("mfd: lpc_ich: Enable GPIO driver for DH89xxCC")
+Co-developed-by: Christian Lamparter <chunkeey at gmail.com>
+Signed-off-by: Christian Lamparter <chunkeey at gmail.com>
+Signed-off-by: Chris Blake <chrisrblake93 at gmail.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
+Link: https://lore.kernel.org/r/20210810004021.2538308-1-chrisrblake93@gmail.com
+Reviewed-by: Hans de Goede <hdegoede at redhat.com>
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+---
+ drivers/platform/x86/Kconfig        |  13 ++
+ drivers/platform/x86/Makefile       |   3 +
+ drivers/platform/x86/meraki-mx100.c | 230 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 246 insertions(+)
+ create mode 100644 drivers/platform/x86/meraki-mx100.c
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 6ad35158ae4ef..432d72170b003 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -302,6 +302,19 @@ config ASUS_NB_WMI
+ 	  If you have an ACPI-WMI compatible Asus Notebook, say Y or M
+ 	  here.
+ 
++config MERAKI_MX100
++	tristate "Cisco Meraki MX100 Platform Driver"
++	depends on GPIOLIB
++	depends on GPIO_ICH
++	depends on LEDS_CLASS
++	select LEDS_GPIO
++	help
++	  This driver provides support for the front button and LEDs on
++	  the Cisco Meraki MX100 (Tinkerbell) 1U appliance.
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called meraki-mx100.
++
+ config EEEPC_LAPTOP
+ 	tristate "Eee PC Hotkey Driver"
+ 	depends on ACPI
+diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
+index 5edfdc2ea7f29..9bb3c3f773864 100644
+--- a/drivers/platform/x86/Makefile
++++ b/drivers/platform/x86/Makefile
+@@ -39,6 +39,9 @@ obj-$(CONFIG_ASUS_NB_WMI)	+= asus-nb-wmi.o
+ obj-$(CONFIG_EEEPC_LAPTOP)	+= eeepc-laptop.o
+ obj-$(CONFIG_EEEPC_WMI)		+= eeepc-wmi.o
+ 
++# Cisco/Meraki
++obj-$(CONFIG_MERAKI_MX100)	+= meraki-mx100.o
++
+ # Dell
+ obj-$(CONFIG_X86_PLATFORM_DRIVERS_DELL)		+= dell/
+ 
+diff --git a/drivers/platform/x86/meraki-mx100.c b/drivers/platform/x86/meraki-mx100.c
+new file mode 100644
+index 0000000000000..3751ed36a980a
+--- /dev/null
++++ b/drivers/platform/x86/meraki-mx100.c
+@@ -0,0 +1,230 @@
++// SPDX-License-Identifier: GPL-2.0+
++
++/*
++ * Cisco Meraki MX100 (Tinkerbell) board platform driver
++ *
++ * Based off of arch/x86/platform/meraki/tink.c from the
++ * Meraki GPL release meraki-firmware-sources-r23-20150601
++ *
++ * Format inspired by platform/x86/pcengines-apuv2.c
++ *
++ * Copyright (C) 2021 Chris Blake <chrisrblake93 at gmail.com>
++ */
++
++#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
++
++#include <linux/dmi.h>
++#include <linux/err.h>
++#include <linux/gpio_keys.h>
++#include <linux/gpio/machine.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/leds.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#define TINK_GPIO_DRIVER_NAME "gpio_ich"
++
++/* LEDs */
++static const struct gpio_led tink_leds[] = {
++	{
++		.name = "mx100:green:internet",
++		.default_trigger = "default-on",
++	},
++	{
++		.name = "mx100:green:lan2",
++	},
++	{
++		.name = "mx100:green:lan3",
++	},
++	{
++		.name = "mx100:green:lan4",
++	},
++	{
++		.name = "mx100:green:lan5",
++	},
++	{
++		.name = "mx100:green:lan6",
++	},
++	{
++		.name = "mx100:green:lan7",
++	},
++	{
++		.name = "mx100:green:lan8",
++	},
++	{
++		.name = "mx100:green:lan9",
++	},
++	{
++		.name = "mx100:green:lan10",
++	},
++	{
++		.name = "mx100:green:lan11",
++	},
++	{
++		.name = "mx100:green:ha",
++	},
++	{
++		.name = "mx100:orange:ha",
++	},
++	{
++		.name = "mx100:green:usb",
++	},
++	{
++		.name = "mx100:orange:usb",
++	},
++};
++
++static const struct gpio_led_platform_data tink_leds_pdata = {
++	.num_leds	= ARRAY_SIZE(tink_leds),
++	.leds		= tink_leds,
++};
++
++static struct gpiod_lookup_table tink_leds_table = {
++	.dev_id = "leds-gpio",
++	.table = {
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 11,
++				NULL, 0, GPIO_ACTIVE_LOW),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 18,
++				NULL, 1, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 20,
++				NULL, 2, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 22,
++				NULL, 3, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 23,
++				NULL, 4, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 32,
++				NULL, 5, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 34,
++				NULL, 6, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 35,
++				NULL, 7, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 36,
++				NULL, 8, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 37,
++				NULL, 9, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 48,
++				NULL, 10, GPIO_ACTIVE_HIGH),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 16,
++				NULL, 11, GPIO_ACTIVE_LOW),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 7,
++				NULL, 12, GPIO_ACTIVE_LOW),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 21,
++				NULL, 13, GPIO_ACTIVE_LOW),
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 19,
++				NULL, 14, GPIO_ACTIVE_LOW),
++		{} /* Terminating entry */
++	}
++};
++
++/* Reset Button */
++static struct gpio_keys_button tink_buttons[] = {
++	{
++		.desc			= "Reset",
++		.type			= EV_KEY,
++		.code			= KEY_RESTART,
++		.active_low             = 1,
++		.debounce_interval      = 100,
++	},
++};
++
++static const struct gpio_keys_platform_data tink_buttons_pdata = {
++	.buttons	= tink_buttons,
++	.nbuttons	= ARRAY_SIZE(tink_buttons),
++	.poll_interval  = 20,
++	.rep		= 0,
++	.name		= "mx100-keys",
++};
++
++static struct gpiod_lookup_table tink_keys_table = {
++	.dev_id = "gpio-keys-polled",
++	.table = {
++		GPIO_LOOKUP_IDX(TINK_GPIO_DRIVER_NAME, 60,
++				NULL, 0, GPIO_ACTIVE_LOW),
++		{} /* Terminating entry */
++	}
++};
++
++/* Board setup */
++static const struct dmi_system_id tink_systems[] __initconst = {
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Cisco"),
++			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MX100-HW"),
++		},
++	},
++	{} /* Terminating entry */
++};
++MODULE_DEVICE_TABLE(dmi, tink_systems);
++
++static struct platform_device *tink_leds_pdev;
++static struct platform_device *tink_keys_pdev;
++
++static struct platform_device * __init tink_create_dev(
++	const char *name, const void *pdata, size_t sz)
++{
++	struct platform_device *pdev;
++
++	pdev = platform_device_register_data(NULL,
++		name, PLATFORM_DEVID_NONE, pdata, sz);
++	if (IS_ERR(pdev))
++		pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev));
++
++	return pdev;
++}
++
++static int __init tink_board_init(void)
++{
++	int ret;
++
++	if (!dmi_first_match(tink_systems))
++		return -ENODEV;
++
++	/*
++	 * We need to make sure that GPIO60 isn't set to native mode as is default since it's our
++	 * Reset Button. To do this, write to GPIO_USE_SEL2 to have GPIO60 set to GPIO mode.
++	 * This is documented on page 1609 of the PCH datasheet, order number 327879-005US
++	 */
++	outl(inl(0x530) | BIT(28), 0x530);
++
++	gpiod_add_lookup_table(&tink_leds_table);
++	gpiod_add_lookup_table(&tink_keys_table);
++
++	tink_leds_pdev = tink_create_dev("leds-gpio",
++		&tink_leds_pdata, sizeof(tink_leds_pdata));
++	if (IS_ERR(tink_leds_pdev)) {
++		ret = PTR_ERR(tink_leds_pdev);
++		goto err;
++	}
++
++	tink_keys_pdev = tink_create_dev("gpio-keys-polled",
++		&tink_buttons_pdata, sizeof(tink_buttons_pdata));
++	if (IS_ERR(tink_keys_pdev)) {
++		ret = PTR_ERR(tink_keys_pdev);
++		platform_device_unregister(tink_leds_pdev);
++		goto err;
++	}
++
++	return 0;
++
++err:
++	gpiod_remove_lookup_table(&tink_keys_table);
++	gpiod_remove_lookup_table(&tink_leds_table);
++	return ret;
++}
++module_init(tink_board_init);
++
++static void __exit tink_board_exit(void)
++{
++	platform_device_unregister(tink_keys_pdev);
++	platform_device_unregister(tink_leds_pdev);
++	gpiod_remove_lookup_table(&tink_keys_table);
++	gpiod_remove_lookup_table(&tink_leds_table);
++}
++module_exit(tink_board_exit);
++
++MODULE_AUTHOR("Chris Blake <chrisrblake93 at gmail.com>");
++MODULE_DESCRIPTION("Cisco Meraki MX100 Platform Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:meraki-mx100");
+-- 
+cgit 1.2.3-1.el7



More information about the lede-commits mailing list