From: Marek Szyprowski Date: Wed, 4 Jun 2014 13:08:23 +0000 (+0200) Subject: ARM: Exynos: fix reboot hang on Odroid X2/U2/U3 with eMMC memory X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fdab6e6c789885f5fc552db87279c596f98bcc74;p=platform%2Fkernel%2Flinux-3.10.git ARM: Exynos: fix reboot hang on Odroid X2/U2/U3 with eMMC memory Odroid X/X2/U2/U3 require special handling of SD4_nRESET_OUT line for eMMC memory to perform complete reboot. This patch adds code for performing such reset. Signed-off-by: Marek Szyprowski Change-id: I0dd05288da3d5e661772914cc853a1267609fc6d --- diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 1600037..9eac03c 100644 --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi @@ -516,6 +516,11 @@ vdd_pll-supply = <&ldo8_reg>; status = "okay"; }; + + odroid_reboot { + compatible = "hardkernel,odroid-reboot"; + reset-gpio = <&gpk1 2 0>; + }; }; &pinctrl_1 { diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 0b539ea..9f6844c 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o obj-$(CONFIG_ARCH_EXYNOS4) += sec-reboot.o +obj-$(CONFIG_ARCH_EXYNOS4) += odroid-reboot.o # device support diff --git a/arch/arm/mach-exynos/odroid-reboot.c b/arch/arm/mach-exynos/odroid-reboot.c new file mode 100644 index 0000000..a81a5cb --- /dev/null +++ b/arch/arm/mach-exynos/odroid-reboot.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include +#include +#include + +struct odroid_reboot_platform_data { + struct device *dev; + int power_gpio; +}; + +static struct odroid_reboot_platform_data *g_pdata; + +static void odroid_reboot(char str, const char *cmd) +{ + local_irq_disable(); + + writel(0x12345678, S5P_INFORM2); /* Don't enter lpm mode */ + writel(0x0, S5P_INFORM4); /* Reset reboot count */ + + gpio_set_value(g_pdata->power_gpio, 0); + mdelay(150); + gpio_set_value(g_pdata->power_gpio, 1); + + flush_cache_all(); + outer_flush_all(); + + exynos4_restart(0, 0); + + pr_emerg("%s: waiting for reboot\n", __func__); + while (1) + ; +} + +static struct odroid_reboot_platform_data *odroid_reboot_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct odroid_reboot_platform_data *pdata; + + pdata = devm_kzalloc(dev, sizeof(struct odroid_reboot_platform_data), + GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->power_gpio = of_get_named_gpio(np, "reset-gpio", 0); + if (!gpio_is_valid(pdata->power_gpio)) { + dev_err(dev, "invalied power-gpio\n"); + return NULL; + } + devm_gpio_request(dev, pdata->power_gpio, "reset-gpio"); + + return pdata; +} + +static int odroid_reboot_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + if (pdev->dev.of_node) + g_pdata = odroid_reboot_parse_dt(dev); + + if (!g_pdata) { + dev_err(&pdev->dev, "failed to get platform data\n"); + return -EINVAL; + } + + g_pdata->dev = &pdev->dev; + + /* Set machine specific functions */ + arm_pm_restart = odroid_reboot; + + return 0; +} + +static struct of_device_id odroid_reboot_of_match[] = { + { .compatible = "hardkernel,odroid-reboot", }, + { }, +}; + +static struct platform_driver odroid_reboot_driver = { + .probe = odroid_reboot_probe, + .driver = { + .name = "odroid-reboot", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(odroid_reboot_of_match), + } +}; + +module_platform_driver(odroid_reboot_driver);