summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott D Phillips <scott.d.phillips@intel.com>2015-09-21 13:39:29 -0700
committerBrian Wood <brian.j.wood@intel.com>2015-09-23 15:31:28 -0700
commitadf5722c0141e429b4a1c66885a187edfb1173f0 (patch)
tree6d7fda385db5656a674ea1c43b6ce4f60ed7fb34
parent72683e74f8012153d079471c0ebb7ed60459c1df (diff)
downloadintel-adf5722c0141e429b4a1c66885a187edfb1173f0.tar.gz
staging: android: Add Intel reboot reason driver
This is derived from the osip driver on fugu, although largely lobotomized because we don't need the OSIP futzing. Change-Id: Ia1f587357170df7a2efb696870fdac78edb43f52 Signed-off-by: Scott D Phillips <scott.d.phillips@intel.com> Reviewed-on: https://android.intel.com/414299 Tested-by: cactus <cactus@intel.com> Reviewed-by: Wood, Brian J <brian.j.wood@intel.com>
-rw-r--r--drivers/staging/android/Kconfig2
-rw-r--r--drivers/staging/android/Makefile1
-rw-r--r--drivers/staging/android/reboot/Kconfig18
-rw-r--r--drivers/staging/android/reboot/Makefile2
-rw-r--r--drivers/staging/android/reboot/intel_scu_reboot_reason.c124
-rw-r--r--drivers/staging/android/reboot/reboot_target.c163
-rw-r--r--drivers/staging/android/reboot/reboot_target.h30
7 files changed, 340 insertions, 0 deletions
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index b3c054e4fd5..ef104169a8e 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -75,6 +75,8 @@ source "drivers/staging/android/ion/Kconfig"
source "drivers/staging/android/fiq_debugger/Kconfig"
+source "drivers/staging/android/reboot/Kconfig"
+
endif # if ANDROID
endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index 30ba2f0cb08..f09945e1bbb 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -2,6 +2,7 @@ ccflags-y += -I$(src) # needed for trace events
obj-y += ion/
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
+obj-y += reboot/
obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
diff --git a/drivers/staging/android/reboot/Kconfig b/drivers/staging/android/reboot/Kconfig
new file mode 100644
index 00000000000..0094696e089
--- /dev/null
+++ b/drivers/staging/android/reboot/Kconfig
@@ -0,0 +1,18 @@
+#
+# X86 Platform Specific Drivers
+#
+
+config INTEL_SCU_REBOOT_REASON
+ tristate "osip driver for Intel MID platforms"
+ default y
+ depends on INTEL_REBOOT_TARGET && INTEL_SCU_IPC
+ help
+ This driver squirrels away the reboot reason with the SCU.
+
+ If unsure, say N.
+
+config INTEL_REBOOT_TARGET
+ bool "Intel Reboot Target"
+ ---help---
+ This driver provides a generic implementation for reboot target setting at
+ reset time.
diff --git a/drivers/staging/android/reboot/Makefile b/drivers/staging/android/reboot/Makefile
new file mode 100644
index 00000000000..6ee5f823135
--- /dev/null
+++ b/drivers/staging/android/reboot/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_INTEL_SCU_REBOOT_REASON) += intel_scu_reboot_reason.o
+obj-$(CONFIG_INTEL_REBOOT_TARGET) += reboot_target.o
diff --git a/drivers/staging/android/reboot/intel_scu_reboot_reason.c b/drivers/staging/android/reboot/intel_scu_reboot_reason.c
new file mode 100644
index 00000000000..aacb88181e2
--- /dev/null
+++ b/drivers/staging/android/reboot/intel_scu_reboot_reason.c
@@ -0,0 +1,124 @@
+/*
+ * Reboot Reason driver for Edison, derived from SCURR driver for Medfield.
+ *
+ * Copyright (C) 2015,2011 Intel Corp
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/reboot.h>
+#include <linux/pagemap.h>
+#include <linux/blkdev.h>
+#include <linux/debugfs.h>
+#include <linux/genhd.h>
+#include <linux/seq_file.h>
+#include <linux/rpmsg.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 1))
+#include <linux/platform_data/intel_mid_remoteproc.h>
+#else
+#include <asm/intel_mid_remoteproc.h>
+#endif
+#include <linux/delay.h>
+#include <asm/intel_scu_ipcutil.h>
+#include <asm/intel_mid_rpmsg.h>
+#include <asm/intel-mid.h>
+
+#include "reboot_target.h"
+
+#include <asm/intel_scu_ipc.h>
+#include <linux/power_supply.h>
+
+static int scurr_reboot_target_call(const char *target, int id)
+{
+ int ret_ipc;
+
+ pr_info("%s: notified [%s] target\n", __func__, target);
+
+ pr_warn("[REBOOT] %s, rebooting into %s\n", __func__, target);
+
+ ret_ipc = intel_scu_ipc_write_osnib_rr(id);
+ if (ret_ipc < 0)
+ pr_err("%s cannot write %s reboot reason in OSNIB\n",
+ __func__, target);
+ return NOTIFY_DONE;
+}
+
+static struct reboot_target scurr_reboot_target = {
+ .set_reboot_target = scurr_reboot_target_call,
+};
+
+static int scurr_init(void)
+{
+ pr_info("%s: reboot_target registered\n", __func__);
+ if (reboot_target_register(&scurr_reboot_target))
+ pr_warning("scurr: unable to register reboot notifier");
+
+ return 0;
+}
+
+static void scurr_exit(void)
+{
+ pr_info("%s: reboot_target unregistered\n", __func__);
+ reboot_target_unregister(&scurr_reboot_target);
+}
+
+static int __init scurr_probe(struct platform_device *dev)
+{
+ return scurr_init();
+}
+
+static int scurr_remove(struct platform_device *dev)
+{
+ scurr_exit();
+ return 0;
+}
+
+static struct platform_driver scurr_driver = {
+ .remove = scurr_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ },
+};
+
+static int __init scurr_init_module(void)
+{
+ int err=0;
+
+ pr_info("Intel SCURR Driver\n");
+
+ platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
+ err = platform_driver_probe(&scurr_driver,scurr_probe);
+
+ return err;
+}
+
+static void __exit scurr_cleanup_module(void)
+{
+ platform_driver_unregister(&scurr_driver);
+ pr_info("SCURR Module Unloaded\n");
+}
+module_init(scurr_init_module);
+module_exit(scurr_cleanup_module);
+
+MODULE_AUTHOR("Pierre Tardy <pierre.tardy@intel.com>");
+MODULE_AUTHOR("Xiaokang Qin <xiaokang.qin@intel.com>");
+MODULE_DESCRIPTION("Intel SCU Reboot Reason Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/reboot/reboot_target.c b/drivers/staging/android/reboot/reboot_target.c
new file mode 100644
index 00000000000..3c9696c373c
--- /dev/null
+++ b/drivers/staging/android/reboot/reboot_target.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2013 Intel Corp
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/module.h>
+
+#include "reboot_target.h"
+
+/* Currently registered Reboot Target setter */
+static struct reboot_target *var;
+
+struct name2id {
+ const char *name;
+ int id;
+};
+
+static const unsigned int DEFAULT_TARGET_INDEX = 0;
+
+static const struct name2id NAME2ID[] = {
+ { "main", 0x00 },
+ { "android", 0x00 },
+ { "charging", 0x0A },
+ { "recovery", 0x0C },
+ { "fastboot", 0x0E },
+ { "bootloader", 0x0E },
+ { "factory", 0x12 },
+ { "dnx", 0x14 },
+ { "ramconsole", 0x16 },
+ { "factory2", 0x18 },
+ { "bootoneshot", 0x1A },
+};
+
+#define ALLOW_FACTORY_PARAM_NAME "allow_factory="
+
+static int reboot_target_name2id(const char *name)
+{
+ int i;
+ char *allow_factory;
+
+ allow_factory = strstr(saved_command_line, ALLOW_FACTORY_PARAM_NAME);
+ if (!allow_factory && strstr(name, "factory"))
+ return NAME2ID[DEFAULT_TARGET_INDEX].id;
+
+ for (i = 0; i < ARRAY_SIZE(NAME2ID); i++)
+ if (!strcmp(NAME2ID[i].name, name))
+ return NAME2ID[i].id;
+
+ return -EINVAL;
+}
+
+const char *reboot_target_id2name(int id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(NAME2ID); i++)
+ if (NAME2ID[i].id == id)
+ return NAME2ID[i].name;
+
+ return "";
+}
+
+static int set_reboot_target(const char *name)
+{
+ int id;
+
+ if (name == NULL) {
+ pr_err("Error in %s: NULL target\n", __func__);
+ return -EINVAL;
+ }
+
+ id = reboot_target_name2id(name);
+ if (id < 0) {
+ pr_err("Error in %s: '%s' is not a valid target\n",
+ __func__, name );
+ return -EINVAL;
+ }
+
+ return var ? var->set_reboot_target(name, id) : -ENODEV;
+}
+
+static int reboot_target_notify(struct notifier_block *notifier,
+ unsigned long what, void *data)
+{
+ const char *target = (const char *)data;
+ int ret;
+
+ if (what != SYS_RESTART)
+ goto out;
+
+ if (!target || target[0] == '\0')
+ target = NAME2ID[DEFAULT_TARGET_INDEX].name;
+
+ ret = set_reboot_target(target);
+ if (ret)
+ pr_err("%s: Failed to set the reboot target, return=%d\n",
+ __func__, ret);
+
+out:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block reboot_target_notifier = {
+ .notifier_call = reboot_target_notify,
+};
+
+int reboot_target_register(struct reboot_target *new)
+{
+ if (var)
+ return -EBUSY;
+
+ var = new;
+ return 0;
+}
+EXPORT_SYMBOL(reboot_target_register);
+
+int reboot_target_unregister(struct reboot_target *old)
+{
+ if (old && old == var) {
+ var = NULL;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(reboot_target_unregister);
+
+int __init reboot_target_init(void)
+{
+ int ret = 0;
+
+ ret = register_reboot_notifier(&reboot_target_notifier);
+ if (ret)
+ pr_err("%s: failed to register reboot_notifier\n", __func__);
+
+ return ret;
+}
+
+void __exit reboot_target_exit(void)
+{
+ unregister_reboot_notifier(&reboot_target_notifier);
+}
+
+module_init(reboot_target_init);
+module_exit(reboot_target_exit);
+
+MODULE_AUTHOR("Jeremy Compostella <jeremy.compostella@intel.com>");
+MODULE_DESCRIPTION("Intel Reboot Target");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/reboot/reboot_target.h b/drivers/staging/android/reboot/reboot_target.h
new file mode 100644
index 00000000000..023d998d04b
--- /dev/null
+++ b/drivers/staging/android/reboot/reboot_target.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 Intel Corp
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _REBOOT_TARGET_H_
+#define _REBOOT_TARGET_H_
+
+struct reboot_target {
+ int (*set_reboot_target)(const char *name, const int id);
+};
+
+extern const char *reboot_target_id2name(int id);
+
+extern int reboot_target_register(struct reboot_target *);
+extern int reboot_target_unregister(struct reboot_target *);
+
+#endif /* _REBOOT_TARGET_H_ */