1d28c74c1SJosef Friedl // SPDX-License-Identifier: GPL-2.0 2d28c74c1SJosef Friedl /* 3d28c74c1SJosef Friedl * Power off through MediaTek PMIC 4d28c74c1SJosef Friedl * 5d28c74c1SJosef Friedl * Copyright (C) 2018 MediaTek Inc. 6d28c74c1SJosef Friedl * 7d28c74c1SJosef Friedl * Author: Sean Wang <sean.wang@mediatek.com> 8d28c74c1SJosef Friedl * 9d28c74c1SJosef Friedl */ 10d28c74c1SJosef Friedl 11d28c74c1SJosef Friedl #include <linux/err.h> 12d28c74c1SJosef Friedl #include <linux/module.h> 13d28c74c1SJosef Friedl #include <linux/of.h> 14d28c74c1SJosef Friedl #include <linux/platform_device.h> 15d28c74c1SJosef Friedl #include <linux/mfd/mt6397/core.h> 16d28c74c1SJosef Friedl #include <linux/mfd/mt6397/rtc.h> 17d28c74c1SJosef Friedl 18d28c74c1SJosef Friedl struct mt6323_pwrc { 19d28c74c1SJosef Friedl struct device *dev; 20d28c74c1SJosef Friedl struct regmap *regmap; 21d28c74c1SJosef Friedl u32 base; 22d28c74c1SJosef Friedl }; 23d28c74c1SJosef Friedl 24d28c74c1SJosef Friedl static struct mt6323_pwrc *mt_pwrc; 25d28c74c1SJosef Friedl 26d28c74c1SJosef Friedl static void mt6323_do_pwroff(void) 27d28c74c1SJosef Friedl { 28d28c74c1SJosef Friedl struct mt6323_pwrc *pwrc = mt_pwrc; 29d28c74c1SJosef Friedl unsigned int val; 30d28c74c1SJosef Friedl int ret; 31d28c74c1SJosef Friedl 32d28c74c1SJosef Friedl regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY); 3329ee4009SRan Bi regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR_MT6323, 1); 34d28c74c1SJosef Friedl 35d28c74c1SJosef Friedl ret = regmap_read_poll_timeout(pwrc->regmap, 36d28c74c1SJosef Friedl pwrc->base + RTC_BBPU, val, 37d28c74c1SJosef Friedl !(val & RTC_BBPU_CBUSY), 38d28c74c1SJosef Friedl MTK_RTC_POLL_DELAY_US, 39d28c74c1SJosef Friedl MTK_RTC_POLL_TIMEOUT); 40d28c74c1SJosef Friedl if (ret) 41d28c74c1SJosef Friedl dev_err(pwrc->dev, "failed to write BBPU: %d\n", ret); 42d28c74c1SJosef Friedl 43d28c74c1SJosef Friedl /* Wait some time until system down, otherwise, notice with a warn */ 44d28c74c1SJosef Friedl mdelay(1000); 45d28c74c1SJosef Friedl 46d28c74c1SJosef Friedl WARN_ONCE(1, "Unable to power off system\n"); 47d28c74c1SJosef Friedl } 48d28c74c1SJosef Friedl 49d28c74c1SJosef Friedl static int mt6323_pwrc_probe(struct platform_device *pdev) 50d28c74c1SJosef Friedl { 51d28c74c1SJosef Friedl struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); 52d28c74c1SJosef Friedl struct mt6323_pwrc *pwrc; 53d28c74c1SJosef Friedl struct resource *res; 54d28c74c1SJosef Friedl 55d28c74c1SJosef Friedl pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); 56d28c74c1SJosef Friedl if (!pwrc) 57d28c74c1SJosef Friedl return -ENOMEM; 58d28c74c1SJosef Friedl 59d28c74c1SJosef Friedl res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 60d28c74c1SJosef Friedl pwrc->base = res->start; 61d28c74c1SJosef Friedl pwrc->regmap = mt6397_chip->regmap; 62d28c74c1SJosef Friedl pwrc->dev = &pdev->dev; 63d28c74c1SJosef Friedl mt_pwrc = pwrc; 64d28c74c1SJosef Friedl 65d28c74c1SJosef Friedl pm_power_off = &mt6323_do_pwroff; 66d28c74c1SJosef Friedl 67d28c74c1SJosef Friedl return 0; 68d28c74c1SJosef Friedl } 69d28c74c1SJosef Friedl 70d28c74c1SJosef Friedl static int mt6323_pwrc_remove(struct platform_device *pdev) 71d28c74c1SJosef Friedl { 72d28c74c1SJosef Friedl if (pm_power_off == &mt6323_do_pwroff) 73d28c74c1SJosef Friedl pm_power_off = NULL; 74d28c74c1SJosef Friedl 75d28c74c1SJosef Friedl return 0; 76d28c74c1SJosef Friedl } 77d28c74c1SJosef Friedl 78d28c74c1SJosef Friedl static const struct of_device_id mt6323_pwrc_dt_match[] = { 79d28c74c1SJosef Friedl { .compatible = "mediatek,mt6323-pwrc" }, 80d28c74c1SJosef Friedl {}, 81d28c74c1SJosef Friedl }; 82d28c74c1SJosef Friedl MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match); 83d28c74c1SJosef Friedl 84d28c74c1SJosef Friedl static struct platform_driver mt6323_pwrc_driver = { 85d28c74c1SJosef Friedl .probe = mt6323_pwrc_probe, 86d28c74c1SJosef Friedl .remove = mt6323_pwrc_remove, 87d28c74c1SJosef Friedl .driver = { 88d28c74c1SJosef Friedl .name = "mt6323-pwrc", 89d28c74c1SJosef Friedl .of_match_table = mt6323_pwrc_dt_match, 90d28c74c1SJosef Friedl }, 91d28c74c1SJosef Friedl }; 92d28c74c1SJosef Friedl 93d28c74c1SJosef Friedl module_platform_driver(mt6323_pwrc_driver); 94d28c74c1SJosef Friedl 95d28c74c1SJosef Friedl MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC"); 96d28c74c1SJosef Friedl MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); 97d28c74c1SJosef Friedl MODULE_LICENSE("GPL v2"); 98