Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Power off through MediaTek PMIC
0004  *
0005  * Copyright (C) 2018 MediaTek Inc.
0006  *
0007  * Author: Sean Wang <sean.wang@mediatek.com>
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     /* Wait some time until system down, otherwise, notice with a warn */
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");