diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2014-06-04 15:08:23 +0200 |
---|---|---|
committer | Marek Szyprowski <m.szyprowski@samsung.com> | 2014-06-11 11:02:17 +0200 |
commit | a7f81a7dcbe3eeca4095657af97a716170116942 (patch) | |
tree | 4fe11c5bf24bcefd544ab85399afffda974210d7 | |
parent | 087b2f2da65398e0655fe84390190d5eda4a4972 (diff) | |
download | linux-3.10-a7f81a7dcbe3eeca4095657af97a716170116942.tar.gz linux-3.10-a7f81a7dcbe3eeca4095657af97a716170116942.tar.bz2 linux-3.10-a7f81a7dcbe3eeca4095657af97a716170116942.zip |
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 <m.szyprowski@samsung.com>
Change-id: I0dd05288da3d5e661772914cc853a1267609fc6d
-rw-r--r-- | arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 5 | ||||
-rw-r--r-- | arch/arm/mach-exynos/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/odroid-reboot.c | 96 |
3 files changed, 102 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi index 16000370198..9eac03cd858 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 0b539ea1bda..9f6844cf498 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 00000000000..a81a5cb863a --- /dev/null +++ b/arch/arm/mach-exynos/odroid-reboot.c @@ -0,0 +1,96 @@ +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <asm/cacheflush.h> +#include <asm/system.h> +#include <mach/regs-pmu.h> +#include <linux/gpio.h> +#include "common.h" +#include <linux/extcon.h> +#include <linux/of.h> +#include <linux/of_gpio.h> + +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); |