diff --git a/config/kernel/linux-meson64-current.config b/config/kernel/linux-meson64-current.config index ffbff07fb2..be4595bb36 100644 --- a/config/kernel/linux-meson64-current.config +++ b/config/kernel/linux-meson64-current.config @@ -4527,6 +4527,7 @@ CONFIG_POWER_RESET_BRCMSTB=y # CONFIG_POWER_RESET_GPIO_RESTART is not set # CONFIG_POWER_RESET_LTC2952 is not set # CONFIG_POWER_RESET_MT6323 is not set +CONFIG_POWER_RESET_ODROID=y # CONFIG_POWER_RESET_REGULATOR is not set CONFIG_POWER_RESET_RESTART=y # CONFIG_POWER_RESET_TPS65086 is not set diff --git a/config/kernel/linux-meson64-edge.config b/config/kernel/linux-meson64-edge.config index f3370e34a6..8a12797011 100644 --- a/config/kernel/linux-meson64-edge.config +++ b/config/kernel/linux-meson64-edge.config @@ -4554,6 +4554,7 @@ CONFIG_POWER_RESET_BRCMSTB=y # CONFIG_POWER_RESET_GPIO_RESTART is not set # CONFIG_POWER_RESET_LTC2952 is not set # CONFIG_POWER_RESET_MT6323 is not set +CONFIG_POWER_RESET_ODROID=y # CONFIG_POWER_RESET_REGULATOR is not set CONFIG_POWER_RESET_RESTART=y # CONFIG_POWER_RESET_TPS65086 is not set diff --git a/patch/kernel/archive/meson64-6.1/board-odroidc4-reset-driver.patch b/patch/kernel/archive/meson64-6.1/board-odroidc4-reset-driver.patch new file mode 100644 index 0000000000..16082fc9fe --- /dev/null +++ b/patch/kernel/archive/meson64-6.1/board-odroidc4-reset-driver.patch @@ -0,0 +1,243 @@ +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 8c30ce636..ee8aa390e 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 4b563db3a..14396a3fc 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 f606a2f60..ce0149984 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 000000000..00fedd36b +--- /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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++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); ++ diff --git a/patch/kernel/archive/meson64-6.2/board-odroidc4-reset-driver.patch b/patch/kernel/archive/meson64-6.2/board-odroidc4-reset-driver.patch new file mode 100644 index 0000000000..16082fc9fe --- /dev/null +++ b/patch/kernel/archive/meson64-6.2/board-odroidc4-reset-driver.patch @@ -0,0 +1,243 @@ +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 8c30ce636..ee8aa390e 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 4b563db3a..14396a3fc 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 f606a2f60..ce0149984 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 000000000..00fedd36b +--- /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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++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); ++