0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/err.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/mfd/mt6397/core.h>
0016 #include <linux/mfd/mt6397/rtc.h>
0017
0018 struct mt6323_pwrc {
0019 struct device *dev;
0020 struct regmap *regmap;
0021 u32 base;
0022 };
0023
0024 static struct mt6323_pwrc *mt_pwrc;
0025
0026 static void mt6323_do_pwroff(void)
0027 {
0028 struct mt6323_pwrc *pwrc = mt_pwrc;
0029 unsigned int val;
0030 int ret;
0031
0032 regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY);
0033 regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR_MT6323, 1);
0034
0035 ret = regmap_read_poll_timeout(pwrc->regmap,
0036 pwrc->base + RTC_BBPU, val,
0037 !(val & RTC_BBPU_CBUSY),
0038 MTK_RTC_POLL_DELAY_US,
0039 MTK_RTC_POLL_TIMEOUT);
0040 if (ret)
0041 dev_err(pwrc->dev, "failed to write BBPU: %d\n", ret);
0042
0043
0044 mdelay(1000);
0045
0046 WARN_ONCE(1, "Unable to power off system\n");
0047 }
0048
0049 static int mt6323_pwrc_probe(struct platform_device *pdev)
0050 {
0051 struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
0052 struct mt6323_pwrc *pwrc;
0053 struct resource *res;
0054
0055 pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
0056 if (!pwrc)
0057 return -ENOMEM;
0058
0059 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0060 if (!res)
0061 return -EINVAL;
0062
0063 pwrc->base = res->start;
0064 pwrc->regmap = mt6397_chip->regmap;
0065 pwrc->dev = &pdev->dev;
0066 mt_pwrc = pwrc;
0067
0068 pm_power_off = &mt6323_do_pwroff;
0069
0070 return 0;
0071 }
0072
0073 static int mt6323_pwrc_remove(struct platform_device *pdev)
0074 {
0075 if (pm_power_off == &mt6323_do_pwroff)
0076 pm_power_off = NULL;
0077
0078 return 0;
0079 }
0080
0081 static const struct of_device_id mt6323_pwrc_dt_match[] = {
0082 { .compatible = "mediatek,mt6323-pwrc" },
0083 {},
0084 };
0085 MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
0086
0087 static struct platform_driver mt6323_pwrc_driver = {
0088 .probe = mt6323_pwrc_probe,
0089 .remove = mt6323_pwrc_remove,
0090 .driver = {
0091 .name = "mt6323-pwrc",
0092 .of_match_table = mt6323_pwrc_dt_match,
0093 },
0094 };
0095
0096 module_platform_driver(mt6323_pwrc_driver);
0097
0098 MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC");
0099 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
0100 MODULE_LICENSE("GPL v2");