blob: aa78d411e79038469bebcb765d9d1ccc1907a488 [file] [log] [blame]
/*
* 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);