brintos

brintos / linux-shallow public Read only

0
0
Text · 10.1 KiB · 08ed171 Raw
398 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Xilinx Zynq Ultrascale+ MPSoC Real Time Clock Driver4 *5 * Copyright (C) 2015 Xilinx, Inc.6 *7 */8 9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/init.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <linux/rtc.h>17 18/* RTC Registers */19#define RTC_SET_TM_WR		0x0020#define RTC_SET_TM_RD		0x0421#define RTC_CALIB_WR		0x0822#define RTC_CALIB_RD		0x0C23#define RTC_CUR_TM		0x1024#define RTC_CUR_TICK		0x1425#define RTC_ALRM		0x1826#define RTC_INT_STS		0x2027#define RTC_INT_MASK		0x2428#define RTC_INT_EN		0x2829#define RTC_INT_DIS		0x2C30#define RTC_CTRL		0x4031 32#define RTC_FR_EN		BIT(20)33#define RTC_FR_DATSHIFT		1634#define RTC_TICK_MASK		0xFFFF35#define RTC_INT_SEC		BIT(0)36#define RTC_INT_ALRM		BIT(1)37#define RTC_OSC_EN		BIT(24)38#define RTC_BATT_EN		BIT(31)39 40#define RTC_CALIB_DEF		0x7FFF41#define RTC_CALIB_MASK		0x1FFFFF42#define RTC_ALRM_MASK          BIT(1)43#define RTC_MSEC               100044#define RTC_FR_MASK		0xF000045#define RTC_FR_MAX_TICKS	1646#define RTC_PPB			1000000000LL47#define RTC_MIN_OFFSET		-3276800048#define RTC_MAX_OFFSET		3276700049 50struct xlnx_rtc_dev {51	struct rtc_device	*rtc;52	void __iomem		*reg_base;53	int			alarm_irq;54	int			sec_irq;55	struct clk		*rtc_clk;56	unsigned int		freq;57};58 59static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)60{61	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);62	unsigned long new_time;63 64	/*65	 * The value written will be updated after 1 sec into the66	 * seconds read register, so we need to program time +1 sec67	 * to get the correct time on read.68	 */69	new_time = rtc_tm_to_time64(tm) + 1;70 71	writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);72 73	/*74	 * Clear the rtc interrupt status register after setting the75	 * time. During a read_time function, the code should read the76	 * RTC_INT_STATUS register and if bit 0 is still 0, it means77	 * that one second has not elapsed yet since RTC was set and78	 * the current time should be read from SET_TIME_READ register;79	 * otherwise, CURRENT_TIME register is read to report the time80	 */81	writel(RTC_INT_SEC, xrtcdev->reg_base + RTC_INT_STS);82 83	return 0;84}85 86static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)87{88	u32 status;89	unsigned long read_time;90	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);91 92	status = readl(xrtcdev->reg_base + RTC_INT_STS);93 94	if (status & RTC_INT_SEC) {95		/*96		 * RTC has updated the CURRENT_TIME with the time written into97		 * SET_TIME_WRITE register.98		 */99		read_time = readl(xrtcdev->reg_base + RTC_CUR_TM);100	} else {101		/*102		 * Time written in SET_TIME_WRITE has not yet updated into103		 * the seconds read register, so read the time from the104		 * SET_TIME_WRITE instead of CURRENT_TIME register.105		 * Since we add +1 sec while writing, we need to -1 sec while106		 * reading.107		 */108		read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1;109	}110	rtc_time64_to_tm(read_time, tm);111 112	return 0;113}114 115static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)116{117	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);118 119	rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_ALRM), &alrm->time);120	alrm->enabled = readl(xrtcdev->reg_base + RTC_INT_MASK) & RTC_INT_ALRM;121 122	return 0;123}124 125static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled)126{127	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);128	unsigned int status;129	ulong timeout;130 131	timeout = jiffies + msecs_to_jiffies(RTC_MSEC);132 133	if (enabled) {134		while (1) {135			status = readl(xrtcdev->reg_base + RTC_INT_STS);136			if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK))137				break;138 139			if (time_after_eq(jiffies, timeout)) {140				dev_err(dev, "Time out occur, while clearing alarm status bit\n");141				return -ETIMEDOUT;142			}143			writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);144		}145 146		writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);147	} else {148		writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);149	}150 151	return 0;152}153 154static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)155{156	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);157	unsigned long alarm_time;158 159	alarm_time = rtc_tm_to_time64(&alrm->time);160 161	writel((u32)alarm_time, (xrtcdev->reg_base + RTC_ALRM));162 163	xlnx_rtc_alarm_irq_enable(dev, alrm->enabled);164 165	return 0;166}167 168static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)169{170	u32 rtc_ctrl;171 172	/* Enable RTC switch to battery when VCC_PSAUX is not available */173	rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL);174	rtc_ctrl |= RTC_BATT_EN;175	writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL);176}177 178static int xlnx_rtc_read_offset(struct device *dev, long *offset)179{180	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);181	unsigned long long rtc_ppb = RTC_PPB;182	unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);183	unsigned int calibval;184	long offset_val;185 186	calibval = readl(xrtcdev->reg_base + RTC_CALIB_RD);187	/* Offset with seconds ticks */188	offset_val = calibval & RTC_TICK_MASK;189	offset_val = offset_val - RTC_CALIB_DEF;190	offset_val = offset_val * tick_mult;191 192	/* Offset with fractional ticks */193	if (calibval & RTC_FR_EN)194		offset_val += ((calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT)195			* (tick_mult / RTC_FR_MAX_TICKS);196	*offset = offset_val;197 198	return 0;199}200 201static int xlnx_rtc_set_offset(struct device *dev, long offset)202{203	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);204	unsigned long long rtc_ppb = RTC_PPB;205	unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);206	unsigned char fract_tick = 0;207	unsigned int calibval;208	short int  max_tick;209	int fract_offset;210 211	if (offset < RTC_MIN_OFFSET || offset > RTC_MAX_OFFSET)212		return -ERANGE;213 214	/* Number ticks for given offset */215	max_tick = div_s64_rem(offset, tick_mult, &fract_offset);216 217	/* Number fractional ticks for given offset */218	if (fract_offset) {219		if (fract_offset < 0) {220			fract_offset = fract_offset + tick_mult;221			max_tick--;222		}223		if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {224			for (fract_tick = 1; fract_tick < 16; fract_tick++) {225				if (fract_offset <=226				    (fract_tick *227				     (tick_mult / RTC_FR_MAX_TICKS)))228					break;229			}230		}231	}232 233	/* Zynqmp RTC uses second and fractional tick234	 * counters for compensation235	 */236	calibval = max_tick + RTC_CALIB_DEF;237 238	if (fract_tick)239		calibval |= RTC_FR_EN;240 241	calibval |= (fract_tick << RTC_FR_DATSHIFT);242 243	writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));244 245	return 0;246}247 248static const struct rtc_class_ops xlnx_rtc_ops = {249	.set_time	  = xlnx_rtc_set_time,250	.read_time	  = xlnx_rtc_read_time,251	.read_alarm	  = xlnx_rtc_read_alarm,252	.set_alarm	  = xlnx_rtc_set_alarm,253	.alarm_irq_enable = xlnx_rtc_alarm_irq_enable,254	.read_offset	  = xlnx_rtc_read_offset,255	.set_offset	  = xlnx_rtc_set_offset,256};257 258static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)259{260	struct xlnx_rtc_dev *xrtcdev = (struct xlnx_rtc_dev *)id;261	unsigned int status;262 263	status = readl(xrtcdev->reg_base + RTC_INT_STS);264	/* Check if interrupt asserted */265	if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))266		return IRQ_NONE;267 268	/* Disable RTC_INT_ALRM interrupt only */269	writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);270 271	if (status & RTC_INT_ALRM)272		rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);273 274	return IRQ_HANDLED;275}276 277static int xlnx_rtc_probe(struct platform_device *pdev)278{279	struct xlnx_rtc_dev *xrtcdev;280	int ret;281 282	xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL);283	if (!xrtcdev)284		return -ENOMEM;285 286	platform_set_drvdata(pdev, xrtcdev);287 288	xrtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);289	if (IS_ERR(xrtcdev->rtc))290		return PTR_ERR(xrtcdev->rtc);291 292	xrtcdev->rtc->ops = &xlnx_rtc_ops;293	xrtcdev->rtc->range_max = U32_MAX;294 295	xrtcdev->reg_base = devm_platform_ioremap_resource(pdev, 0);296	if (IS_ERR(xrtcdev->reg_base))297		return PTR_ERR(xrtcdev->reg_base);298 299	xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm");300	if (xrtcdev->alarm_irq < 0)301		return xrtcdev->alarm_irq;302	ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq,303			       xlnx_rtc_interrupt, 0,304			       dev_name(&pdev->dev), xrtcdev);305	if (ret) {306		dev_err(&pdev->dev, "request irq failed\n");307		return ret;308	}309 310	xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec");311	if (xrtcdev->sec_irq < 0)312		return xrtcdev->sec_irq;313	ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq,314			       xlnx_rtc_interrupt, 0,315			       dev_name(&pdev->dev), xrtcdev);316	if (ret) {317		dev_err(&pdev->dev, "request irq failed\n");318		return ret;319	}320 321	/* Getting the rtc_clk info */322	xrtcdev->rtc_clk = devm_clk_get_optional(&pdev->dev, "rtc_clk");323	if (IS_ERR(xrtcdev->rtc_clk)) {324		if (PTR_ERR(xrtcdev->rtc_clk) != -EPROBE_DEFER)325			dev_warn(&pdev->dev, "Device clock not found.\n");326	}327	xrtcdev->freq = clk_get_rate(xrtcdev->rtc_clk);328	if (!xrtcdev->freq) {329		ret = of_property_read_u32(pdev->dev.of_node, "calibration",330					   &xrtcdev->freq);331		if (ret)332			xrtcdev->freq = RTC_CALIB_DEF;333	}334	ret = readl(xrtcdev->reg_base + RTC_CALIB_RD);335	if (!ret)336		writel(xrtcdev->freq, (xrtcdev->reg_base + RTC_CALIB_WR));337 338	xlnx_init_rtc(xrtcdev);339 340	device_init_wakeup(&pdev->dev, 1);341 342	return devm_rtc_register_device(xrtcdev->rtc);343}344 345static void xlnx_rtc_remove(struct platform_device *pdev)346{347	xlnx_rtc_alarm_irq_enable(&pdev->dev, 0);348	device_init_wakeup(&pdev->dev, 0);349}350 351static int __maybe_unused xlnx_rtc_suspend(struct device *dev)352{353	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);354 355	if (device_may_wakeup(dev))356		enable_irq_wake(xrtcdev->alarm_irq);357	else358		xlnx_rtc_alarm_irq_enable(dev, 0);359 360	return 0;361}362 363static int __maybe_unused xlnx_rtc_resume(struct device *dev)364{365	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);366 367	if (device_may_wakeup(dev))368		disable_irq_wake(xrtcdev->alarm_irq);369	else370		xlnx_rtc_alarm_irq_enable(dev, 1);371 372	return 0;373}374 375static SIMPLE_DEV_PM_OPS(xlnx_rtc_pm_ops, xlnx_rtc_suspend, xlnx_rtc_resume);376 377static const struct of_device_id xlnx_rtc_of_match[] = {378	{.compatible = "xlnx,zynqmp-rtc" },379	{ }380};381MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match);382 383static struct platform_driver xlnx_rtc_driver = {384	.probe		= xlnx_rtc_probe,385	.remove_new	= xlnx_rtc_remove,386	.driver		= {387		.name	= KBUILD_MODNAME,388		.pm	= &xlnx_rtc_pm_ops,389		.of_match_table	= xlnx_rtc_of_match,390	},391};392 393module_platform_driver(xlnx_rtc_driver);394 395MODULE_DESCRIPTION("Xilinx Zynq MPSoC RTC driver");396MODULE_AUTHOR("Xilinx Inc.");397MODULE_LICENSE("GPL v2");398