mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
commit
8b172c82cb
@ -1,3 +1,11 @@
|
||||
From c95f6c30e3230b02e90b98ca6ec8e8c2784141eb Mon Sep 17 00:00:00 2001
|
||||
From: vpeter4 <peter.vicman@gmail.com>
|
||||
Date: Thu, 21 May 2015 20:42:22 +0200
|
||||
Subject: [PATCH] Add poweroff driver.
|
||||
|
||||
Use original power_off function from rtc-snvs if set.
|
||||
Arduino operation is controled by device tree parameter.
|
||||
|
||||
From 1bc304cd507fe9eb5673223f0d76ec0aa4ff55f3 Mon Sep 17 00:00:00 2001
|
||||
From: mxt512 <mtx512@yahoo.co.uk>
|
||||
Date: Thu, 13 Feb 2014 20:13:27 +0000
|
||||
@ -7,33 +15,97 @@ Existing pm_power_off function was in rtc-snvs. Given we need to reset the SAM3X
|
||||
the 5v supply on power down, lets implement a power-off driver to do this for now.
|
||||
|
||||
TODO: Not the cleanest solution but it works, should revisit.
|
||||
Overwriting power_off function with udoo_power_off in case uddo is used.
|
||||
Overwriting power_off function with udoo_power_off in case uddo is used.
|
||||
|
||||
---
|
||||
arch/arm/boot/dts/imx6q-udoo.dts | 6 ++
|
||||
arch/arm/boot/dts/imx6q-udoo.dts | 12 ++++
|
||||
arch/arm/mach-imx/mach-imx6q.c | 44 ++++++++++++++
|
||||
drivers/power/reset/Kconfig | 8 +++
|
||||
drivers/power/reset/Makefile | 1 +
|
||||
drivers/power/reset/udoo-poweroff.c | 114 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 129 insertions(+)
|
||||
drivers/power/reset/udoo-poweroff.c | 113 ++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 178 insertions(+)
|
||||
create mode 100644 drivers/power/reset/udoo-poweroff.c
|
||||
|
||||
diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts
|
||||
index 7cc0267..1b8cce1 100644
|
||||
index 7cc0267..6c9d46f 100644
|
||||
--- a/arch/arm/boot/dts/imx6q-udoo.dts
|
||||
+++ b/arch/arm/boot/dts/imx6q-udoo.dts
|
||||
@@ -23,6 +23,12 @@
|
||||
@@ -23,6 +23,13 @@
|
||||
memory {
|
||||
reg = <0x10000000 0x40000000>;
|
||||
};
|
||||
+
|
||||
+ poweroff {
|
||||
+ compatible = "udoo,poweroff";
|
||||
+ sam3x_rst_gpio = <&gpio1 0 0>;
|
||||
+ pwr_5v_gpio = <&gpio2 4 0>;
|
||||
+ sam3x_rst_gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
|
||||
+ pwr_5v_gpio = <&gpio2 4 GPIO_ACTIVE_HIGH>;
|
||||
+ arduino_mode = <0>;
|
||||
+ };
|
||||
};
|
||||
|
||||
&fec {
|
||||
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
|
||||
index a466891..ed49659 100644
|
||||
--- a/arch/arm/mach-imx/mach-imx6q.c
|
||||
+++ b/arch/arm/mach-imx/mach-imx6q.c
|
||||
@@ -280,6 +280,46 @@ static inline void imx6q_enet_init(void)
|
||||
imx6q_1588_init();
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_POWER_RESET_UDOO
|
||||
+#define ARDUINO_MODE_STOPPED 1 /* does arduino starts at boot */
|
||||
+#define ARDUINO_MODE_LEAVE_POWER 2 /* leave 5V power on after shutdown (to keep arduino reset) */
|
||||
+
|
||||
+static inline void imx6q_udoo_gpio_init(void)
|
||||
+{
|
||||
+ struct device_node *pwr_off_np;
|
||||
+ int sam3x_rst_gpio = -EINVAL;
|
||||
+ u32 arduino_mode = -EINVAL;
|
||||
+ int ret;
|
||||
+
|
||||
+ pwr_off_np = of_find_compatible_node(NULL, NULL, "udoo,poweroff");
|
||||
+ if (pwr_off_np == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ pr_emerg("%s: setup sam3x reset gpio\n", __func__);
|
||||
+
|
||||
+ ret = of_property_read_u32(pwr_off_np, "arduino_mode", &arduino_mode);
|
||||
+ if (ret != 0) {
|
||||
+ pr_err("%s: arduino mode not found in dtb\n", __func__);
|
||||
+ arduino_mode = 0;
|
||||
+ }
|
||||
+
|
||||
+ pr_emerg("%s: arduino_mode set to %d\n", __func__, arduino_mode);
|
||||
+ sam3x_rst_gpio = of_get_named_gpio(pwr_off_np, "sam3x_rst_gpio", 0);
|
||||
+ of_node_put(pwr_off_np);
|
||||
+
|
||||
+ if (gpio_is_valid(sam3x_rst_gpio)) {
|
||||
+ if (arduino_mode & ARDUINO_MODE_STOPPED) {
|
||||
+ pr_emerg("%s: arduino stopped\n", __func__);
|
||||
+ ret = gpio_request_one(sam3x_rst_gpio, GPIOF_OUT_INIT_LOW, "sam3x_rst_gpio");
|
||||
+ } else {
|
||||
+ ret = gpio_request_one(sam3x_rst_gpio, GPIOF_OUT_INIT_HIGH, "sam3x_rst_gpio");
|
||||
+ }
|
||||
+
|
||||
+ ret = gpio_export(sam3x_rst_gpio, false);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void __init imx6q_init_machine(void)
|
||||
{
|
||||
struct device *parent;
|
||||
@@ -299,6 +339,10 @@ static void __init imx6q_init_machine(void)
|
||||
imx_anatop_init();
|
||||
cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
|
||||
imx6q_csi_mux_init();
|
||||
+
|
||||
+#ifdef CONFIG_POWER_RESET_UDOO
|
||||
+ imx6q_udoo_gpio_init();
|
||||
+#endif
|
||||
}
|
||||
|
||||
#define OCOTP_CFG3 0x440
|
||||
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
|
||||
index 6d452a7..1a0620f 100644
|
||||
--- a/drivers/power/reset/Kconfig
|
||||
@ -51,26 +123,26 @@ index 6d452a7..1a0620f 100644
|
||||
+ Say Y if you have a UDOO.
|
||||
+
|
||||
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
|
||||
index a5b4a77..b98df20 100644
|
||||
index a5b4a77..9b8e1b0 100644
|
||||
--- a/drivers/power/reset/Makefile
|
||||
+++ b/drivers/power/reset/Makefile
|
||||
@@ -4,4 +4,5 @@ obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
|
||||
@@ -5,3 +5,4 @@ obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o
|
||||
+obj-$(CONFIG_POWER_RESET_UDOO) += udoo-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o
|
||||
+obj-$(CONFIG_POWER_RESET_UDOO) += udoo-poweroff.o
|
||||
diff --git a/drivers/power/reset/udoo-poweroff.c b/drivers/power/reset/udoo-poweroff.c
|
||||
new file mode 100644
|
||||
index 0000000..0255401
|
||||
index 0000000..2a2aecf
|
||||
--- /dev/null
|
||||
+++ b/drivers/power/reset/udoo-poweroff.c
|
||||
@@ -0,0 +1,115 @@
|
||||
@@ -0,0 +1,113 @@
|
||||
+/*
|
||||
+ * UDOO board power off
|
||||
+ *
|
||||
+ *
|
||||
+ * Copyright (C) 2014 Jasbir Matharu
|
||||
+ * Copyright (C) 2015 vpeter
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
@ -87,99 +159,96 @@ index 0000000..0255401
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+
|
||||
+#define SNVS_LPCR 0x04
|
||||
+#define ARDUINO_MODE_STOPPED 1 /* does arduino starts at boot */
|
||||
+#define ARDUINO_MODE_LEAVE_POWER 2 /* leave 5V power on after shutdown (to keep arduino reset) */
|
||||
+
|
||||
+static int sam3x_rst_gpio,pwr_5v_gpio;
|
||||
+static void (*pm_power_off_orig)(void) = NULL;
|
||||
+static int sam3x_rst_gpio = -EINVAL;
|
||||
+static int pwr_5v_gpio = -EINVAL;
|
||||
+static u32 arduino_mode = -EINVAL;
|
||||
+
|
||||
+static void udoo_power_off(void) {
|
||||
+ struct device_node *snvs_np;
|
||||
+ void __iomem *mx6_snvs_base;
|
||||
+ u32 value;
|
||||
+ int ret;
|
||||
+
|
||||
+ pr_info("Powering off udoo\n");
|
||||
+ pr_emerg("%s: powering off\n", __func__);
|
||||
+ if (pm_power_off_orig != NULL)
|
||||
+ pm_power_off_orig();
|
||||
+
|
||||
+ snvs_np = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0-mon-rtc-lp");
|
||||
+ if (!snvs_np) {
|
||||
+ pr_err("%s: failed to find sec-v4.0-mon-rtc-lp node\n",__func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (gpio_is_valid(sam3x_rst_gpio)) {
|
||||
+ pr_emerg("%s: sam3x reset\n", __func__);
|
||||
+ ret = gpio_direction_output(sam3x_rst_gpio, 0);
|
||||
+ if (ret)
|
||||
+ pr_emerg("%s: sam3x reset unsuccessful\n", __func__);
|
||||
+
|
||||
+ mx6_snvs_base = of_iomap(snvs_np, 0);
|
||||
+ if (!mx6_snvs_base) {
|
||||
+ pr_err("%s: failed to map sec-v4.0-mon-rtc-lp\n",__func__);
|
||||
+ goto put_snvs_node;
|
||||
+ }
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+
|
||||
+ value = readl(mx6_snvs_base + SNVS_LPCR);
|
||||
+ /*set TOP and DP_EN bit*/
|
||||
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
|
||||
+
|
||||
+ gpio_request_one(sam3x_rst_gpio, GPIOF_OUT_INIT_LOW,"sam3x_rst_gpio"),
|
||||
+ msleep(5);
|
||||
+ gpio_request_one(pwr_5v_gpio, GPIOF_OUT_INIT_HIGH,"pwr_5v_gpio");
|
||||
+
|
||||
+put_snvs_node:
|
||||
+ of_node_put(snvs_np);
|
||||
+ if (gpio_is_valid(pwr_5v_gpio) && (arduino_mode & ARDUINO_MODE_LEAVE_POWER) == 0) {
|
||||
+ pr_emerg("%s: 5V power down\n", __func__);
|
||||
+ ret = gpio_request_one(pwr_5v_gpio, GPIOF_OUT_INIT_HIGH, "pwr_5v_gpio");
|
||||
+ if (ret)
|
||||
+ pr_emerg("%s: 5V power down unsuccessful\n", __func__);
|
||||
+ } else
|
||||
+ pr_emerg("%s: 5V power still on, sam3x reset\n", __func__);
|
||||
+}
|
||||
+
|
||||
+static int udoo_power_off_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device_node *pwr_off_np;
|
||||
+ struct device_node *pwr_off_np;
|
||||
+ int ret;
|
||||
+
|
||||
+ pwr_off_np = of_find_compatible_node(NULL, NULL, "udoo,poweroff");
|
||||
+ if (pwr_off_np) {
|
||||
+ of_node_put(pwr_off_np);
|
||||
+ /* udoo dtb loaded, run poweroff function from
|
||||
+ here and not snvs_poweroff */
|
||||
+ pr_err("%s: pm_power_off function already registered, overwriting with ours", __func__);
|
||||
+ pr_emerg("%s: power-off probe\n", __func__);
|
||||
+
|
||||
+ sam3x_rst_gpio = of_get_named_gpio(pdev->dev.of_node, "sam3x_rst_gpio", 0);
|
||||
+ pwr_5v_gpio = of_get_named_gpio(pdev->dev.of_node, "pwr_5v_gpio", 0);
|
||||
+ if (gpio_is_valid(sam3x_rst_gpio) && gpio_is_valid(pwr_5v_gpio)) {
|
||||
+ } else {
|
||||
+ pr_err("%s : failed to find sam3x_rst_gpio or pwr_5v_gpio property \n",__func__);
|
||||
+ return ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ pm_power_off = udoo_power_off;
|
||||
+ pr_info("%s: ok\n",__func__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ pwr_off_np = of_find_compatible_node(NULL, NULL, "udoo,poweroff");
|
||||
+ if (pwr_off_np) {
|
||||
+ ret = of_property_read_u32(pwr_off_np, "arduino_mode", &arduino_mode);
|
||||
+ if (ret != 0) {
|
||||
+ pr_emerg("%s: arduino mode not found in dtb\n", __func__);
|
||||
+ arduino_mode = 0;
|
||||
+ }
|
||||
+
|
||||
+ /* If a pm_power_off function has already been added, leave it alone */
|
||||
+ if (pm_power_off != NULL) {
|
||||
+ pr_err("%s: pm_power_off function already registered",
|
||||
+ __func__);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+ sam3x_rst_gpio = of_get_named_gpio(pwr_off_np, "sam3x_rst_gpio", 0);
|
||||
+ pwr_5v_gpio = of_get_named_gpio(pwr_off_np, "pwr_5v_gpio", 0);
|
||||
+ of_node_put(pwr_off_np);
|
||||
+
|
||||
+ return -ENODEV;
|
||||
+ pm_power_off_orig = pm_power_off;
|
||||
+ pm_power_off = udoo_power_off;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* If a pm_power_off function has already been added, leave it alone */
|
||||
+ if (pm_power_off != NULL) {
|
||||
+ pr_emerg("%s: pm_power_off function already registered\n", __func__);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
+
|
||||
+static int udoo_power_off_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ return 0;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id power_off_dt_ids[] = {
|
||||
+ { .compatible = "udoo,poweroff", },
|
||||
+ { /* sentinel */ }
|
||||
+ { .compatible = "udoo,poweroff", },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, power_off_dt_ids);
|
||||
+
|
||||
+static struct platform_driver udoo_power_off_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "udoo_power_off",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = of_match_ptr(power_off_dt_ids),
|
||||
+ },
|
||||
+ .probe = udoo_power_off_probe,
|
||||
+ .remove = udoo_power_off_remove,
|
||||
+ .driver = {
|
||||
+ .name = "udoo_power_off",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = of_match_ptr(power_off_dt_ids),
|
||||
+ },
|
||||
+ .probe = udoo_power_off_probe,
|
||||
+ .remove = udoo_power_off_remove,
|
||||
+};
|
||||
+module_platform_driver(udoo_power_off_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Jasbir Matharu");
|
||||
+MODULE_DESCRIPTION("UDOO Power off driver");
|
||||
+MODULE_AUTHOR("Jasbir Matharu, vpeter");
|
||||
+MODULE_DESCRIPTION("UDOO Power off driver v2");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
--
|
||||
1.8.1.2
|
||||
|
@ -59,21 +59,19 @@ diff -ruN linux-cuboxi-3.14-dc5edb8-original/arch/arm/mach-imx/clk-imx6q.c linux
|
||||
imx6q_set_lpm(WAIT_CLOCKED);
|
||||
|
||||
diff -ruN linux-cuboxi-3.14-dc5edb8-original/arch/arm/mach-imx/mach-imx6q.c linux-cuboxi-3.14-dc5edb8/arch/arm/mach-imx/mach-imx6q.c
|
||||
--- linux-cuboxi-3.14-dc5edb8-original/arch/arm/mach-imx/mach-imx6q.c 2015-02-16 21:54:12.278970657 +0100
|
||||
+++ linux-cuboxi-3.14-dc5edb8/arch/arm/mach-imx/mach-imx6q.c 2015-02-16 21:55:13.970971815 +0100
|
||||
@@ -364,6 +364,12 @@
|
||||
--- linux-cuboxi-3.14-dc5edb8-original/arch/arm/mach-imx/mach-imx6q.c 2015-05-22 19:56:02.761641828 +0200
|
||||
+++ linux-cuboxi-3.14-dc5edb8/arch/arm/mach-imx/mach-imx6q.c 2015-05-22 19:57:22.608235000 +0200
|
||||
@@ -387,6 +387,10 @@
|
||||
if (dev_pm_opp_disable(cpu_dev, 852000000))
|
||||
pr_warn("failed to disable 850 MHz OPP\n");
|
||||
}
|
||||
+ if (IS_ENABLED(CONFIG_MX6_VPU_352M)) {
|
||||
+ if (dev_pm_opp_disable(cpu_dev, 396000000)) {
|
||||
+ if (dev_pm_opp_disable(cpu_dev, 396000000))
|
||||
+ pr_warn("failed to disable 396MHz OPP\n");
|
||||
+ pr_info("remove 396MHz OPP for VPU running at 352MHz!\n");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
put_node:
|
||||
of_node_put(np);
|
||||
static void __init imx6q_opp_init(void)
|
||||
diff -ruN linux-cuboxi-3.14-dc5edb8-original/drivers/cpufreq/imx6-cpufreq.c linux-cuboxi-3.14-dc5edb8/drivers/cpufreq/imx6-cpufreq.c
|
||||
--- linux-cuboxi-3.14-dc5edb8-original/drivers/cpufreq/imx6-cpufreq.c 2015-02-16 21:54:09.350970602 +0100
|
||||
+++ linux-cuboxi-3.14-dc5edb8/drivers/cpufreq/imx6-cpufreq.c 2015-02-16 21:55:49.778972488 +0100
|
||||
|
Loading…
x
Reference in New Issue
Block a user