Esempio n. 1
0
/*
 * Reboot system call: for obvious reasons only root may call it,
 * and even root needs to set up some magic numbers in the registers
 * so that some mistake won't make this reboot the whole machine.
 * You can also set the meaning of the ctrl-alt-del-key here.
 *
 * reboot doesn't sync: do that yourself before calling this.
 */
asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg)
{
	char buffer[256];

	/* We only trust the superuser with rebooting the system. */
	if (!capable(CAP_SYS_BOOT))
		return -EPERM;

	/* For safety, we require "magic" arguments. */
	if (magic1 != LINUX_REBOOT_MAGIC1 ||
	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
			magic2 != LINUX_REBOOT_MAGIC2B))
		return -EINVAL;

#ifdef CONFIG_ARCH_EZXBASE

/* must be sync with include/linux/moto_accy.h */
#define ACCS_REBOOT (1 << MOTO_ACCY_TYPE_CHARGER_MID | \
                     1 << MOTO_ACCY_TYPE_CHARGER_MID_MPX | \
                     1 << MOTO_ACCY_TYPE_CHARGER_FAST | \
                     1 << MOTO_ACCY_TYPE_CHARGER_FAST_MPX | \
                     1 << MOTO_ACCY_TYPE_CHARGER_FAST_3G | \
		     1 << MOTO_ACCY_TYPE_CARKIT_MID | \
		     1 << MOTO_ACCY_TYPE_CARKIT_FAST | \
		     1 << MOTO_ACCY_TYPE_CARKIT_SMART)

#define FACTORY_REBOOT (1 << MOTO_ACCY_TYPE_CABLE_FACTORY)

        MOTO_ACCY_MASK_T mask = (MOTO_ACCY_MASK_T)moto_accy_get_all_devices();
        if (LINUX_REBOOT_CMD_RESTART == cmd) {
		if (mask & FACTORY_REBOOT) {
	                *(unsigned long *)(phys_to_virt(FLAG_ADDR)) = FACTORY_REBOOT_FLAG;
		} else {
	                *(unsigned long *)(phys_to_virt(FLAG_ADDR)) = APP_REBOOT_FLAG;
		}
        }
                                                                                                                             
        if (LINUX_REBOOT_CMD_POWER_OFF == cmd) {
            if (mask & ACCS_REBOOT) {
                *(unsigned long *)(phys_to_virt(FLAG_ADDR)) = CHARGE_FLAG;
                cmd = LINUX_REBOOT_CMD_RESTART;
                printk(KERN_EMERG "Change to reboot mode.\n");
            }
        }
#endif

	lock_kernel();
	switch (cmd) {
	case LINUX_REBOOT_CMD_RESTART:
		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
#ifdef CONFIG_KFI
		kfi_dump_log(NULL);
#endif
		printk(KERN_EMERG "Restarting system.\n");
		machine_restart(NULL);
		break;

	case LINUX_REBOOT_CMD_CAD_ON:
		C_A_D = 1;
		break;

	case LINUX_REBOOT_CMD_CAD_OFF:
		C_A_D = 0;
		break;

	case LINUX_REBOOT_CMD_HALT:
		notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
#ifdef CONFIG_KFI
		kfi_dump_log(NULL);
#endif
		printk(KERN_EMERG "System halted.\n");
		machine_halt();
		do_exit(0);
		break;

	case LINUX_REBOOT_CMD_POWER_OFF:
		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
#ifdef CONFIG_KFI
		kfi_dump_log(NULL);
#endif
		printk(KERN_EMERG "Power down.\n");
		machine_power_off();
		do_exit(0);
		break;

	case LINUX_REBOOT_CMD_RESTART2:
		if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
			unlock_kernel();
			return -EFAULT;
		}
		buffer[sizeof(buffer) - 1] = '\0';

		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
		printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
#ifdef CONFIG_KFI
		kfi_dump_log(NULL);
#endif
		machine_restart(buffer);
		break;

	default:
		unlock_kernel();
		return -EINVAL;
	}
	unlock_kernel();
	return 0;
}
Esempio n. 2
0
static int emu_proc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    unsigned int ret_val = 0;
    
    POWER_IC_EMU_GLUE_READ_SENSE_T read_sense; 
    POWER_IC_EMU_GLUE_TRANSCEIVER_PARAMS_T trans_params;
    POWER_IC_FET_CONTROL_T fet_ctrl;

    /* prev lockout status */
    static bool prev_emu_hw_lockout_state = false;

    /* what devices were connected before lockout */
    static MOTO_ACCY_MASK_T connected_device_before_lock = 0;
    MOTO_ACCY_MASK_T connected_device;
    
    /* Get the actual command from the ioctl request. */
    unsigned int cmd_num = _IOC_NR(cmd);
    
    if ((cmd_num >= POWER_IC_IOC_CMD_EMU_GLUE_BASE) && (cmd_num <= POWER_IC_IOC_CMD_EMU_GLUE_LAST_CMD))
    { 
        tracemsg(_k_d("EMU GLUE control ioctl(), request 0x%X (cmd 0x%X)"),(int) cmd, _IOC_NR(cmd));

        /* Handle the request. */
        switch(cmd)
        {
            case POWER_IC_IOCTL_CMD_EMU_GLUE_READ_SENSE:
                /* Fetch the data passed from user space. */
                if(copy_from_user((void *)&read_sense, (void *)arg, sizeof(read_sense)) != 0)
                {
                    tracemsg(_k_d("error copying data from user space."));
                    ret_val = -EFAULT;
                }  
                else
                {
                    /* Read the sense and clear the interrupt if requested */
                    read_sense.sense = emu_glue_read_sense(read_sense.clear_int_flags);

                    /* Only the sense value read needs to be sent back to the caller. */
                    if(put_user(read_sense.sense,&(((POWER_IC_EMU_GLUE_READ_SENSE_T *)arg)->sense)) != 0)
                    {
                        tracemsg(_k_d("error copying read bits to user space."));
                        ret_val = -EFAULT;
                    }
                }
                break;
                
            case POWER_IC_IOCTL_CMD_EMU_GLUE_LOCKOUT_CHANGES:
                power_ic_emu_hw_locked = (bool)(arg == 0 ? 0 : 1);
                 
                if (power_ic_emu_hw_locked)
                {
                    /* Make sure the hardware is not already locked */
                    if (prev_emu_hw_lockout_state == false)
                    {
                        /* If the EMU hardware needs to be locked, keep track of
                           the currently connected accessory */
                        connected_device_before_lock = moto_accy_get_all_devices();
                    }
                }
                else
                {                   
                    /* If the EMU hardware was previously locked but is now unlocked the accessory may need
                       to be reconfigured. */
                    if (prev_emu_hw_lockout_state == true)
                    {
                        connected_device = moto_accy_get_all_devices();
                        
                        if (connected_device_before_lock == connected_device)
                        {
                            if ((ACCY_BITMASK_ISSET(connected_device, MOTO_ACCY_TYPE_HEADSET_EMU_MONO)) ||
                                (ACCY_BITMASK_ISSET(connected_device, MOTO_ACCY_TYPE_HEADSET_EMU_STEREO)))
                            {
                                audio_config.id_pull_down = 0;
                                audio_config.conn_mode = 0;
                                emu_util_set_emu_headset_mode(audio_config.headset_mode);
                            }
                            else if ((ACCY_BITMASK_ISSET(connected_device, MOTO_ACCY_TYPE_CARKIT_MID)) ||
                                     (ACCY_BITMASK_ISSET(connected_device, MOTO_ACCY_TYPE_CARKIT_FAST)))
                            {
                                audio_config.headset_mode = MOTO_ACCY_HEADSET_MODE_NONE;
                                EMU_SET_EMU_CONN_MODE(audio_config.conn_mode);
                                EMU_SET_ID_PULL_DOWN(audio_config.id_pull_down);
                            }
                            else
                            {
                                audio_config.headset_mode = MOTO_ACCY_HEADSET_MODE_NONE;
                                audio_config.conn_mode = POWER_IC_EMU_CONN_MODE_USB;
                                audio_config.id_pull_down = 0;  
                            }
                        }
                        else
                        {
                            audio_config.headset_mode = MOTO_ACCY_HEADSET_MODE_NONE;
                            audio_config.conn_mode = POWER_IC_EMU_CONN_MODE_USB;
                            audio_config.id_pull_down = 0;  
                        }
                    }
                }

                prev_emu_hw_lockout_state = power_ic_emu_hw_locked;
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_GET_FET_CONTROL:
                if ((power_ic_get_reg_value(POWER_IC_REG_ATLAS_CHARGER_0, 10, (int *)&(fet_ctrl), 2)) != 0)
                {
                    ret_val = -EIO;
                }
                /* Only the sense value read needs to be sent back to the caller. */
                else if(put_user(fet_ctrl, (((int *)arg))) != 0)
                {
                    tracemsg(_k_d("error copying read bits to user space."));
                    ret_val = -EFAULT;
                }
                break;
                   
            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_FET_CONTROL:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_CHARGER_0, 10,
                                       arg, 2);
                break;
                
            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_VBUS_5K_PD:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_CHARGER_0, 19,
                                       (arg == 0 ? 0 : 1), 1);
                break;
         
            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_VBUS_70K_PD:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 6,
                                       (arg == 0 ? 0 : 1), 1);
                               
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_REVERSE_MODE:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_CHARGE_USB_1, 5,
                                   (arg == 0 ? 0 : 1), 1);
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_ID_PU:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 22,
                                       (arg == 0 ? 0 : 1), 1);
                break;            
         
            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_ID_PD:
                 power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 20,
                                       (arg == 0 ? 0 : 1), 1);
                 break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_ID_STEREO_PU:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_CHARGE_USB_1, 8,
                                       (arg == 0 ? 0 : 1), 1);
                break;  

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_CONN_MODE:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 14,
                                       arg, 3);
                break;  

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_DPLUS_150K_PU:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 5,
                                       (arg == 0 ? 0 : 1), 1);            
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_DPLUS_1_5K_PU:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 2,
                                       (arg == 0 ? 0 : 1), 1); 
                break;
  
            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_LOW_SPEED_MODE:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 0,
                                       (arg == 0 ? 0 : 1), 1);    
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_USB_SUSPEND:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_USB_0, 1,
                                       (arg == 0 ? 0 : 1), 1);    
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_TRANSCEIVER_PARAMS:
                /* Fetch the data passed from user space. */
                if(copy_from_user((void *)&trans_params, (void *)arg, sizeof(trans_params)) != 0)
                {
                    tracemsg(_k_d("error copying data from user space."));
                    ret_val = -EFAULT;
                }
                else
                {
                    /* Call local function */
                    emu_glue_set_transceiver_params(trans_params);
                }
                break;

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_ID_INT_MASK:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_INT_MASK_0, 19,
                                       arg, 1);    
                break;  

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_VBUS_INT_MASK:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_INT_MASK_0, 16,
                                       arg, 1);    
                break; 

            case POWER_IC_IOCTL_CMD_EMU_GLUE_SET_SE1_INT_MASK:
                power_ic_set_reg_value(POWER_IC_REG_ATLAS_INT_MASK_0, 21,
                                       arg, 1);    
                break;

            default: /* This shouldn't be able to happen, but just in case... */
                tracemsg(_k_d("=> 0x%X unsupported emu proc ioctl command"), (int) cmd);
                ret_val = -ENOTTY;
                break;
        }
    }
    else /* The driver doesn't support this request. */
    {
        tracemsg(_k_d("0x%X unsupported ioctl command"), (int) cmd);
        ret_val = -ENOTTY;
    }
        
    return ret_val;
}