rtc-at91rm9200.c 12.3 KB
Newer Older
A
Andrew Victor 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 *	Real Time Clock interface for Linux on Atmel AT91RM9200
 *
 *	Copyright (C) 2002 Rick Bronson
 *
 *	Converted to RTC class model by Andrew Victor
 *
 *	Ported to Linux 2.6 by Steven Scholz
 *	Based on s3c2410-rtc.c Simtec Electronics
 *
 *	Based on sa1100-rtc.c by Nils Faerber
 *	Based on rtc.c by Paul Gortmaker
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/interrupt.h>
28
#include <linux/spinlock.h>
A
Andrew Victor 已提交
29 30
#include <linux/ioctl.h>
#include <linux/completion.h>
A
Arnd Bergmann 已提交
31
#include <linux/io.h>
32 33
#include <linux/of.h>
#include <linux/of_device.h>
A
Andrew Victor 已提交
34 35

#include <asm/uaccess.h>
36

37
#include "rtc-at91rm9200.h"
38

39 40 41 42
#define at91_rtc_read(field) \
	__raw_readl(at91_rtc_regs + field)
#define at91_rtc_write(field, val) \
	__raw_writel((val), at91_rtc_regs + field)
A
Andrew Victor 已提交
43 44 45

#define AT91_RTC_EPOCH		1900UL	/* just like arch/arm/common/rtctime.c */

46
struct at91_rtc_config {
47
	bool use_shadow_imr;
48 49 50
};

static const struct at91_rtc_config *at91_rtc_config;
A
Andrew Victor 已提交
51 52
static DECLARE_COMPLETION(at91_rtc_updated);
static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
53 54
static void __iomem *at91_rtc_regs;
static int irq;
55 56
static DEFINE_SPINLOCK(at91_rtc_lock);
static u32 at91_rtc_shadow_imr;
A
Andrew Victor 已提交
57

58 59
static void at91_rtc_write_ier(u32 mask)
{
60 61 62 63
	unsigned long flags;

	spin_lock_irqsave(&at91_rtc_lock, flags);
	at91_rtc_shadow_imr |= mask;
64
	at91_rtc_write(AT91_RTC_IER, mask);
65
	spin_unlock_irqrestore(&at91_rtc_lock, flags);
66 67 68 69
}

static void at91_rtc_write_idr(u32 mask)
{
70 71 72
	unsigned long flags;

	spin_lock_irqsave(&at91_rtc_lock, flags);
73
	at91_rtc_write(AT91_RTC_IDR, mask);
74 75 76 77 78 79 80 81 82 83 84 85 86 87
	/*
	 * Register read back (of any RTC-register) needed to make sure
	 * IDR-register write has reached the peripheral before updating
	 * shadow mask.
	 *
	 * Note that there is still a possibility that the mask is updated
	 * before interrupts have actually been disabled in hardware. The only
	 * way to be certain would be to poll the IMR-register, which is is
	 * the very register we are trying to emulate. The register read back
	 * is a reasonable heuristic.
	 */
	at91_rtc_read(AT91_RTC_SR);
	at91_rtc_shadow_imr &= ~mask;
	spin_unlock_irqrestore(&at91_rtc_lock, flags);
88 89 90 91
}

static u32 at91_rtc_read_imr(void)
{
92 93 94 95 96 97 98 99 100 101 102 103
	unsigned long flags;
	u32 mask;

	if (at91_rtc_config->use_shadow_imr) {
		spin_lock_irqsave(&at91_rtc_lock, flags);
		mask = at91_rtc_shadow_imr;
		spin_unlock_irqrestore(&at91_rtc_lock, flags);
	} else {
		mask = at91_rtc_read(AT91_RTC_IMR);
	}

	return mask;
104 105
}

A
Andrew Victor 已提交
106 107 108
/*
 * Decode time/date into rtc_time structure
 */
109 110
static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
				struct rtc_time *tm)
A
Andrew Victor 已提交
111 112 113 114 115
{
	unsigned int time, date;

	/* must read twice in case it changes */
	do {
116 117 118 119
		time = at91_rtc_read(timereg);
		date = at91_rtc_read(calreg);
	} while ((time != at91_rtc_read(timereg)) ||
			(date != at91_rtc_read(calreg)));
A
Andrew Victor 已提交
120

A
Adrian Bunk 已提交
121 122 123
	tm->tm_sec  = bcd2bin((time & AT91_RTC_SEC) >> 0);
	tm->tm_min  = bcd2bin((time & AT91_RTC_MIN) >> 8);
	tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16);
A
Andrew Victor 已提交
124 125 126 127

	/*
	 * The Calendar Alarm register does not have a field for
	 * the year - so these will return an invalid value.  When an
L
Lucas De Marchi 已提交
128
	 * alarm is set, at91_alarm_year will store the current year.
A
Andrew Victor 已提交
129
	 */
A
Adrian Bunk 已提交
130 131
	tm->tm_year  = bcd2bin(date & AT91_RTC_CENT) * 100;	/* century */
	tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8);	/* year */
A
Andrew Victor 已提交
132

A
Adrian Bunk 已提交
133 134 135
	tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1;	/* day of the week [0-6], Sunday=0 */
	tm->tm_mon  = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1;
	tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24);
A
Andrew Victor 已提交
136 137 138 139 140 141 142 143 144 145 146
}

/*
 * Read current time and date in RTC
 */
static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
	tm->tm_year = tm->tm_year - 1900;

147
	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
148 149
		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec);
A
Andrew Victor 已提交
150 151 152 153 154 155 156 157 158 159 160

	return 0;
}

/*
 * Set current time and date in RTC
 */
static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
{
	unsigned long cr;

161
	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
162 163
		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec);
A
Andrew Victor 已提交
164 165

	/* Stop Time/Calendar from counting */
166 167
	cr = at91_rtc_read(AT91_RTC_CR);
	at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
A
Andrew Victor 已提交
168

169
	at91_rtc_write_ier(AT91_RTC_ACKUPD);
170
	wait_for_completion(&at91_rtc_updated);	/* wait for ACKUPD interrupt */
171
	at91_rtc_write_idr(AT91_RTC_ACKUPD);
A
Andrew Victor 已提交
172

173
	at91_rtc_write(AT91_RTC_TIMR,
A
Adrian Bunk 已提交
174 175 176
			  bin2bcd(tm->tm_sec) << 0
			| bin2bcd(tm->tm_min) << 8
			| bin2bcd(tm->tm_hour) << 16);
A
Andrew Victor 已提交
177

178
	at91_rtc_write(AT91_RTC_CALR,
A
Adrian Bunk 已提交
179 180 181 182 183
			  bin2bcd((tm->tm_year + 1900) / 100)	/* century */
			| bin2bcd(tm->tm_year % 100) << 8	/* year */
			| bin2bcd(tm->tm_mon + 1) << 16		/* tm_mon starts at zero */
			| bin2bcd(tm->tm_wday + 1) << 21	/* day of the week [0-6], Sunday=0 */
			| bin2bcd(tm->tm_mday) << 24);
A
Andrew Victor 已提交
184 185

	/* Restart Time/Calendar */
186 187
	cr = at91_rtc_read(AT91_RTC_CR);
	at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
A
Andrew Victor 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

	return 0;
}

/*
 * Read alarm time and date in RTC
 */
static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_time *tm = &alrm->time;

	at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
	tm->tm_year = at91_alarm_year - 1900;

203
	alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
204 205
			? 1 : 0;

206
	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
207 208
		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec);
A
Andrew Victor 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

	return 0;
}

/*
 * Set alarm time and date in RTC
 */
static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct rtc_time tm;

	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);

	at91_alarm_year = tm.tm_year;

	tm.tm_hour = alrm->time.tm_hour;
	tm.tm_min = alrm->time.tm_min;
	tm.tm_sec = alrm->time.tm_sec;

228
	at91_rtc_write_idr(AT91_RTC_ALARM);
229
	at91_rtc_write(AT91_RTC_TIMALR,
A
Adrian Bunk 已提交
230 231 232
		  bin2bcd(tm.tm_sec) << 0
		| bin2bcd(tm.tm_min) << 8
		| bin2bcd(tm.tm_hour) << 16
A
Andrew Victor 已提交
233
		| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
234
	at91_rtc_write(AT91_RTC_CALALR,
A
Adrian Bunk 已提交
235 236
		  bin2bcd(tm.tm_mon + 1) << 16		/* tm_mon starts at zero */
		| bin2bcd(tm.tm_mday) << 24
A
Andrew Victor 已提交
237 238
		| AT91_RTC_DATEEN | AT91_RTC_MTHEN);

239
	if (alrm->enabled) {
240
		at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
241
		at91_rtc_write_ier(AT91_RTC_ALARM);
242
	}
D
David Brownell 已提交
243

244
	dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
245 246
		at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
		tm.tm_min, tm.tm_sec);
A
Andrew Victor 已提交
247 248 249 250

	return 0;
}

251 252
static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
253
	dev_dbg(dev, "%s(): cmd=%08x\n", __func__, enabled);
254 255

	if (enabled) {
256
		at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
257
		at91_rtc_write_ier(AT91_RTC_ALARM);
258
	} else
259
		at91_rtc_write_idr(AT91_RTC_ALARM);
260 261 262

	return 0;
}
A
Andrew Victor 已提交
263 264 265 266 267
/*
 * Provide additional RTC information in /proc/driver/rtc
 */
static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
{
268
	unsigned long imr = at91_rtc_read_imr();
269

270
	seq_printf(seq, "update_IRQ\t: %s\n",
271
			(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
272
	seq_printf(seq, "periodic_IRQ\t: %s\n",
273
			(imr & AT91_RTC_SECEV) ? "yes" : "no");
A
Andrew Victor 已提交
274 275 276 277 278 279 280

	return 0;
}

/*
 * IRQ handler for the RTC
 */
281
static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
A
Andrew Victor 已提交
282
{
283
	struct platform_device *pdev = dev_id;
A
Andrew Victor 已提交
284 285 286 287
	struct rtc_device *rtc = platform_get_drvdata(pdev);
	unsigned int rtsr;
	unsigned long events = 0;

288
	rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read_imr();
A
Andrew Victor 已提交
289 290 291 292 293 294 295 296
	if (rtsr) {		/* this interrupt is shared!  Is it ours? */
		if (rtsr & AT91_RTC_ALARM)
			events |= (RTC_AF | RTC_IRQF);
		if (rtsr & AT91_RTC_SECEV)
			events |= (RTC_UF | RTC_IRQF);
		if (rtsr & AT91_RTC_ACKUPD)
			complete(&at91_rtc_updated);

297
		at91_rtc_write(AT91_RTC_SCCR, rtsr);	/* clear status reg */
A
Andrew Victor 已提交
298

299
		rtc_update_irq(rtc, 1, events);
A
Andrew Victor 已提交
300

301
		dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n", __func__,
A
Andrew Victor 已提交
302 303 304 305 306 307 308
			events >> 8, events & 0x000000FF);

		return IRQ_HANDLED;
	}
	return IRQ_NONE;		/* not handled */
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
static const struct at91_rtc_config at91rm9200_config = {
};

#ifdef CONFIG_OF
static const struct of_device_id at91_rtc_dt_ids[] = {
	{
		.compatible = "atmel,at91rm9200-rtc",
		.data = &at91rm9200_config,
	}, {
		/* sentinel */
	}
};
MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
#endif

static const struct at91_rtc_config *
at91_rtc_get_config(struct platform_device *pdev)
{
	const struct of_device_id *match;

	if (pdev->dev.of_node) {
		match = of_match_node(at91_rtc_dt_ids, pdev->dev.of_node);
		if (!match)
			return NULL;
		return (const struct at91_rtc_config *)match->data;
	}

	return &at91rm9200_config;
}

339
static const struct rtc_class_ops at91_rtc_ops = {
A
Andrew Victor 已提交
340 341 342 343 344
	.read_time	= at91_rtc_readtime,
	.set_time	= at91_rtc_settime,
	.read_alarm	= at91_rtc_readalarm,
	.set_alarm	= at91_rtc_setalarm,
	.proc		= at91_rtc_proc,
345
	.alarm_irq_enable = at91_rtc_alarm_irq_enable,
A
Andrew Victor 已提交
346 347 348 349 350 351 352 353
};

/*
 * Initialize and install RTC driver
 */
static int __init at91_rtc_probe(struct platform_device *pdev)
{
	struct rtc_device *rtc;
354 355
	struct resource *regs;
	int ret = 0;
A
Andrew Victor 已提交
356

357 358 359 360
	at91_rtc_config = at91_rtc_get_config(pdev);
	if (!at91_rtc_config)
		return -ENODEV;

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs) {
		dev_err(&pdev->dev, "no mmio resource defined\n");
		return -ENXIO;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "no irq resource defined\n");
		return -ENXIO;
	}

	at91_rtc_regs = ioremap(regs->start, resource_size(regs));
	if (!at91_rtc_regs) {
		dev_err(&pdev->dev, "failed to map registers, aborting.\n");
		return -ENOMEM;
	}

	at91_rtc_write(AT91_RTC_CR, 0);
	at91_rtc_write(AT91_RTC_MR, 0);		/* 24 hour mode */
A
Andrew Victor 已提交
381 382

	/* Disable all interrupts */
383
	at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
384 385
					AT91_RTC_SECEV | AT91_RTC_TIMEV |
					AT91_RTC_CALEV);
A
Andrew Victor 已提交
386

387
	ret = request_irq(irq, at91_rtc_interrupt,
D
David Brownell 已提交
388
				IRQF_SHARED,
389
				"at91_rtc", pdev);
A
Andrew Victor 已提交
390
	if (ret) {
391
		dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);
392
		goto err_unmap;
A
Andrew Victor 已提交
393 394
	}

D
David Brownell 已提交
395 396 397 398 399 400
	/* cpu init code should really have flagged this device as
	 * being wake-capable; if it didn't, do that here.
	 */
	if (!device_can_wakeup(&pdev->dev))
		device_init_wakeup(&pdev->dev, 1);

401 402
	rtc = rtc_device_register(pdev->name, &pdev->dev,
				&at91_rtc_ops, THIS_MODULE);
A
Andrew Victor 已提交
403
	if (IS_ERR(rtc)) {
404 405
		ret = PTR_ERR(rtc);
		goto err_free_irq;
A
Andrew Victor 已提交
406 407 408
	}
	platform_set_drvdata(pdev, rtc);

409
	dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
A
Andrew Victor 已提交
410
	return 0;
411 412 413 414 415 416 417

err_free_irq:
	free_irq(irq, pdev);
err_unmap:
	iounmap(at91_rtc_regs);

	return ret;
A
Andrew Victor 已提交
418 419 420 421 422
}

/*
 * Disable and remove the RTC driver
 */
D
David Brownell 已提交
423
static int __exit at91_rtc_remove(struct platform_device *pdev)
A
Andrew Victor 已提交
424 425 426 427
{
	struct rtc_device *rtc = platform_get_drvdata(pdev);

	/* Disable all interrupts */
428
	at91_rtc_write_idr(AT91_RTC_ACKUPD | AT91_RTC_ALARM |
429 430
					AT91_RTC_SECEV | AT91_RTC_TIMEV |
					AT91_RTC_CALEV);
431
	free_irq(irq, pdev);
A
Andrew Victor 已提交
432 433

	rtc_device_unregister(rtc);
434
	iounmap(at91_rtc_regs);
A
Andrew Victor 已提交
435 436 437 438 439
	platform_set_drvdata(pdev, NULL);

	return 0;
}

440
#ifdef CONFIG_PM_SLEEP
A
Andrew Victor 已提交
441 442 443

/* AT91RM9200 RTC Power management control */

444
static u32 at91_rtc_imr;
A
Andrew Victor 已提交
445

D
David Brownell 已提交
446
static int at91_rtc_suspend(struct device *dev)
A
Andrew Victor 已提交
447
{
448 449 450
	/* this IRQ is shared with DBGU and other hardware which isn't
	 * necessarily doing PM like we are...
	 */
451
	at91_rtc_imr = at91_rtc_read_imr()
452 453 454
			& (AT91_RTC_ALARM|AT91_RTC_SECEV);
	if (at91_rtc_imr) {
		if (device_may_wakeup(dev))
455
			enable_irq_wake(irq);
456
		else
457
			at91_rtc_write_idr(at91_rtc_imr);
458
	}
A
Andrew Victor 已提交
459 460 461
	return 0;
}

D
David Brownell 已提交
462
static int at91_rtc_resume(struct device *dev)
A
Andrew Victor 已提交
463
{
464 465
	if (at91_rtc_imr) {
		if (device_may_wakeup(dev))
466
			disable_irq_wake(irq);
467
		else
468
			at91_rtc_write_ier(at91_rtc_imr);
469
	}
A
Andrew Victor 已提交
470 471 472 473
	return 0;
}
#endif

474 475
static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);

A
Andrew Victor 已提交
476
static struct platform_driver at91_rtc_driver = {
D
David Brownell 已提交
477
	.remove		= __exit_p(at91_rtc_remove),
A
Andrew Victor 已提交
478 479 480
	.driver		= {
		.name	= "at91_rtc",
		.owner	= THIS_MODULE,
481
		.pm	= &at91_rtc_pm_ops,
482
		.of_match_table = of_match_ptr(at91_rtc_dt_ids),
A
Andrew Victor 已提交
483 484 485
	},
};

486
module_platform_driver_probe(at91_rtc_driver, at91_rtc_probe);
A
Andrew Victor 已提交
487 488 489 490

MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
MODULE_LICENSE("GPL");
491
MODULE_ALIAS("platform:at91_rtc");