Lines Matching +full:smc +full:- +full:reboot
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
3 * Apple SMC Reboot/Poweroff Handler
12 #include <linux/nvmem-consumer.h>
14 #include <linux/reboot.h>
39 struct apple_smc *smc; member
61 return -EINVAL; in nvmem_cell_get_u8()
75 * SMC 'MBSE' key actions:
77 * 'offw' - shutdown warning
78 * 'slpw' - sleep warning
79 * 'rest' - restart warning
80 * 'off1' - shutdown (needs PMU bit set to stay on)
81 * 'susp' - suspend
82 * 'phra' - restart ("PE Halt Restart Action"?)
83 * 'panb' - panic beginning
84 * 'pane' - panic end
89 struct macsmc_reboot *reboot = data->cb_data; in macsmc_prepare_atomic() local
91 dev_info(reboot->dev, "Preparing SMC for atomic mode\n"); in macsmc_prepare_atomic()
93 apple_smc_enter_atomic(reboot->smc); in macsmc_prepare_atomic()
99 struct macsmc_reboot *reboot = data->cb_data; in macsmc_power_off() local
101 dev_info(reboot->dev, "Issuing power off (off1)\n"); in macsmc_power_off()
103 if (apple_smc_write_u32_atomic(reboot->smc, SMC_KEY(MBSE), SMC_KEY(off1)) < 0) { in macsmc_power_off()
104 dev_err(reboot->dev, "Failed to issue MBSE = off1 (power_off)\n"); in macsmc_power_off()
115 struct macsmc_reboot *reboot = data->cb_data; in macsmc_restart() local
117 dev_info(reboot->dev, "Issuing restart (phra)\n"); in macsmc_restart()
119 if (apple_smc_write_u32_atomic(reboot->smc, SMC_KEY(MBSE), SMC_KEY(phra)) < 0) { in macsmc_restart()
120 dev_err(reboot->dev, "Failed to issue MBSE = phra (restart)\n"); in macsmc_restart()
131 struct macsmc_reboot *reboot = container_of(this, struct macsmc_reboot, reboot_notify); in macsmc_reboot_notify() local
148 dev_info(reboot->dev, "Preparing for reboot (%p4ch)\n", &val); in macsmc_reboot_notify()
151 if (apple_smc_write_u32(reboot->smc, SMC_KEY(MBSE), val) < 0) in macsmc_reboot_notify()
152 dev_err(reboot->dev, "Failed to issue MBSE = %p4ch (reboot_prepare)\n", &val); in macsmc_reboot_notify()
154 /* Set the boot_stage to 0, which means we're doing a clean shutdown/reboot. */ in macsmc_reboot_notify()
155 if (reboot->nvm.boot_stage && in macsmc_reboot_notify()
156 nvmem_cell_set_u8(reboot->nvm.boot_stage, BOOT_STAGE_SHUTDOWN) < 0) in macsmc_reboot_notify()
157 dev_err(reboot->dev, "Failed to write boot_stage\n"); in macsmc_reboot_notify()
160 * Set the PMU flag to actually reboot into the off state. in macsmc_reboot_notify()
161 * Without this, the device will just reboot. We make it optional in case it is no longer in macsmc_reboot_notify()
164 if (reboot->nvm.shutdown_flag && in macsmc_reboot_notify()
165 nvmem_cell_set_u8(reboot->nvm.shutdown_flag, shutdown_flag) < 0) in macsmc_reboot_notify()
166 dev_err(reboot->dev, "Failed to write shutdown_flag\n"); in macsmc_reboot_notify()
171 static void macsmc_power_init_error_counts(struct macsmc_reboot *reboot) in macsmc_power_init_error_counts() argument
175 if (!reboot->nvm.boot_error_count || !reboot->nvm.panic_count) in macsmc_power_init_error_counts()
178 boot_error_count = nvmem_cell_get_u8(reboot->nvm.boot_error_count); in macsmc_power_init_error_counts()
180 dev_err(reboot->dev, "Failed to read boot_error_count (%d)\n", boot_error_count); in macsmc_power_init_error_counts()
184 panic_count = nvmem_cell_get_u8(reboot->nvm.panic_count); in macsmc_power_init_error_counts()
186 dev_err(reboot->dev, "Failed to read panic_count (%d)\n", panic_count); in macsmc_power_init_error_counts()
193 dev_warn(reboot->dev, "PMU logged %d boot error(s) and %d panic(s)\n", in macsmc_power_init_error_counts()
196 if (nvmem_cell_set_u8(reboot->nvm.panic_count, 0) < 0) in macsmc_power_init_error_counts()
197 dev_err(reboot->dev, "Failed to reset panic_count\n"); in macsmc_power_init_error_counts()
198 if (nvmem_cell_set_u8(reboot->nvm.boot_error_count, 0) < 0) in macsmc_power_init_error_counts()
199 dev_err(reboot->dev, "Failed to reset boot_error_count\n"); in macsmc_power_init_error_counts()
204 struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent); in macsmc_reboot_probe() local
205 struct macsmc_reboot *reboot; in macsmc_reboot_probe() local
208 reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL); in macsmc_reboot_probe()
209 if (!reboot) in macsmc_reboot_probe()
210 return -ENOMEM; in macsmc_reboot_probe()
212 reboot->dev = &pdev->dev; in macsmc_reboot_probe()
213 reboot->smc = smc; in macsmc_reboot_probe()
215 platform_set_drvdata(pdev, reboot); in macsmc_reboot_probe()
220 cell = devm_nvmem_cell_get(&pdev->dev, in macsmc_reboot_probe()
223 if (PTR_ERR(cell) == -EPROBE_DEFER) in macsmc_reboot_probe()
224 return -EPROBE_DEFER; in macsmc_reboot_probe()
225 dev_warn(&pdev->dev, "Missing NVMEM cell %s (%ld)\n", in macsmc_reboot_probe()
230 reboot->nvm_cells[i] = cell; in macsmc_reboot_probe()
234 if (reboot->nvm.boot_stage && in macsmc_reboot_probe()
235 nvmem_cell_set_u8(reboot->nvm.boot_stage, BOOT_STAGE_KERNEL_STARTED) < 0) in macsmc_reboot_probe()
236 dev_err(reboot->dev, "Failed to write boot_stage\n"); in macsmc_reboot_probe()
239 macsmc_power_init_error_counts(reboot); in macsmc_reboot_probe()
241 reboot->reboot_notify.notifier_call = macsmc_reboot_notify; in macsmc_reboot_probe()
243 ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF_PREPARE, in macsmc_reboot_probe()
244 SYS_OFF_PRIO_HIGH, macsmc_prepare_atomic, reboot); in macsmc_reboot_probe()
246 return dev_err_probe(&pdev->dev, ret, in macsmc_reboot_probe()
247 "Failed to register power-off prepare handler\n"); in macsmc_reboot_probe()
248 ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_HIGH, in macsmc_reboot_probe()
249 macsmc_power_off, reboot); in macsmc_reboot_probe()
251 return dev_err_probe(&pdev->dev, ret, in macsmc_reboot_probe()
252 "Failed to register power-off handler\n"); in macsmc_reboot_probe()
254 ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART_PREPARE, in macsmc_reboot_probe()
255 SYS_OFF_PRIO_HIGH, macsmc_prepare_atomic, reboot); in macsmc_reboot_probe()
257 return dev_err_probe(&pdev->dev, ret, in macsmc_reboot_probe()
259 ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, in macsmc_reboot_probe()
260 macsmc_restart, reboot); in macsmc_reboot_probe()
262 return dev_err_probe(&pdev->dev, ret, "Failed to register restart handler\n"); in macsmc_reboot_probe()
264 ret = devm_register_reboot_notifier(&pdev->dev, &reboot->reboot_notify); in macsmc_reboot_probe()
266 return dev_err_probe(&pdev->dev, ret, "Failed to register reboot notifier\n"); in macsmc_reboot_probe()
268 dev_info(&pdev->dev, "Handling reboot and poweroff requests via SMC\n"); in macsmc_reboot_probe()
274 { .compatible = "apple,smc-reboot", },
281 .name = "macsmc-reboot",
289 MODULE_DESCRIPTION("Apple SMC reboot/poweroff driver");