armbian_build/patch/kernel/archive/meson64-6.2/board-odroidc4-reset-driver.patch

261 lines
7.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ash Hughes <spirit.returned@gmail.com>
Date: Sat, 18 Feb 2023 07:46:38 -0300
Subject: adapted odroid-reboot driver, fix reboot on odroid C4 when using
UHS-II SD cards
bring back fixed version of `odroid-reboot` driver (Fix reboot on odroid C4 when using UHS-II SD cards)
---
arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dts | 10 +
drivers/power/reset/Kconfig | 7 +
drivers/power/reset/Makefile | 1 +
drivers/power/reset/odroid-reboot.c | 186 ++++++++++
4 files changed, 204 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dts
index 8c30ce63686e..ee8aa390ea56 100644
--- a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid-c4.dts
@@ -11,6 +11,16 @@ / {
compatible = "hardkernel,odroid-c4", "amlogic,sm1";
model = "Hardkernel ODROID-C4";
+ odroid-reboot {
+ compatible = "odroid,reboot";
+ sys_reset = <0x84000009>;
+ sys_poweroff = <0x84000008>;
+
+ sd-vqen = <&gpio_ao GPIOE_2 GPIO_ACTIVE_HIGH>;
+ sd-vqsw = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>;
+ sd-vmmc = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+ };
+
leds {
compatible = "gpio-leds";
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index a8c46ba5878f..f685772c8213 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -141,6 +141,13 @@ config POWER_RESET_OCELOT_RESET
help
This driver supports restart for Microsemi Ocelot SoC and similar.
+config POWER_RESET_ODROID
+ bool "odroid reboot/power-off driver"
+ depends on ARCH_MESON
+ help
+ This driver supports restart / power off board for amlogic
+ g12a/g12b/sm1 SoCs
+
config POWER_RESET_OXNAS
bool "OXNAS SoC restart driver"
depends on ARCH_OXNAS
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 0a39424fc558..b58a4f2891db 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
+obj-$(CONFIG_POWER_RESET_ODROID) += odroid-reboot.o
obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o
obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
diff --git a/drivers/power/reset/odroid-reboot.c b/drivers/power/reset/odroid-reboot.c
new file mode 100644
index 000000000000..0339718b4a80
--- /dev/null
+++ b/drivers/power/reset/odroid-reboot.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: (GPL-2.0)
+/*
+ * drivers/power/reset/odroid-reboot.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2023 Ash Hughes (sehguh.hsa@gmail.com)
+ *
+ * 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 odroid_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 int do_odroid_restart(struct notifier_block *this, unsigned long mode, void *cmd)
+{
+ odroid_card_reset();
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block odroid_restart_handler = {
+ .notifier_call = do_odroid_restart,
+ .priority = 130,
+};
+
+static void do_odroid_poweroff(void)
+{
+ odroid_card_reset();
+
+ __invoke_psci_fn_smc(0x82000042, 1, 0, 0);
+}
+
+static int odroid_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;
+ register_restart_handler(&odroid_restart_handler);
+ }
+
+ if (!of_property_read_u32(pdev->dev.of_node, "sys_poweroff", &id)) {
+ psci_function_id_poweroff = id;
+ pm_power_off = do_odroid_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_odroid_restart_match[] = {
+ { .compatible = "odroid,reboot", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_odroid_restart_match);
+
+static struct platform_driver odroid_restart_driver = {
+ .probe = odroid_restart_probe,
+ .driver = {
+ .name = "odroid-restart",
+ .of_match_table = of_match_ptr(of_odroid_restart_match),
+ },
+};
+
+static int __init odroid_restart_init(void)
+{
+ return platform_driver_register(&odroid_restart_driver);
+}
+device_initcall(odroid_restart_init);
+
--
Armbian