当待机流程就会完成一些硬件驱动的现场操作,灯也是如此。
kernel\fusion\4.9\kernel\reboot.c

/** 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.*/
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,void __user *, arg)
{struct pid_namespace *pid_ns = task_active_pid_ns(current);char buffer[256];int ret = 0;/* We only trust the superuser with rebooting the system. */if (!ns_capable(pid_ns->user_ns, 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 &&magic2 != LINUX_REBOOT_MAGIC2C))return -EINVAL;/** If pid namespaces are enabled and the current task is in a child* pid_namespace, the command is handled by reboot_pid_ns() which will* call do_exit().*/ret = reboot_pid_ns(pid_ns, cmd);if (ret)return ret;/* Instead of trying to make the power_off code look like* halt when pm_power_off is not set do it the easy way.*/
#if (MP_PLATFORM_PM == 0)if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)cmd = LINUX_REBOOT_CMD_HALT;
#endifmutex_lock(&reboot_mutex);switch (cmd) {case LINUX_REBOOT_CMD_RESTART:
#ifdef CONFIG_MP_AMAZON_SIGN_OF_LIFElife_cycle_set_boot_reason(WARMBOOT_BY_SW);
#endifkernel_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:kernel_halt();do_exit(0);panic("cannot halt");case LINUX_REBOOT_CMD_POWER_OFF:
#ifdef CONFIG_MP_AMAZON_SIGN_OF_LIFElife_cycle_set_shutdown_reason(SHUTDOWN_BY_SW);
#endifkernel_power_off();do_exit(0);break;case LINUX_REBOOT_CMD_RESTART2:
#ifdef CONFIG_MP_AMAZON_SIGN_OF_LIFElife_cycle_set_boot_reason(WARMBOOT_BY_SW);
#endifret = strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1);if (ret < 0) {ret = -EFAULT;break;}buffer[sizeof(buffer) - 1] = '\0';kernel_restart(buffer);break;#ifdef CONFIG_KEXEC_COREcase LINUX_REBOOT_CMD_KEXEC:ret = kernel_kexec();break;
#endif#ifdef CONFIG_HIBERNATIONcase LINUX_REBOOT_CMD_SW_SUSPEND:ret = hibernate();break;
#endifdefault:ret = -EINVAL;break;}mutex_unlock(&reboot_mutex);return ret;
}

当收到上层reboot 指令时,根据不同的cmd 来决定是关机,重启,挂起等等。

/** Commands accepted by the _reboot() system call.** RESTART     Restart system using default command and mode.* HALT        Stop OS and give system control to ROM monitor, if any.* CAD_ON      Ctrl-Alt-Del sequence causes RESTART command.* CAD_OFF     Ctrl-Alt-Del sequence sends SIGINT to init task.* POWER_OFF   Stop OS and remove all power from system, if possible.* RESTART2    Restart system using given command string.* SW_SUSPEND  Suspend system using software suspend if compiled in.* KEXEC       Restart system using a previously loaded Linux kernel*/#define    LINUX_REBOOT_CMD_RESTART    0x01234567
#define LINUX_REBOOT_CMD_HALT       0xCDEF0123
#define LINUX_REBOOT_CMD_CAD_ON     0x89ABCDEF
#define LINUX_REBOOT_CMD_CAD_OFF    0x00000000
#define LINUX_REBOOT_CMD_POWER_OFF  0x4321FEDC
#define LINUX_REBOOT_CMD_RESTART2   0xA1B2C3D4
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
#define LINUX_REBOOT_CMD_KEXEC      0x45584543

本篇我们关注关机流程,收到 cmd “LINUX_REBOOT_CMD_POWER_OFF ” 时,就会进入kernel_power_off.

void kernel_power_off(void)
{#if defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) || defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE) || defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL)
#if defined(CONFIG_MSTAR_CPU_CLUSTER_CALIBRATING)atomic_set(&disable_dvfs_reboot, 1);
#endif
#endif#if defined(CONFIG_MSTAR_PM)check_boot_mode = 0;
#endifkernel_shutdown_prepare(SYSTEM_POWER_OFF);if (pm_power_off_prepare)pm_power_off_prepare();migrate_to_reboot_cpu();syscore_shutdown();pr_emerg("Power down\n");kmsg_dump(KMSG_DUMP_POWEROFF);machine_power_off();
#ifdef CONFIG_MSTAR_MBX
#if (MP_PLATFORM_PM == 1)mstar_str_notifypmmaxcnt_off();
#endif
#endif
}

pm_power_off_prepare 做关机前PM的预处理,
migrate_to_reboot_cpu
syscore_shutdown 调用各个驱动注册的shutdown 回调函数
machine_power_off 停止CPU任务

/** Power-off simply requires that the secondary CPUs stop performing any* activity (executing tasks, handling interrupts). smp_send_stop()* achieves this. When the system power is turned off, it will take all CPUs* with it.*/
void machine_power_off(void)
{local_irq_disable();smp_send_stop();if (pm_power_off)pm_power_off();
}

pm_power_off PM开始断电。

下面我们主要看和MTK平台相关的部分,其它kernel 的暂不关注。
pm_power_off_prepare 和 pm_power_off 都是在mstar2\hal\m7332\cpu\arm\pm.c 里面注册


static void mstar_pm_power_off_prepare(void)
{printk("mstar set pm power off param\n");MDrv_PM_Reboot(E_PM_STATE_POWER_OFF_PRE);mstar_sleep_cur_cpu_flush();
}static void mstar_pm_power_off(void)
{printk("mstar pm power down\n");MDrv_PM_Reboot(E_PM_STATE_POWER_OFF);_mstar_str_enter_tee(NULL);
}static int __init mstar_pm_init(void)
{pm_power_off_prepare = mstar_pm_power_off_prepare;pm_power_off = mstar_pm_power_off;/* set operation function of suspend */suspend_set_ops(&mstar_pm_ops);return 0;
}

mstar_pm_power_off_prepare 和 mstar_pm_power_off 调用 MDrv_PM_Reboot 发送了E_PM_STATE_POWER_OFF_PRE, E_PM_STATE_POWER_OFF 两个cmd,但是E_PM_STATE_POWER_OFF没有做处理。

PM_Result MDrv_PM_Reboot(PM_STATE eState)
{PM_Result eRet = E_PM_OK;switch (eState){case E_PM_STATE_REBOOT_NOTIFY:if (!is_mstar_str()){// MDrv_PM_Mapping() via mi notify callback.eRet &= _MDrv_PM_Store_Fw();}break;case E_PM_STATE_POWER_OFF_PRE:if (!is_mstar_str()){/* TODO: Remove. */_MDrv_PM_Set_Ir();#ifdef CONFIG_MSTAR_SYSFS_BACKLIGHTMDrv_PM_TurnoffBacklight();#endif#if (CONFIG_MSTAR_GPIO)_MDrv_PM_Set_Led();#endif// TODO: Remove patch for reboot recovery case._MDrv_PM_Patch_Mapping();_MDrv_PM_Set_Mode(PM_DC_MODE);_MDrv_PM_Flush_Config();eRet &= _MDrv_PM_BringUp();}break;default:eRet = E_PM_FAIL;break;}return eRet;
}

接着 _MDrv_PM_Set_Led 开始控制灯

#if (CONFIG_MSTAR_GPIO)
static void _MDrv_PM_Set_Led(void)
{u8 u8LedPad = 0;u8LedPad = MDrv_PM_Get_PowerOffLed();printk("Get LedPadNum = %d.\n", u8LedPad);if (u8LedPad != PM_SOURCE_DISABLE){printk("======= set red led on (set PAD_PWM_PM to High) ========\n");MDrv_GPIO_Set_High(u8LedPad);}
}
#endif

而这个LedPad 是在PM 注册时设置

static int _mstar_drv_pm_probe(struct platform_device *pdev)
{int retval = 0;U8 u8LedPad = 0xFF;struct device_node *node = pdev->dev.of_node;const struct of_device_id *match = of_match_device(of_match_ptr(mstar_pm_of_device_ids), &pdev->dev);if (!(pdev->name) || strcmp(pdev->name, MDRV_PM_DD_NAME) || (pdev->id != 0)){retval = -ENXIO;}if (match != NULL){if (of_property_read_u8(node, "poweroff_led", &u8LedPad) >= 0){if (u8LedPad != 0xFF){MDrv_PM_Set_PowerOffLed(u8LedPad);}}}return retval;
}

poweroff_led 即是从设备树中配置。
在m7332_an.dts 中配置mstar-pm 驱动的poweroff_led 属性

        mstar-pm {compatible = "mstar-pm";poweroff_led = /bits/ 8 <4>;};

其中4 为 PAD_PWM_PM 脚,在mhal_gpio_reg.h 文件中定义

#define PAD_PWM_PM 4

在现在框架里面根据,在dts 配置上Led 的pin 即可。也可以在mstar_pm_power_off_prepare或者mstar_pm_power_off自行添加。

拓展
system\core\reboot\reboot.c 收到reboot -p 指令时,会设置系统属性"sys.powerctl", system\core\init\init.cpp property_changed 检测到属性变化时,会处理

bool HandlePowerctlMessage(const std::string& command) {unsigned int cmd = 0;std::vector<std::string> cmd_params = android::base::Split(command, ",");std::string reboot_target = "";bool run_fsck = false;bool command_invalid = false;if (cmd_params.size() > 3) {command_invalid = true;} else if (cmd_params[0] == "shutdown") {cmd = ANDROID_RB_POWEROFF;if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") {// The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.// Run fsck once the file system is remounted in read-only mode.run_fsck = true;}} else if (cmd_params[0] == "reboot") {cmd = ANDROID_RB_RESTART2;if (cmd_params.size() >= 2) {reboot_target = cmd_params[1];// When rebooting to the bootloader notify the bootloader writing// also the BCB.if (reboot_target == "bootloader") {std::string err;if (!write_reboot_bootloader(&err)) {LOG(ERROR) << "reboot-bootloader: Error writing ""bootloader_message: "<< err;}}// If there is an additional bootloader parameter, pass it alongif (cmd_params.size() == 3) {reboot_target += "," + cmd_params[2];}}} else if (command == "thermal-shutdown") {  // no additional parameter allowedcmd = ANDROID_RB_THERMOFF;} else {command_invalid = true;}if (command_invalid) {LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";return false;}DoReboot(cmd, command, reboot_target, run_fsck);return true;
}

doReboot 进一步处理

void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,bool runFsck) {Timer t;LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE,S_IRUSR | S_IWUSR, AID_SYSTEM, AID_SYSTEM);if (cmd == ANDROID_RB_THERMOFF) {  // do not wait if it is thermalDoThermalOff();abort();}constexpr unsigned int shutdownTimeoutDefault = 6;unsigned int shutdownTimeout = shutdownTimeoutDefault;if (SHUTDOWN_ZERO_TIMEOUT) {  // eng buildshutdownTimeout = 0;} else {shutdownTimeout =android::base::GetUintProperty("ro.build.shutdown_timeout", shutdownTimeoutDefault);}LOG(INFO) << "Shutdown timeout: " << shutdownTimeout;// keep debugging tools until non critical ones are all gone.const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};// watchdogd is a vendor specific component but should be alive to complete shutdown safely.const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {if (kill_after_apps.count(s->name())) {s->SetShutdownCritical();} else if (to_starts.count(s->name())) {s->Start();s->SetShutdownCritical();}});Service* bootAnim = ServiceManager::GetInstance().FindServiceByName("bootanim");Service* surfaceFlinger = ServiceManager::GetInstance().FindServiceByName("surfaceflinger");if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {ServiceManager::GetInstance().ForEachServiceInClass("animation", [](Service* s) {s->SetShutdownCritical();  // will not check animation class separately});}// optional shutdown step// 1. terminate all services except shutdown critical ones. wait for delay to finishif (shutdownTimeout > 0) {LOG(INFO) << "terminating init services";// Ask all services to terminate except shutdown critical ones.ServiceManager::GetInstance().ForEachService([](Service* s) {if (!s->IsShutdownCritical()) s->Terminate();});int service_count = 0;// Up to half as long as shutdownTimeout or 3 seconds, whichever is lower.unsigned int terminationWaitTimeout = std::min<unsigned int>((shutdownTimeout + 1) / 2, 3);while (t.duration_s() < terminationWaitTimeout) {ServiceManager::GetInstance().ReapAnyOutstandingChildren();service_count = 0;ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {// Count the number of services running except shutdown critical.// Exclude the console as it will ignore the SIGTERM signal// and not exit.// Note: SVC_CONSOLE actually means "requires console" but// it is only used by the shell.if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {service_count++;}});if (service_count == 0) {// All terminable services terminated. We can exit early.break;}// Wait a bit before recounting the number or running services.std::this_thread::sleep_for(50ms);}LOG(INFO) << "Terminating running services took " << t<< " with remaining services:" << service_count;}// minimum safety steps before restarting// 2. kill all services except ones that are necessary for the shutdown sequence.ServiceManager::GetInstance().ForEachService([](Service* s) {if (!s->IsShutdownCritical()) s->Stop();});ServiceManager::GetInstance().ReapAnyOutstandingChildren();// 3. send volume shutdown to voldService* voldService = ServiceManager::GetInstance().FindServiceByName("vold");if (voldService != nullptr && voldService->IsRunning()) {ShutdownVold();voldService->Stop();} else {LOG(INFO) << "vold not running, skipping vold shutdown";}// logcat stopped hereServiceManager::GetInstance().ForEachService([&kill_after_apps](Service* s) {if (kill_after_apps.count(s->name())) s->Stop();});// 4. sync, try umount, and optionally run fsck for user shutdownsync();UmountStat stat = TryUmountAndFsck(runFsck, shutdownTimeout * 1000 - t.duration_ms());// Follow what linux shutdown is doing: one more sync with little bit delaysync();std::this_thread::sleep_for(100ms);LogShutdownTime(stat, &t);// Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.RebootSystem(cmd, rebootTarget);abort();
}

系统关闭一些上层服务后,会进入内核部分

static void __attribute__((noreturn))
RebootSystem(unsigned int cmd, const std::string& rebootTarget) {LOG(INFO) << "Reboot ending, jumping to kernel";switch (cmd) {case ANDROID_RB_POWEROFF:reboot(RB_POWER_OFF);break;case ANDROID_RB_RESTART2:syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());break;case ANDROID_RB_THERMOFF:reboot(RB_POWER_OFF);break;}// In normal case, reboot should not return.PLOG(FATAL) << "reboot call returned";abort();
}

reboot(RB_POWER_OFF); 其中RB_POWER_OFF在libc 库里面定义的值为#define RB_POWER_OFF 0x4321fedc
与内核LINUX_REBOOT_CMD_POWER_OFF 是同一个cmd,接着会进入内核的SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) 函数。

T9632 待机led 控制相关推荐

  1. APA102C全彩色LED控制IC

    简 介: 测试了APA102C的工作机制.利用MM32F3277 MicroPython中的SPI控制APA102C工作. 关键词: APA102C,MM32F3277,SPI #mermaid-sv ...

  2. SES2 LED控制

    SES2 LED控制 1.磁盘LED控制的背景及需求 磁盘阵列中每个磁盘都对应多个LED灯,常用来指示磁盘的状态和行为. 比如当磁盘出现故障需要定位.磁盘缺失.正常在线或者正在读写等情况下,可以通过S ...

  3. 极域电子教室软件怎么脱离控制_新疆灵感科技技术汇总~LED控制卡常见软、硬件问题...

    许多技术员在操作LED电子显示屏的时候,经常显示屏的软件或者硬软出现异常,那是怎么回事呢?一.软件应用1.为什么显示的时候某显示项只闪一下就消失了? 在预览脚本或在屏幕上显示脚本的时候,发现某项一闪而 ...

  4. am335x linux修改ip,Linux 修改代码以支持LED 控制(board-am335xevm)

    Linux 修改代码以支持LED 控制(board-am335xevm) Note: All the codes are changed at the file board-am335xevm.c d ...

  5. 【单片机应用】项目一 发光二极管LED控制

    发光二极管LED控制 一.LED介绍 二.LED的工作原理 三.小项目:点亮一个LED 点亮一个发光二极管 认识PROTEUS 用PROTEUS设计第一个LED控制电路 工作过程 LED点亮程序 点亮 ...

  6. Ardunio开发实例-红外遥控器解码与LED控制

    红外遥控器解码与LED控制 红外遥控是一种无线.非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机和手机系 ...

  7. 通用GPIO驱动和apk(含jni),支持所有GPIO,支持LED控制,支持友善6410/210开发板,支持安卓2.3/4.0,内核2.6/3.0

    转自:http://www.arm9home.net/read.php?tid-27259.html GPIO Driver and apk(include jni) support All GPIO ...

  8. ESP32-CAM GPIO LED 控制 - uPython

    ESP32-CAM GPIO LED 控制 - uPython ESP32-CAM 内建有两个发光二极管(light-emitting diode, 以下简称 LED)外设,分别是接在通用型之输入输出 ...

  9. 志良电子关于LED控制卡显示内容上下行有虚点的问题研究(一)

    问题描述: 在调试一块LED控制板时发现在显示的内容上下行,根据显示内容应该是熄灭的LED灯却亮着,亮度比正常显示的LED灯低很多. 调试过程: LED显示相关函数如下,LED屏为单色屏,1/16扫描 ...

最新文章

  1. HR最常用的Excel技巧,职场必备,值得收藏转发!
  2. 蓝桥杯评分标准_蓝桥杯软件个人赛校内选拔赛评分标准和选拔标准
  3. 抽象类的实际应用--模版设计
  4. jsoncpp之初体验
  5. 针对模拟滚动条插件(jQuery.slimscroll.js)的修改
  6. CentOS查看硬件情况
  7. 【C++】朝花夕拾——表达式树
  8. Mac 10.12使用free命令(fish)
  9. (七)、Java异常类型及处理
  10. 《史记》记载的喝粥延命内容
  11. 续【将数据从MongoDB迁移到mysql】
  12. uniapp 条码生成器
  13. Error response from daemon: Get https://index.docker.io/v1/search?q=elastics earchn=25: net/http: T
  14. Jmeter的元件使用介绍:取样器详解
  15. Reporter对象的几个鲜为人知的方法
  16. 电竞LOL数据API接口 - 【赛事列表数据】API调用示例代码
  17. win10 快速批量删除快速访问下的文件夹记录
  18. [Java]介绍|环境|编码|数据类型|String|运算符|标准输入|if语句|循环语句|三元运算符|循环语句|swich语句
  19. 标称型数据和数值型数据_数据的来源与类型以及数据的特征抽取
  20. 清华大学胡事民是计算机视觉,清华团队将Transformer用到3D点云分割上后,效果好极了丨开源...

热门文章

  1. Altium Designer初学者入门——stm32最小系统的PCB图(接上一篇原理图绘制)
  2. 电商api、地图api、视频api、音乐api等各类接口合集,或许对你有用
  3. SQL Server 2000 企业管理器错误 提示:MMC 无法创建管理单元(不重装)
  4. 图像频率域分析之频域谱(FDE)
  5. LiveMe x TiDB丨单表数据量 39 亿条,简化架构新体验
  6. 【数字IC手撕代码】Verilog奇数分频|题目|原理|设计|仿真(三分频,五分频,奇数分频及特殊占空比)
  7. Vue简单快速上手 idea版
  8. 专注少儿成长,掌门少儿打造多维思维启蒙体验
  9. 一键批量替换文本工具
  10. 阿里妈妈智能诊断工程能力建设