mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
Backport DTS/DTSI changes from linux-6.4.y to 6.1.y
Add meson64-reboot driver to all boards
Add board: ODROID N2L
Add uart_A uart_AO_B uart_B uart_C where appropriate
U-Boot v2023.07.02: ODROID N2/N2L/N2Plus/C4
Meson64-reboot driver: (source: tobetter)
While the current meson64-reboot driver is cleaner and doesn't
depend on modding other kernel sources, its functionality leaves
much to be desired. One example can be found in the ODROID C4.
Using the current driver, the board will not properly power off,
leaving the POWER LED still on. The new driver powers off the unit
completely.
Fan control: (ODROID N2L/N2PLus)
Added service and script for controlling the trip point.
fanctrl: arguments: 65 55 45 35 25 menu run
┌──┤ Fan Control ├──┐
│ │
│ 6) 65°C │
│ 5) 55°C │
│ 4) 45°C │
│ 3) 35°C │
│ 2) 25°C │
│ E) Exit .. │
│ │
│ │
│ <Ok> │
│ │
└───────────────────┘
NOTES: (N2L/HC4): I do not own the units so I can't run tests.
Signed-off-by: Patrick Yavitz <pyavitz@xxxxx.com>
275 lines
7.5 KiB
Diff
275 lines
7.5 KiB
Diff
From 7730fee7ed2eb1cc1b5d588c62618532a75b39ce Mon Sep 17 00:00:00 2001
|
|
From: Patrick Yavitz <pyavitz@xxxxx.com>
|
|
Date: Wed, 26 Jul 2023 03:39:48 -0400
|
|
Subject: [PATCH] meson64 reboot power off driver
|
|
|
|
Driver supports restart / power off for amlogic g12a, g12b and
|
|
sm1 SoCs.
|
|
|
|
Signed-off-by: Patrick Yavitz <pyavitz@xxxxx.com>
|
|
---
|
|
arch/arm64/include/asm/system_misc.h | 2 +
|
|
arch/arm64/kernel/process.c | 7 +-
|
|
drivers/power/reset/Kconfig | 7 ++
|
|
drivers/power/reset/Makefile | 1 +
|
|
drivers/power/reset/meson64-reboot.c | 181 +++++++++++++++++++++++++++
|
|
5 files changed, 197 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/power/reset/meson64-reboot.c
|
|
|
|
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
|
|
index c34344256762..311bc7c5f580 100644
|
|
--- a/arch/arm64/include/asm/system_misc.h
|
|
+++ b/arch/arm64/include/asm/system_misc.h
|
|
@@ -32,6 +32,8 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned long,
|
|
struct mm_struct;
|
|
extern void __show_regs(struct pt_regs *);
|
|
|
|
+extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
|
+
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* __ASM_SYSTEM_MISC_H */
|
|
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
|
|
index 0fcc4eb1a7ab..78d66392fb8a 100644
|
|
--- a/arch/arm64/kernel/process.c
|
|
+++ b/arch/arm64/kernel/process.c
|
|
@@ -68,6 +68,8 @@ EXPORT_SYMBOL(__stack_chk_guard);
|
|
void (*pm_power_off)(void);
|
|
EXPORT_SYMBOL_GPL(pm_power_off);
|
|
|
|
+void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
|
|
+
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
void __noreturn arch_cpu_idle_dead(void)
|
|
{
|
|
@@ -137,7 +139,10 @@ void machine_restart(char *cmd)
|
|
efi_reboot(reboot_mode, NULL);
|
|
|
|
/* Now call the architecture specific reboot code. */
|
|
- do_kernel_restart(cmd);
|
|
+ if (arm_pm_restart)
|
|
+ arm_pm_restart(reboot_mode, cmd);
|
|
+ else
|
|
+ do_kernel_restart(cmd);
|
|
|
|
/*
|
|
* Whoops - the architecture was unable to reboot.
|
|
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
|
|
index 8c87eeda0fec..bd654b885c2f 100644
|
|
--- a/drivers/power/reset/Kconfig
|
|
+++ b/drivers/power/reset/Kconfig
|
|
@@ -9,6 +9,13 @@ menuconfig POWER_RESET
|
|
|
|
if POWER_RESET
|
|
|
|
+config POWER_RESET_MESON64
|
|
+ bool "Meson64 reboot/power-off driver"
|
|
+ depends on ARCH_MESON
|
|
+ help
|
|
+ The driver supports restart / power off for amlogic
|
|
+ g12a, g12b and sm1 SoCs
|
|
+
|
|
config POWER_RESET_AS3722
|
|
bool "ams AS3722 power-off driver"
|
|
depends on MFD_AS3722
|
|
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
|
|
index d763e6735ee3..93dd2025dcf3 100644
|
|
--- a/drivers/power/reset/Makefile
|
|
+++ b/drivers/power/reset/Makefile
|
|
@@ -1,4 +1,5 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
+obj-$(CONFIG_POWER_RESET_MESON64) += meson64-reboot.o
|
|
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
|
|
obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
|
|
obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
|
|
diff --git a/drivers/power/reset/meson64-reboot.c b/drivers/power/reset/meson64-reboot.c
|
|
new file mode 100644
|
|
index 000000000000..d5e2c2633c68
|
|
--- /dev/null
|
|
+++ b/drivers/power/reset/meson64-reboot.c
|
|
@@ -0,0 +1,181 @@
|
|
+/*
|
|
+ * drivers/power/reset/meson64-reboot.c
|
|
+ *
|
|
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
+ * more details.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <linux/delay.h>
|
|
+#include <linux/err.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/reboot.h>
|
|
+
|
|
+#include <asm/system_misc.h>
|
|
+
|
|
+#include <asm/compiler.h>
|
|
+#include <linux/kdebug.h>
|
|
+#include <linux/arm-smccc.h>
|
|
+
|
|
+#include <linux/gpio.h>
|
|
+#include <linux/of_gpio.h>
|
|
+
|
|
+int sd_vqsw;
|
|
+int sd_vmmc;
|
|
+int sd_vqen;
|
|
+
|
|
+static u32 psci_function_id_restart;
|
|
+static u32 psci_function_id_poweroff;
|
|
+
|
|
+#define CHECK_RET(ret) { \
|
|
+ if (ret) \
|
|
+ pr_err("[%s] gpio op failed(%d) at line %d\n",\
|
|
+ __func__, ret, __LINE__); \
|
|
+}
|
|
+
|
|
+static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
|
|
+ u64 arg2)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ arm_smccc_smc((unsigned long)function_id,
|
|
+ (unsigned long)arg0,
|
|
+ (unsigned long)arg1,
|
|
+ (unsigned long)arg2,
|
|
+ 0, 0, 0, 0, &res);
|
|
+ return res.a0;
|
|
+}
|
|
+
|
|
+void meson64_card_reset(void)
|
|
+{
|
|
+ int ret = 0;
|
|
+
|
|
+ if ((sd_vqsw == 0) && (sd_vmmc == 0))
|
|
+ return;
|
|
+
|
|
+ if (sd_vqen == 0) {
|
|
+ gpio_free(sd_vqsw);
|
|
+ gpio_free(sd_vmmc);
|
|
+ ret = gpio_request_one(sd_vqsw,
|
|
+ GPIOF_OUT_INIT_LOW, "REBOOT");
|
|
+ CHECK_RET(ret);
|
|
+ mdelay(10);
|
|
+ ret = gpio_direction_output(sd_vqsw, 1);
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_request_one(sd_vmmc,
|
|
+ GPIOF_OUT_INIT_LOW, "REBOOT");
|
|
+ CHECK_RET(ret);
|
|
+ mdelay(10);
|
|
+ ret = gpio_direction_output(sd_vqsw, 0);
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_direction_output(sd_vmmc, 1);
|
|
+ CHECK_RET(ret);
|
|
+ mdelay(5);
|
|
+ gpio_free(sd_vqsw);
|
|
+ gpio_free(sd_vmmc);
|
|
+ } else {
|
|
+ gpio_free(sd_vqsw);
|
|
+ gpio_free(sd_vqen);
|
|
+ gpio_free(sd_vmmc);
|
|
+
|
|
+ ret = gpio_request_one(sd_vqsw,
|
|
+ GPIOF_OUT_INIT_LOW, "REBOOT");
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_request_one(sd_vqen,
|
|
+ GPIOF_OUT_INIT_LOW, "REBOOT");
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_request_one(sd_vmmc,
|
|
+ GPIOF_OUT_INIT_LOW, "REBOOT");
|
|
+ CHECK_RET(ret);
|
|
+ mdelay(100);
|
|
+ ret = gpio_direction_input(sd_vqen);
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_direction_input(sd_vmmc);
|
|
+ CHECK_RET(ret);
|
|
+ ret = gpio_direction_input(sd_vqsw);
|
|
+ CHECK_RET(ret);
|
|
+ mdelay(5);
|
|
+ gpio_free(sd_vqen);
|
|
+ gpio_free(sd_vmmc);
|
|
+ gpio_free(sd_vqsw);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void do_meson64_restart(enum reboot_mode reboot_mode, const char *cmd)
|
|
+{
|
|
+ meson64_card_reset();
|
|
+ __invoke_psci_fn_smc(psci_function_id_restart,
|
|
+ 0, 0, 0);
|
|
+}
|
|
+
|
|
+static void do_meson64_poweroff(void)
|
|
+{
|
|
+ meson64_card_reset();
|
|
+
|
|
+ __invoke_psci_fn_smc(0x82000042, 1, 0, 0);
|
|
+ __invoke_psci_fn_smc(psci_function_id_poweroff,
|
|
+ 0, 0, 0);
|
|
+}
|
|
+
|
|
+static int meson64_restart_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device_node *of_node;
|
|
+ u32 id;
|
|
+
|
|
+ if (!of_property_read_u32(pdev->dev.of_node, "sys_reset", &id)) {
|
|
+ psci_function_id_restart = id;
|
|
+ arm_pm_restart = do_meson64_restart;
|
|
+ }
|
|
+
|
|
+ if (!of_property_read_u32(pdev->dev.of_node, "sys_poweroff", &id)) {
|
|
+ psci_function_id_poweroff = id;
|
|
+ pm_power_off = do_meson64_poweroff;
|
|
+ }
|
|
+
|
|
+ of_node = pdev->dev.of_node;
|
|
+
|
|
+ sd_vqsw = of_get_named_gpio(of_node, "sd-vqsw", 0);
|
|
+ if (!gpio_is_valid(sd_vqsw)) sd_vqsw = 0;
|
|
+
|
|
+ sd_vmmc = of_get_named_gpio(of_node, "sd-vmmc", 0);
|
|
+ if (!gpio_is_valid(sd_vmmc)) sd_vmmc = 0;
|
|
+
|
|
+ sd_vqen = of_get_named_gpio(of_node, "sd-vqen", 0);
|
|
+ if (!gpio_is_valid(sd_vqen)) sd_vqen = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct of_device_id of_meson64_restart_match[] = {
|
|
+ { .compatible = "meson64,reboot", },
|
|
+ {},
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, of_meson64_restart_match);
|
|
+
|
|
+static struct platform_driver meson64_restart_driver = {
|
|
+ .probe = meson64_restart_probe,
|
|
+ .driver = {
|
|
+ .name = "meson64-restart",
|
|
+ .of_match_table = of_match_ptr(of_meson64_restart_match),
|
|
+ },
|
|
+};
|
|
+
|
|
+static int __init meson64_restart_init(void)
|
|
+{
|
|
+ return platform_driver_register(&meson64_restart_driver);
|
|
+}
|
|
+device_initcall(meson64_restart_init);
|
|
--
|
|
2.39.2
|
|
|