/* * 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; }
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; }