brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 094c649 Raw
410 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for MediaTek SoC based RTC4 *5 * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>6 */7 8#include <linux/clk.h>9#include <linux/interrupt.h>10#include <linux/io.h>11#include <linux/mod_devicetable.h>12#include <linux/module.h>13#include <linux/platform_device.h>14#include <linux/rtc.h>15 16#define MTK_RTC_DEV KBUILD_MODNAME17 18#define MTK_RTC_PWRCHK1		0x419#define	RTC_PWRCHK1_MAGIC	0xc620 21#define MTK_RTC_PWRCHK2		0x822#define	RTC_PWRCHK2_MAGIC	0x9a23 24#define MTK_RTC_KEY		0xc25#define	RTC_KEY_MAGIC		0x5926 27#define MTK_RTC_PROT1		0x1028#define	RTC_PROT1_MAGIC		0xa329 30#define MTK_RTC_PROT2		0x1431#define	RTC_PROT2_MAGIC		0x5732 33#define MTK_RTC_PROT3		0x1834#define	RTC_PROT3_MAGIC		0x6735 36#define MTK_RTC_PROT4		0x1c37#define	RTC_PROT4_MAGIC		0xd238 39#define MTK_RTC_CTL		0x2040#define	RTC_RC_STOP		BIT(0)41 42#define MTK_RTC_DEBNCE		0x2c43#define	RTC_DEBNCE_MASK		GENMASK(2, 0)44 45#define MTK_RTC_INT		0x3046#define RTC_INT_AL_STA		BIT(4)47 48/*49 * Ranges from 0x40 to 0x78 provide RTC time setup for year, month,50 * day of month, day of week, hour, minute and second.51 */52#define MTK_RTC_TREG(_t, _f)	(0x40 + (0x4 * (_f)) + ((_t) * 0x20))53 54#define MTK_RTC_AL_CTL		0x7c55#define	RTC_AL_EN		BIT(0)56#define	RTC_AL_ALL		GENMASK(7, 0)57 58/*59 * The offset is used in the translation for the year between in struct60 * rtc_time and in hardware register MTK_RTC_TREG(x,MTK_YEA)61 */62#define MTK_RTC_TM_YR_OFFSET	10063 64/*65 * The lowest value for the valid tm_year. RTC hardware would take incorrectly66 * tm_year 100 as not a leap year and thus it is also required being excluded67 * from the valid options.68 */69#define MTK_RTC_TM_YR_L		(MTK_RTC_TM_YR_OFFSET + 1)70 71/*72 * The most year the RTC can hold is 99 and the next to 99 in year register73 * would be wraparound to 0, for MT7622.74 */75#define MTK_RTC_HW_YR_LIMIT	9976 77/* The highest value for the valid tm_year */78#define MTK_RTC_TM_YR_H		(MTK_RTC_TM_YR_OFFSET + MTK_RTC_HW_YR_LIMIT)79 80/* Simple macro helps to check whether the hardware supports the tm_year */81#define MTK_RTC_TM_YR_VALID(_y)	((_y) >= MTK_RTC_TM_YR_L && \82				 (_y) <= MTK_RTC_TM_YR_H)83 84/* Types of the function the RTC provides are time counter and alarm. */85enum {86	MTK_TC,87	MTK_AL,88};89 90/* Indexes are used for the pointer to relevant registers in MTK_RTC_TREG */91enum {92	MTK_YEA,93	MTK_MON,94	MTK_DOM,95	MTK_DOW,96	MTK_HOU,97	MTK_MIN,98	MTK_SEC99};100 101struct mtk_rtc {102	struct rtc_device *rtc;103	void __iomem *base;104	int irq;105	struct clk *clk;106};107 108static void mtk_w32(struct mtk_rtc *rtc, u32 reg, u32 val)109{110	writel_relaxed(val, rtc->base + reg);111}112 113static u32 mtk_r32(struct mtk_rtc *rtc, u32 reg)114{115	return readl_relaxed(rtc->base + reg);116}117 118static void mtk_rmw(struct mtk_rtc *rtc, u32 reg, u32 mask, u32 set)119{120	u32 val;121 122	val = mtk_r32(rtc, reg);123	val &= ~mask;124	val |= set;125	mtk_w32(rtc, reg, val);126}127 128static void mtk_set(struct mtk_rtc *rtc, u32 reg, u32 val)129{130	mtk_rmw(rtc, reg, 0, val);131}132 133static void mtk_clr(struct mtk_rtc *rtc, u32 reg, u32 val)134{135	mtk_rmw(rtc, reg, val, 0);136}137 138static void mtk_rtc_hw_init(struct mtk_rtc *hw)139{140	/* The setup of the init sequence is for allowing RTC got to work */141	mtk_w32(hw, MTK_RTC_PWRCHK1, RTC_PWRCHK1_MAGIC);142	mtk_w32(hw, MTK_RTC_PWRCHK2, RTC_PWRCHK2_MAGIC);143	mtk_w32(hw, MTK_RTC_KEY, RTC_KEY_MAGIC);144	mtk_w32(hw, MTK_RTC_PROT1, RTC_PROT1_MAGIC);145	mtk_w32(hw, MTK_RTC_PROT2, RTC_PROT2_MAGIC);146	mtk_w32(hw, MTK_RTC_PROT3, RTC_PROT3_MAGIC);147	mtk_w32(hw, MTK_RTC_PROT4, RTC_PROT4_MAGIC);148	mtk_rmw(hw, MTK_RTC_DEBNCE, RTC_DEBNCE_MASK, 0);149	mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP);150}151 152static void mtk_rtc_get_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,153				      int time_alarm)154{155	u32 year, mon, mday, wday, hour, min, sec;156 157	/*158	 * Read again until the field of the second is not changed which159	 * ensures all fields in the consistent state. Note that MTK_SEC must160	 * be read first. In this way, it guarantees the others remain not161	 * changed when the results for two MTK_SEC consecutive reads are same.162	 */163	do {164		sec = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC));165		min = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN));166		hour = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU));167		wday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW));168		mday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM));169		mon = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MON));170		year = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA));171	} while (sec != mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC)));172 173	tm->tm_sec  = sec;174	tm->tm_min  = min;175	tm->tm_hour = hour;176	tm->tm_wday = wday;177	tm->tm_mday = mday;178	tm->tm_mon  = mon - 1;179 180	/* Rebase to the absolute year which userspace queries */181	tm->tm_year = year + MTK_RTC_TM_YR_OFFSET;182}183 184static void mtk_rtc_set_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm,185				      int time_alarm)186{187	u32 year;188 189	/* Rebase to the relative year which RTC hardware requires */190	year = tm->tm_year - MTK_RTC_TM_YR_OFFSET;191 192	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA), year);193	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MON), tm->tm_mon + 1);194	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW), tm->tm_wday);195	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM), tm->tm_mday);196	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU), tm->tm_hour);197	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN), tm->tm_min);198	mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC), tm->tm_sec);199}200 201static irqreturn_t mtk_rtc_alarmirq(int irq, void *id)202{203	struct mtk_rtc *hw = (struct mtk_rtc *)id;204	u32 irq_sta;205 206	irq_sta = mtk_r32(hw, MTK_RTC_INT);207	if (irq_sta & RTC_INT_AL_STA) {208		/* Stop alarm also implicitly disables the alarm interrupt */209		mtk_w32(hw, MTK_RTC_AL_CTL, 0);210		rtc_update_irq(hw->rtc, 1, RTC_IRQF | RTC_AF);211 212		/* Ack alarm interrupt status */213		mtk_w32(hw, MTK_RTC_INT, RTC_INT_AL_STA);214		return IRQ_HANDLED;215	}216 217	return IRQ_NONE;218}219 220static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm)221{222	struct mtk_rtc *hw = dev_get_drvdata(dev);223 224	mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC);225 226	return 0;227}228 229static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm)230{231	struct mtk_rtc *hw = dev_get_drvdata(dev);232 233	if (!MTK_RTC_TM_YR_VALID(tm->tm_year))234		return -EINVAL;235 236	/* Stop time counter before setting a new one*/237	mtk_set(hw, MTK_RTC_CTL, RTC_RC_STOP);238 239	mtk_rtc_set_alarm_or_time(hw, tm, MTK_TC);240 241	/* Restart the time counter */242	mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP);243 244	return 0;245}246 247static int mtk_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)248{249	struct mtk_rtc *hw = dev_get_drvdata(dev);250	struct rtc_time *alrm_tm = &wkalrm->time;251 252	mtk_rtc_get_alarm_or_time(hw, alrm_tm, MTK_AL);253 254	wkalrm->enabled = !!(mtk_r32(hw, MTK_RTC_AL_CTL) & RTC_AL_EN);255	wkalrm->pending = !!(mtk_r32(hw, MTK_RTC_INT) & RTC_INT_AL_STA);256 257	return 0;258}259 260static int mtk_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)261{262	struct mtk_rtc *hw = dev_get_drvdata(dev);263	struct rtc_time *alrm_tm = &wkalrm->time;264 265	if (!MTK_RTC_TM_YR_VALID(alrm_tm->tm_year))266		return -EINVAL;267 268	/*269	 * Stop the alarm also implicitly including disables interrupt before270	 * setting a new one.271	 */272	mtk_clr(hw, MTK_RTC_AL_CTL, RTC_AL_EN);273 274	/*275	 * Avoid contention between mtk_rtc_setalarm and IRQ handler so that276	 * disabling the interrupt and awaiting for pending IRQ handler to277	 * complete.278	 */279	synchronize_irq(hw->irq);280 281	mtk_rtc_set_alarm_or_time(hw, alrm_tm, MTK_AL);282 283	/* Restart the alarm with the new setup */284	mtk_w32(hw, MTK_RTC_AL_CTL, RTC_AL_ALL);285 286	return 0;287}288 289static const struct rtc_class_ops mtk_rtc_ops = {290	.read_time		= mtk_rtc_gettime,291	.set_time		= mtk_rtc_settime,292	.read_alarm		= mtk_rtc_getalarm,293	.set_alarm		= mtk_rtc_setalarm,294};295 296static const struct of_device_id mtk_rtc_match[] = {297	{ .compatible = "mediatek,mt7622-rtc" },298	{ .compatible = "mediatek,soc-rtc" },299	{},300};301MODULE_DEVICE_TABLE(of, mtk_rtc_match);302 303static int mtk_rtc_probe(struct platform_device *pdev)304{305	struct mtk_rtc *hw;306	int ret;307 308	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);309	if (!hw)310		return -ENOMEM;311 312	platform_set_drvdata(pdev, hw);313 314	hw->base = devm_platform_ioremap_resource(pdev, 0);315	if (IS_ERR(hw->base))316		return PTR_ERR(hw->base);317 318	hw->clk = devm_clk_get(&pdev->dev, "rtc");319	if (IS_ERR(hw->clk)) {320		dev_err(&pdev->dev, "No clock\n");321		return PTR_ERR(hw->clk);322	}323 324	ret = clk_prepare_enable(hw->clk);325	if (ret)326		return ret;327 328	hw->irq = platform_get_irq(pdev, 0);329	if (hw->irq < 0) {330		ret = hw->irq;331		goto err;332	}333 334	ret = devm_request_irq(&pdev->dev, hw->irq, mtk_rtc_alarmirq,335			       0, dev_name(&pdev->dev), hw);336	if (ret) {337		dev_err(&pdev->dev, "Can't request IRQ\n");338		goto err;339	}340 341	mtk_rtc_hw_init(hw);342 343	device_init_wakeup(&pdev->dev, true);344 345	hw->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,346					   &mtk_rtc_ops, THIS_MODULE);347	if (IS_ERR(hw->rtc)) {348		ret = PTR_ERR(hw->rtc);349		dev_err(&pdev->dev, "Unable to register device\n");350		goto err;351	}352 353	return 0;354err:355	clk_disable_unprepare(hw->clk);356 357	return ret;358}359 360static void mtk_rtc_remove(struct platform_device *pdev)361{362	struct mtk_rtc *hw = platform_get_drvdata(pdev);363 364	clk_disable_unprepare(hw->clk);365}366 367#ifdef CONFIG_PM_SLEEP368static int mtk_rtc_suspend(struct device *dev)369{370	struct mtk_rtc *hw = dev_get_drvdata(dev);371 372	if (device_may_wakeup(dev))373		enable_irq_wake(hw->irq);374 375	return 0;376}377 378static int mtk_rtc_resume(struct device *dev)379{380	struct mtk_rtc *hw = dev_get_drvdata(dev);381 382	if (device_may_wakeup(dev))383		disable_irq_wake(hw->irq);384 385	return 0;386}387 388static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume);389 390#define MTK_RTC_PM_OPS (&mtk_rtc_pm_ops)391#else	/* CONFIG_PM */392#define MTK_RTC_PM_OPS NULL393#endif	/* CONFIG_PM */394 395static struct platform_driver mtk_rtc_driver = {396	.probe	= mtk_rtc_probe,397	.remove_new = mtk_rtc_remove,398	.driver = {399		.name = MTK_RTC_DEV,400		.of_match_table = mtk_rtc_match,401		.pm = MTK_RTC_PM_OPS,402	},403};404 405module_platform_driver(mtk_rtc_driver);406 407MODULE_DESCRIPTION("MediaTek SoC based RTC Driver");408MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");409MODULE_LICENSE("GPL");410