diff options
author | Scott D Phillips <scott.d.phillips@intel.com> | 2015-09-21 13:39:29 -0700 |
---|---|---|
committer | Brian Wood <brian.j.wood@intel.com> | 2015-09-23 15:31:28 -0700 |
commit | adf5722c0141e429b4a1c66885a187edfb1173f0 (patch) | |
tree | 6d7fda385db5656a674ea1c43b6ce4f60ed7fb34 | |
parent | 72683e74f8012153d079471c0ebb7ed60459c1df (diff) | |
download | intel-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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/android/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/android/reboot/Kconfig | 18 | ||||
-rw-r--r-- | drivers/staging/android/reboot/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/android/reboot/intel_scu_reboot_reason.c | 124 | ||||
-rw-r--r-- | drivers/staging/android/reboot/reboot_target.c | 163 | ||||
-rw-r--r-- | drivers/staging/android/reboot/reboot_target.h | 30 |
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_ */ |