diff --git a/MAINTAINERS b/MAINTAINERS index 3d687daf9b88..ebeba16627f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13459,3 +13459,7 @@ AMLOGIC EFUSE DRIVER M: Yun Cai F: drivers/amlogic/efuse/* F: include/linux/amlogic/efuse.h + +AMLOGIC reboot +M: Jianxin Pan +F: drivers/amlogic/reboot/* diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index 030d48ab93bc..d81e02d00916 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -747,5 +747,11 @@ size = <16>; }; }; + + aml_reboot { + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index 755a768ab890..f5bfdcaaec7f 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -792,5 +792,11 @@ size = <16>; }; }; + + aml_reboot{ + compatible = "aml, reboot"; + sys_reset = <0x84000009>; + sys_poweroff = <0x84000008>; + }; }; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 76f43863790d..c8fa81963082 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -173,6 +173,7 @@ CONFIG_AMLOGIC_INPUT_KEYBOARD=y CONFIG_AMLOGIC_ADC_KEYPADS=y CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_EFUSE=y +CONFIG_AMLOGIC_REBOOT=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y diff --git a/drivers/amlogic/Kconfig b/drivers/amlogic/Kconfig index 32d6f78da28f..09621adec072 100644 --- a/drivers/amlogic/Kconfig +++ b/drivers/amlogic/Kconfig @@ -36,5 +36,7 @@ source "drivers/amlogic/crypto/Kconfig" source "drivers/amlogic/input/Kconfig" source "drivers/amlogic/efuse/Kconfig" + +source "drivers/amlogic/reboot/Kconfig" endmenu endif diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index be67faed62bf..3c456d57e947 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -33,3 +33,5 @@ obj-$(CONFIG_AMLOGIC_CRYPTO) += crypto/ obj-$(CONFIG_AMLOGIC_INPUT) += input/ obj-$(CONFIG_AMLOGIC_EFUSE) += efuse/ + +obj-$(CONFIG_AMLOGIC_REBOOT) += reboot/ diff --git a/drivers/amlogic/reboot/Kconfig b/drivers/amlogic/reboot/Kconfig new file mode 100644 index 000000000000..08a40f5838e3 --- /dev/null +++ b/drivers/amlogic/reboot/Kconfig @@ -0,0 +1,10 @@ +# Amlogic POWER OFF +config AMLOGIC_REBOOT + bool "Amlogic Board level reboot or power off" + default n + help + This is the Amlogic + Board reboot + or poweroff + driver. + diff --git a/drivers/amlogic/reboot/Makefile b/drivers/amlogic/reboot/Makefile new file mode 100644 index 000000000000..46f57713906e --- /dev/null +++ b/drivers/amlogic/reboot/Makefile @@ -0,0 +1,5 @@ +# +#Makefile for the RESET dirver +# +obj-$(CONFIG_AMLOGIC_REBOOT) += reboot.o + diff --git a/drivers/amlogic/reboot/reboot.c b/drivers/amlogic/reboot/reboot.c new file mode 100644 index 000000000000..27173fee8c95 --- /dev/null +++ b/drivers/amlogic/reboot/reboot.c @@ -0,0 +1,160 @@ +/* + * drivers/amlogic/reboot/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +static u32 psci_function_id_restart; +static u32 psci_function_id_poweroff; +static char *kernel_panic; +static u32 parse_reason(const char *cmd) +{ + u32 reboot_reason = MESON_NORMAL_BOOT; + + if (cmd) { + if (strcmp(cmd, "recovery") == 0 || + strcmp(cmd, "factory_reset") == 0) + reboot_reason = MESON_FACTORY_RESET_REBOOT; + else if (strcmp(cmd, "update") == 0) + reboot_reason = MESON_UPDATE_REBOOT; + else if (strcmp(cmd, "fastboot") == 0) + reboot_reason = MESON_FASTBOOT_REBOOT; + else if (strcmp(cmd, "bootloader") == 0) + reboot_reason = MESON_BOOTLOADER_REBOOT; + else if (strcmp(cmd, "report_crash") == 0) + reboot_reason = MESON_CRASH_REBOOT; + else if (strcmp(cmd, "uboot_suspend") == 0) + reboot_reason = MESON_UBOOT_SUSPEND; + } else { + if (kernel_panic) { + if (strcmp(kernel_panic, "kernel_panic") == 0) + reboot_reason = MESON_KERNEL_PANIC; + } + + } + + pr_info("reboot reason %d\n", reboot_reason); + return reboot_reason; +} +static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, + u64 arg2) +{ + register long x0 asm("x0") = function_id; + register long x1 asm("x1") = arg0; + register long x2 asm("x2") = arg1; + register long x3 asm("x3") = arg2; + asm volatile( + __asmeq("%0", "x0") + __asmeq("%1", "x1") + __asmeq("%2", "x2") + __asmeq("%3", "x3") + "smc #0\n" + : "+r" (x0) + : "r" (x1), "r" (x2), "r" (x3)); + + return function_id; +} +void meson_smc_restart(u64 function_id, u64 reboot_reason) +{ + __invoke_psci_fn_smc(function_id, + reboot_reason, 0, 0); +} +void meson_common_restart(char mode, const char *cmd) +{ + u32 reboot_reason = parse_reason(cmd); + + if (psci_function_id_restart) + meson_smc_restart((u64)psci_function_id_restart, + (u64)reboot_reason); +} +static void do_aml_restart(enum reboot_mode reboot_mode, const char *cmd) +{ + meson_common_restart(reboot_mode, cmd); +} + +static void do_aml_poweroff(void) +{ + /* TODO: Add poweroff capability */ + __invoke_psci_fn_smc(0x82000042, 1, 0, 0); + __invoke_psci_fn_smc(psci_function_id_poweroff, + 0, 0, 0); +} +static int panic_notify(struct notifier_block *self, + unsigned long cmd, void *ptr) +{ + kernel_panic = "kernel_panic"; + + return NOTIFY_DONE; +} + +static struct notifier_block panic_notifier = { + .notifier_call = panic_notify, +}; + +static int aml_restart_probe(struct platform_device *pdev) +{ + u32 id; + int ret; + + if (!of_property_read_u32(pdev->dev.of_node, "sys_reset", &id)) { + psci_function_id_restart = id; + arm_pm_restart = do_aml_restart; + } + + if (!of_property_read_u32(pdev->dev.of_node, "sys_poweroff", &id)) { + psci_function_id_poweroff = id; + pm_power_off = do_aml_poweroff; + } + + ret = register_die_notifier(&panic_notifier); + return ret; +} + +static const struct of_device_id of_aml_restart_match[] = { + { .compatible = "aml, reboot", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_aml_restart_match); + +static struct platform_driver aml_restart_driver = { + .probe = aml_restart_probe, + .driver = { + .name = "aml-restart", + .of_match_table = of_match_ptr(of_aml_restart_match), + }, +}; + +static int __init aml_restart_init(void) +{ + return platform_driver_register(&aml_restart_driver); +} +device_initcall(aml_restart_init); diff --git a/include/linux/amlogic/reboot.h b/include/linux/amlogic/reboot.h new file mode 100644 index 000000000000..f0f022afa009 --- /dev/null +++ b/include/linux/amlogic/reboot.h @@ -0,0 +1,28 @@ +/* + * include/linux/amlogic/reboot.h + * + * 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. + * + */ + +/*******************************************************************/ +#define MESON_COLD_REBOOT 0 +#define MESON_NORMAL_BOOT 1 +#define MESON_FACTORY_RESET_REBOOT 2 +#define MESON_UPDATE_REBOOT 3 +#define MESON_FASTBOOT_REBOOT 4 +#define MESON_UBOOT_SUSPEND 5 +#define MESON_HIBERNATE 6 +#define MESON_BOOTLOADER_REBOOT 7 +#define MESON_CRASH_REBOOT 11 +#define MESON_KERNEL_PANIC 12