Commit 7c5b0264 authored by Lee Jones's avatar Lee Jones

Merge branches 'ib-mfd-doc-sparc-libdevres-5.5' and 'ib-mfd-power-rtc-5.5' into ibs-for-mfd-merged

parents 7b8c4d73 9d0863ba
Device-Tree bindings for MediaTek PMIC based RTC
MediaTek PMIC based RTC is an independent function of MediaTek PMIC that works
as a type of multi-function device (MFD). The RTC can be configured and set up
with PMIC wrapper bus which is a common resource shared with the other
functions found on the same PMIC.
For MediaTek PMIC MFD bindings, see:
../mfd/mt6397.txt
For MediaTek PMIC wrapper bus bindings, see:
../soc/mediatek/pwrap.txt
Required properties:
- compatible: Should be one of follows
"mediatek,mt6323-rtc": for MT6323 PMIC
"mediatek,mt6397-rtc": for MT6397 PMIC
Example:
pmic {
compatible = "mediatek,mt6323";
...
rtc {
compatible = "mediatek,mt6323-rtc";
};
};
...@@ -10266,6 +10266,13 @@ S: Maintained ...@@ -10266,6 +10266,13 @@ S: Maintained
F: drivers/net/dsa/mt7530.* F: drivers/net/dsa/mt7530.*
F: net/dsa/tag_mtk.c F: net/dsa/tag_mtk.c
MEDIATEK BOARD LEVEL SHUTDOWN DRIVERS
M: Sean Wang <sean.wang@mediatek.com>
L: linux-pm@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/power/reset/mt6323-poweroff.txt
F: drivers/power/reset/mt6323-poweroff.c
MEDIATEK JPEG DRIVER MEDIATEK JPEG DRIVER
M: Rick Chang <rick.chang@mediatek.com> M: Rick Chang <rick.chang@mediatek.com>
M: Bin Liu <bin.liu@mediatek.com> M: Bin Liu <bin.liu@mediatek.com>
......
...@@ -140,6 +140,16 @@ config POWER_RESET_LTC2952 ...@@ -140,6 +140,16 @@ config POWER_RESET_LTC2952
This driver supports an external powerdown trigger and board power This driver supports an external powerdown trigger and board power
down via the LTC2952. Bindings are made in the device tree. down via the LTC2952. Bindings are made in the device tree.
config POWER_RESET_MT6323
bool "MediaTek MT6323 power-off driver"
depends on MFD_MT6397
help
The power-off driver is responsible for externally shutdown down
the power of a remote MediaTek SoC MT6323 is connected to through
controlling a tiny circuit BBPU inside MT6323 RTC.
Say Y if you have a board where MT6323 could be found.
config POWER_RESET_QNAP config POWER_RESET_QNAP
bool "QNAP power-off driver" bool "QNAP power-off driver"
depends on OF_GPIO && PLAT_ORION depends on OF_GPIO && PLAT_ORION
......
...@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o ...@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Power off through MediaTek PMIC
*
* Copyright (C) 2018 MediaTek Inc.
*
* Author: Sean Wang <sean.wang@mediatek.com>
*
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/rtc.h>
struct mt6323_pwrc {
struct device *dev;
struct regmap *regmap;
u32 base;
};
static struct mt6323_pwrc *mt_pwrc;
static void mt6323_do_pwroff(void)
{
struct mt6323_pwrc *pwrc = mt_pwrc;
unsigned int val;
int ret;
regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY);
regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR, 1);
ret = regmap_read_poll_timeout(pwrc->regmap,
pwrc->base + RTC_BBPU, val,
!(val & RTC_BBPU_CBUSY),
MTK_RTC_POLL_DELAY_US,
MTK_RTC_POLL_TIMEOUT);
if (ret)
dev_err(pwrc->dev, "failed to write BBPU: %d\n", ret);
/* Wait some time until system down, otherwise, notice with a warn */
mdelay(1000);
WARN_ONCE(1, "Unable to power off system\n");
}
static int mt6323_pwrc_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
struct mt6323_pwrc *pwrc;
struct resource *res;
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
mt_pwrc = pwrc;
pm_power_off = &mt6323_do_pwroff;
return 0;
}
static int mt6323_pwrc_remove(struct platform_device *pdev)
{
if (pm_power_off == &mt6323_do_pwroff)
pm_power_off = NULL;
return 0;
}
static const struct of_device_id mt6323_pwrc_dt_match[] = {
{ .compatible = "mediatek,mt6323-pwrc" },
{},
};
MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe,
.remove = mt6323_pwrc_remove,
.driver = {
.name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match,
},
};
module_platform_driver(mt6323_pwrc_driver);
MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC");
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_LICENSE("GPL v2");
...@@ -4,69 +4,19 @@ ...@@ -4,69 +4,19 @@
* Author: Tianping.Fang <tianping.fang@mediatek.com> * Author: Tianping.Fang <tianping.fang@mediatek.com>
*/ */
#include <linux/delay.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/interrupt.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/irqdomain.h> #include <linux/mfd/mt6397/rtc.h>
#include <linux/platform_device.h> #include <linux/mod_devicetable.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/mfd/mt6397/core.h>
#define RTC_BBPU 0x0000
#define RTC_BBPU_CBUSY BIT(6)
#define RTC_WRTGR 0x003c
#define RTC_IRQ_STA 0x0002
#define RTC_IRQ_STA_AL BIT(0)
#define RTC_IRQ_STA_LP BIT(3)
#define RTC_IRQ_EN 0x0004
#define RTC_IRQ_EN_AL BIT(0)
#define RTC_IRQ_EN_ONESHOT BIT(2)
#define RTC_IRQ_EN_LP BIT(3)
#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
#define RTC_AL_MASK 0x0008
#define RTC_AL_MASK_DOW BIT(4)
#define RTC_TC_SEC 0x000a
/* Min, Hour, Dom... register offset to RTC_TC_SEC */
#define RTC_OFFSET_SEC 0
#define RTC_OFFSET_MIN 1
#define RTC_OFFSET_HOUR 2
#define RTC_OFFSET_DOM 3
#define RTC_OFFSET_DOW 4
#define RTC_OFFSET_MTH 5
#define RTC_OFFSET_YEAR 6
#define RTC_OFFSET_COUNT 7
#define RTC_AL_SEC 0x0018
#define RTC_PDN2 0x002e
#define RTC_PDN2_PWRON_ALARM BIT(4)
#define RTC_MIN_YEAR 1968
#define RTC_BASE_YEAR 1900
#define RTC_NUM_YEARS 128
#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
struct mt6397_rtc {
struct device *dev;
struct rtc_device *rtc_dev;
struct mutex lock;
struct regmap *regmap;
int irq;
u32 addr_base;
};
static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
{ {
unsigned long timeout = jiffies + HZ;
int ret; int ret;
u32 data; u32 data;
...@@ -74,19 +24,13 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) ...@@ -74,19 +24,13 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
if (ret < 0) if (ret < 0)
return ret; return ret;
while (1) { ret = regmap_read_poll_timeout(rtc->regmap,
ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU, rtc->addr_base + RTC_BBPU, data,
&data); !(data & RTC_BBPU_CBUSY),
if (ret < 0) MTK_RTC_POLL_DELAY_US,
break; MTK_RTC_POLL_TIMEOUT);
if (!(data & RTC_BBPU_CBUSY)) if (ret < 0)
break; dev_err(rtc->dev, "failed to write WRTGE: %d\n", ret);
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
break;
}
cpu_relax();
}
return ret; return ret;
} }
...@@ -319,19 +263,19 @@ static int mtk_rtc_probe(struct platform_device *pdev) ...@@ -319,19 +263,19 @@ static int mtk_rtc_probe(struct platform_device *pdev)
return rtc->irq; return rtc->irq;
rtc->regmap = mt6397_chip->regmap; rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev;
mutex_init(&rtc->lock); mutex_init(&rtc->lock);
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc_dev)) if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev); return PTR_ERR(rtc->rtc_dev);
ret = request_threaded_irq(rtc->irq, NULL, ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
mtk_rtc_irq_handler_thread, mtk_rtc_irq_handler_thread,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
"mt6397-rtc", rtc); "mt6397-rtc", rtc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
rtc->irq, ret); rtc->irq, ret);
...@@ -353,15 +297,6 @@ static int mtk_rtc_probe(struct platform_device *pdev) ...@@ -353,15 +297,6 @@ static int mtk_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int mtk_rtc_remove(struct platform_device *pdev)
{
struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
free_irq(rtc->irq, rtc);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int mt6397_rtc_suspend(struct device *dev) static int mt6397_rtc_suspend(struct device *dev)
{ {
...@@ -388,6 +323,7 @@ static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend, ...@@ -388,6 +323,7 @@ static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend,
mt6397_rtc_resume); mt6397_rtc_resume);
static const struct of_device_id mt6397_rtc_of_match[] = { static const struct of_device_id mt6397_rtc_of_match[] = {
{ .compatible = "mediatek,mt6323-rtc", },
{ .compatible = "mediatek,mt6397-rtc", }, { .compatible = "mediatek,mt6397-rtc", },
{ } { }
}; };
...@@ -400,7 +336,6 @@ static struct platform_driver mtk_rtc_driver = { ...@@ -400,7 +336,6 @@ static struct platform_driver mtk_rtc_driver = {
.pm = &mt6397_pm_ops, .pm = &mt6397_pm_ops,
}, },
.probe = mtk_rtc_probe, .probe = mtk_rtc_probe,
.remove = mtk_rtc_remove,
}; };
module_platform_driver(mtk_rtc_driver); module_platform_driver(mtk_rtc_driver);
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2014-2019 MediaTek Inc.
*
* Author: Tianping.Fang <tianping.fang@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*/
#ifndef _LINUX_MFD_MT6397_RTC_H_
#define _LINUX_MFD_MT6397_RTC_H_
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#define RTC_BBPU 0x0000
#define RTC_BBPU_CBUSY BIT(6)
#define RTC_BBPU_KEY (0x43 << 8)
#define RTC_WRTGR 0x003c
#define RTC_IRQ_STA 0x0002
#define RTC_IRQ_STA_AL BIT(0)
#define RTC_IRQ_STA_LP BIT(3)
#define RTC_IRQ_EN 0x0004
#define RTC_IRQ_EN_AL BIT(0)
#define RTC_IRQ_EN_ONESHOT BIT(2)
#define RTC_IRQ_EN_LP BIT(3)
#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
#define RTC_AL_MASK 0x0008
#define RTC_AL_MASK_DOW BIT(4)
#define RTC_TC_SEC 0x000a
/* Min, Hour, Dom... register offset to RTC_TC_SEC */
#define RTC_OFFSET_SEC 0
#define RTC_OFFSET_MIN 1
#define RTC_OFFSET_HOUR 2
#define RTC_OFFSET_DOM 3
#define RTC_OFFSET_DOW 4
#define RTC_OFFSET_MTH 5
#define RTC_OFFSET_YEAR 6
#define RTC_OFFSET_COUNT 7
#define RTC_AL_SEC 0x0018
#define RTC_PDN2 0x002e
#define RTC_PDN2_PWRON_ALARM BIT(4)
#define RTC_MIN_YEAR 1968
#define RTC_BASE_YEAR 1900
#define RTC_NUM_YEARS 128
#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
#define MTK_RTC_POLL_DELAY_US 10
#define MTK_RTC_POLL_TIMEOUT (jiffies_to_usecs(HZ))
struct mt6397_rtc {
struct device *dev;
struct rtc_device *rtc_dev;
/* Protect register access from multiple tasks */
struct mutex lock;
struct regmap *regmap;
int irq;
u32 addr_base;
};
#endif /* _LINUX_MFD_MT6397_RTC_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment