| /* |
| * linux/arch/arm/mach-zx297520v3/reset.c |
| * |
| * Copyright (C) 2015 ZTE-TSP |
| * |
| * 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; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * 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. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/interrupt.h> |
| #include <linux/irq.h> |
| #include <linux/clockchips.h> |
| #include <linux/clk.h> |
| #include <linux/module.h> |
| #include <linux/err.h> |
| #include <linux/syscore_ops.h> |
| #include <linux/gpio.h> |
| #include <linux/miscdevice.h> /* For handling misc devices */ |
| #include <linux/fs.h> /* For file operations */ |
| #include <mach/board.h> |
| #include <mach/iomap.h> |
| #include <mach/spinlock.h> |
| #include <linux/mfd/zx234290.h> |
| #include <linux/delay.h> |
| #include <linux/reboot.h> |
| #include <linux/sched.h> |
| |
| #define ZX_RESET_DEV "/dev/zx_reset" |
| |
| #define ZX_RESET_IOC_MAGIC 'W' |
| /*ioctl cmd usd by device*/ |
| #define ZX_RESET_FAST_REBOOT _IOW(ZX_RESET_IOC_MAGIC, 1, char *) |
| |
| |
| #define GLOBAL_RESET_REG (ZX_TOP_CRM_BASE) |
| |
| #define USER_RST_UNDEFINE 0 |
| #define USER_RST_TO_NORMAL 1 |
| #define USER_RST_TO_CHARGER 2 |
| #define USER_RST_TO_ALARM 3 |
| #define USER_RST_TO_EXCEPT 4 |
| #ifdef CONFIG_DWC_DEVICE_ONLY |
| typedef enum |
| { |
| GSM_RAM_PWR = 0, |
| GSM_DSP_PWR = 1, |
| EDCP_PWR = 4, |
| USB_CTRL_PWR = 8, |
| USB_HSIC_PWR = 9, |
| |
| PARTITION_ALL = 10 |
| |
| } T_ZDrvPow_Partition; |
| |
| typedef enum |
| { |
| POW_MDL_1 = 0, |
| POW_MDL_ALL = 1 |
| } T_ZDrvPow_PowerModule; |
| |
| typedef enum |
| { |
| POW_ENABLE = 0, |
| POW_DISABLE = 1, |
| |
| POW_ENABLE_ALL |
| } T_ZDrvPow_PowerEnable; |
| |
| extern int pow_partition_powerswitch(T_ZDrvPow_Partition part, T_ZDrvPow_PowerEnable ena); |
| extern int zx234290_setusb_v0v9_sleepmode(T_ZDrvPmic_SlpMode mode); |
| extern int zx234290_setusb_v3v3_sleepmode(T_ZDrvPmic_SlpMode mode); |
| #endif |
| static bool debug_stop_reboot = false; |
| module_param(debug_stop_reboot, bool, 0644); |
| |
| #ifdef CONFIG_WATCHDOG_RESTART |
| extern void wdt_restart(void); |
| #endif |
| |
| extern void zx_denali_nand_lock(void); |
| extern void zx_denali_nand_unlock(void); |
| extern void zxic_reset_reason(int reason, const char *cpu, const char *app); |
| |
| |
| void zx29_restart(char mode, const char *cmd) |
| { |
| /* change to "#ifdef CONFIG_MFD_ZX234290/CONFIG_MFD_ZX234290_I2C" later! */ |
| #ifndef CONFIG_ARCH_ZX297520V3_CAP |
| /* reset */ |
| unsigned char reg = 0; |
| int ret = 0; |
| u8 restart_flag = 0; |
| unsigned char status = USER_RST_UNDEFINE; |
| |
| zxic_reset_reason(2, "ap", current->comm); |
| |
| if (cmd == NULL) { |
| printk(KERN_INFO"restart:enter reboot :reset to normal\n"); |
| |
| /*set the vale = 1*/ |
| status = USER_RST_TO_NORMAL; |
| } else if (strcmp(cmd,"drv_key reboot") == 0) { |
| printk(KERN_INFO"restart:enter drv_key reboot :reset to charger\n"); |
| |
| /*set the vale = 2*/ |
| status = USER_RST_TO_CHARGER; |
| } else if (strcmp(cmd,"drv_except reboot") == 0) { |
| printk(KERN_INFO"restart:enter drv_except reboot :reset to normal\n"); |
| |
| /* set the vale = 4 */ |
| status = USER_RST_TO_EXCEPT; |
| } else if (strcmp(cmd,"mmi_key reboot") == 0) { |
| printk(KERN_INFO"restart:enter mmi_key reboot :reset to charger\n"); |
| |
| /*set the vale = 2*/ |
| status = USER_RST_TO_CHARGER; |
| } else if (strcmp(cmd,"mmi_rtc reboot") == 0) { |
| printk(KERN_INFO"restart: enter mmi_rtc reboot: reset to alarm\n"); |
| |
| status = USER_RST_TO_ALARM; |
| } else { |
| printk(KERN_INFO"restart: reboot with cmd %s\n", cmd); |
| |
| /*set the vale = 1*/ |
| status = USER_RST_TO_NORMAL; |
| } |
| if(debug_stop_reboot ) |
| { |
| printk(KERN_INFO"debug_stop_reboot= 0x%x, for debug, bug_on!!!!\n", debug_stop_reboot); |
| panic("reboot"); |
| } |
| /*reset spifc cs*/ |
| soft_spin_lock_nand_psm(NAND_SFLOCK); |
| zx29_gpio_config(ZX29_GPIO_93, GPIO93_SPIFC_CS); |
| gpio_set_value(ZX29_GPIO_86,GPIO_HIGH); |
| |
| #ifdef CONFIG_XR_WLAN |
| gpio_set_value(ZX29_GPIO_121,GPIO_LOW); |
| if (gpio_get_value(ZX29_GPIO_123) == 1) |
| mdelay(4000); |
| #endif |
| |
| if (status != USER_RST_TO_EXCEPT) { |
| #ifdef CONFIG_DWC_DEVICE_ONLY |
| //add by gsn,for user mode |
| zDrvPmic_SetNormal_Onoff(VUSB_0V9,PM_ENABLE); |
| zDrvPmic_SetNormal_Onoff(VUSB_3V3,PM_ENABLE); |
| pow_partition_powerswitch(USB_CTRL_PWR, POW_ENABLE); |
| |
| zx234290_setusb_v0v9_sleepmode(PM_SLPMODE_ECO_SLPV); |
| zx234290_setusb_v3v3_sleepmode(PM_SLPMODE_ECO_SLPV); |
| #endif |
| local_irq_disable(); |
| soft_spin_lock_psm(I2C2_SFLOCK); |
| |
| ret = Zx234290_SetUserReg_PSM(status); |
| if(0!= ret){ |
| panic("restart:set restar flag error!\n"); |
| } |
| |
| #ifdef CONFIG_WATCHDOG_RESTART //delete 32k |
| wdt_restart(); |
| #else |
| zx_write_reg(GLOBAL_RESET_REG, 1); |
| #endif |
| |
| soft_spin_unlock_psm(I2C2_SFLOCK); |
| local_irq_enable(); |
| } else { |
| ret = Zx234290_SetUserReg_PSM(USER_RST_TO_EXCEPT); |
| if (ret) { |
| panic("restart:set restar flag error!\n"); |
| } |
| |
| #ifdef CONFIG_WATCHDOG_RESTART //delete 32k |
| local_irq_disable(); |
| wdt_restart(); |
| #else |
| zx_write_reg(GLOBAL_RESET_REG, 1); |
| #endif |
| } |
| #endif |
| } |
| EXPORT_SYMBOL(zx29_restart); |
| |
| |
| /******************************************************************************** |
| * Function: |
| * Description: |
| * Parameters: |
| * Returns: |
| * Others: |
| ********************************************************************************/ |
| |
| static int zx_reset_open(struct inode *inode, struct file *file) |
| { |
| return 0; |
| } |
| |
| static int zx_reset_close(struct inode *inode, struct file *file) |
| { |
| return 0; |
| } |
| static long zx_reset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| { |
| switch(cmd) |
| { |
| case ZX_RESET_FAST_REBOOT: |
| //zx29_restart (NULL, "at set fast reboot!\n\n"); |
| #ifndef CONFIG_MTD_SPI_NOR |
| zx_denali_nand_lock(); |
| #endif |
| kernel_restart("at set fast reboot!\n\n"); |
| #ifndef CONFIG_MTD_SPI_NOR |
| zx_denali_nand_unlock(); |
| #endif |
| break; |
| |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| |
| static const struct file_operations zx_reset_fops = { |
| .owner = THIS_MODULE, |
| .unlocked_ioctl = zx_reset_ioctl, |
| .open = zx_reset_open, |
| .release = zx_reset_close, |
| }; |
| |
| static struct miscdevice zx_reset_miscdev = { |
| .minor = MISC_DYNAMIC_MINOR, |
| .name = "zx_reset", |
| .fops = &zx_reset_fops, |
| }; |
| |
| static int __init zx_reset_init(void) |
| { |
| int ret=0; |
| ret = misc_register(&zx_reset_miscdev); |
| if (ret != 0) { |
| printk(KERN_ERR"reset cannot register miscdev on(err=%d)\n", ret); |
| return ret; |
| } |
| return 0; |
| } |
| |
| late_initcall_sync(zx_reset_init); |
| |
| |