1 // SPDX-License-Identifier: GPL-2.0
3 * Power off through MediaTek PMIC
5 * Copyright (C) 2018 MediaTek Inc.
7 * Author: Sean Wang <sean.wang@mediatek.com>
11 #include <linux/err.h>
12 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/mfd/mt6397/core.h>
16 #include <linux/mfd/mt6397/rtc.h>
17 #include <linux/reboot.h>
21 struct regmap
*regmap
;
25 static int mt6323_do_pwroff(struct sys_off_data
*data
)
27 struct mt6323_pwrc
*pwrc
= data
->cb_data
;
31 regmap_write(pwrc
->regmap
, pwrc
->base
+ RTC_BBPU
, RTC_BBPU_KEY
);
32 regmap_write(pwrc
->regmap
, pwrc
->base
+ RTC_WRTGR_MT6323
, 1);
34 ret
= regmap_read_poll_timeout(pwrc
->regmap
,
35 pwrc
->base
+ RTC_BBPU
, val
,
36 !(val
& RTC_BBPU_CBUSY
),
37 MTK_RTC_POLL_DELAY_US
,
38 MTK_RTC_POLL_TIMEOUT
);
40 dev_err(pwrc
->dev
, "failed to write BBPU: %d\n", ret
);
42 /* Wait some time until system down, otherwise, notice with a warn */
45 WARN_ONCE(1, "Unable to power off system\n");
50 static int mt6323_pwrc_probe(struct platform_device
*pdev
)
52 struct mt6397_chip
*mt6397_chip
= dev_get_drvdata(pdev
->dev
.parent
);
53 struct mt6323_pwrc
*pwrc
;
57 pwrc
= devm_kzalloc(&pdev
->dev
, sizeof(*pwrc
), GFP_KERNEL
);
61 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
65 pwrc
->base
= res
->start
;
66 pwrc
->regmap
= mt6397_chip
->regmap
;
67 pwrc
->dev
= &pdev
->dev
;
69 ret
= devm_register_sys_off_handler(pwrc
->dev
,
70 SYS_OFF_MODE_POWER_OFF
,
75 return dev_err_probe(pwrc
->dev
, ret
, "failed to register power-off handler\n");
80 static const struct of_device_id mt6323_pwrc_dt_match
[] = {
81 { .compatible
= "mediatek,mt6323-pwrc" },
84 MODULE_DEVICE_TABLE(of
, mt6323_pwrc_dt_match
);
86 static struct platform_driver mt6323_pwrc_driver
= {
87 .probe
= mt6323_pwrc_probe
,
89 .name
= "mt6323-pwrc",
90 .of_match_table
= mt6323_pwrc_dt_match
,
94 module_platform_driver(mt6323_pwrc_driver
);
96 MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC");
97 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");