diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts index 932037682286..c356e40ed3ed 100644 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts +++ b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts @@ -375,6 +375,11 @@ status = "disabled"; }; +&reboot { + sd_volsw_gpio = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>; + sd_power_gpio = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>; +}; + &sd_emmc_b { status = "okay"; sd-uhs-sdr25; diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi index 91f2b2220392..113dd780d3bc 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12b_a.dtsi @@ -327,7 +327,7 @@ cpuinfo_cmd = <0x82000044>; }; - aml_reboot{ + reboot: aml_reboot{ compatible = "aml, reboot"; sys_reset = <0x84000009>; sys_poweroff = <0x84000008>; diff --git a/drivers/amlogic/reboot/reboot.c b/drivers/amlogic/reboot/reboot.c index 94b11535d762..f2db4b5b42a7 100644 --- a/drivers/amlogic/reboot/reboot.c +++ b/drivers/amlogic/reboot/reboot.c @@ -35,9 +35,24 @@ #include static void __iomem *reboot_reason_vaddr; + +#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) +#include +#include + +int sd_volsw_gpio; +int sd_power_gpio; +#define CHECK_RET(ret) { \ + if (ret) \ + pr_err("[%s] gpio op failed(%d) at line %d\n",\ + __func__, ret, __LINE__); \ +} +#endif + 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; @@ -107,8 +122,41 @@ void meson_common_restart(char mode, const char *cmd) meson_smc_restart((u64)psci_function_id_restart, (u64)reboot_reason); } + +#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) +void odroid_card_reset(void) +{ + int ret = 0; + + if ((sd_volsw_gpio == 0) && (sd_power_gpio == 0)) + return; + + gpio_free(sd_volsw_gpio); + gpio_free(sd_power_gpio); + ret = gpio_request_one(sd_volsw_gpio, + GPIOF_OUT_INIT_LOW, "REBOOT"); + CHECK_RET(ret); + mdelay(10); + ret = gpio_direction_output(sd_volsw_gpio, 1); + CHECK_RET(ret); + ret = gpio_request_one(sd_power_gpio, + GPIOF_OUT_INIT_LOW, "REBOOT"); + CHECK_RET(ret); + mdelay(10); + ret = gpio_direction_output(sd_volsw_gpio, 0); + CHECK_RET(ret); + ret = gpio_direction_output(sd_power_gpio, 1); + CHECK_RET(ret); + mdelay(5); + gpio_free(sd_volsw_gpio); + gpio_free(sd_power_gpio); +} +#endif // CONFIG_ARCH_MESON64_ODROID_COMMON static void do_aml_restart(enum reboot_mode reboot_mode, const char *cmd) { +#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) + odroid_card_reset(); +#endif meson_common_restart(reboot_mode, cmd); } @@ -149,6 +197,9 @@ DEVICE_ATTR(reboot_reason, 0444, reboot_reason_show, NULL); static int aml_restart_probe(struct platform_device *pdev) { +#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) + struct device_node *of_node; +#endif u32 id; int ret; u32 paddr = 0; @@ -171,6 +222,15 @@ static int aml_restart_probe(struct platform_device *pdev) device_create_file(&pdev->dev, &dev_attr_reboot_reason); } +#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON) + of_node = pdev->dev.of_node; + sd_volsw_gpio = 0; + sd_power_gpio = 0; + + sd_volsw_gpio = of_get_named_gpio(of_node, "sd_volsw_gpio", 0); + sd_power_gpio = of_get_named_gpio(of_node, "sd_power_gpio", 0); +#endif + ret = register_die_notifier(&panic_notifier); if (ret != 0) { pr_err("%s,register die notifier failed,ret =%d!\n",