Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: add support for the ST M48T59 RTC

[akpm@linux-foundation.org: x86_64 build fix]
[akpm@linux-foundation.org: The acpi guys changed the bin_attribute code]
Signed-off-by: Mark Zhan <rongkai.zhan@windriver.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Mark Zhan and committed by
Linus Torvalds
2e774c7c 617780d2

+559
+10
drivers/rtc/Kconfig
··· 310 310 This driver can also be built as a module. If so, the module 311 311 will be called rtc-m48t86. 312 312 313 + config RTC_DRV_M48T59 314 + tristate "ST M48T59" 315 + depends on RTC_CLASS 316 + help 317 + If you say Y here you will get support for the 318 + ST M48T59 RTC chip. 319 + 320 + This driver can also be built as a module, if so, the module 321 + will be called "rtc-m48t59". 322 + 313 323 config RTC_DRV_V3020 314 324 tristate "EM Microelectronic V3020" 315 325 depends on RTC_CLASS
+1
drivers/rtc/Makefile
··· 43 43 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o 44 44 obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o 45 45 obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o 46 + obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
+491
drivers/rtc/rtc-m48t59.c
··· 1 + /* 2 + * ST M48T59 RTC driver 3 + * 4 + * Copyright (c) 2007 Wind River Systems, Inc. 5 + * 6 + * Author: Mark Zhan <rongkai.zhan@windriver.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/init.h> 16 + #include <linux/io.h> 17 + #include <linux/device.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/rtc.h> 20 + #include <linux/rtc/m48t59.h> 21 + #include <linux/bcd.h> 22 + 23 + #ifndef NO_IRQ 24 + #define NO_IRQ (-1) 25 + #endif 26 + 27 + #define M48T59_READ(reg) pdata->read_byte(dev, reg) 28 + #define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) 29 + 30 + #define M48T59_SET_BITS(mask, reg) \ 31 + M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) 32 + #define M48T59_CLEAR_BITS(mask, reg) \ 33 + M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg)) 34 + 35 + struct m48t59_private { 36 + void __iomem *ioaddr; 37 + unsigned int size; /* iomem size */ 38 + unsigned int irq; 39 + struct rtc_device *rtc; 40 + spinlock_t lock; /* serialize the NVRAM and RTC access */ 41 + }; 42 + 43 + /* 44 + * This is the generic access method when the chip is memory-mapped 45 + */ 46 + static void 47 + m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val) 48 + { 49 + struct platform_device *pdev = to_platform_device(dev); 50 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 51 + 52 + writeb(val, m48t59->ioaddr+ofs); 53 + } 54 + 55 + static u8 56 + m48t59_mem_readb(struct device *dev, u32 ofs) 57 + { 58 + struct platform_device *pdev = to_platform_device(dev); 59 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 60 + 61 + return readb(m48t59->ioaddr+ofs); 62 + } 63 + 64 + /* 65 + * NOTE: M48T59 only uses BCD mode 66 + */ 67 + static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) 68 + { 69 + struct platform_device *pdev = to_platform_device(dev); 70 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 71 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 72 + unsigned long flags; 73 + u8 val; 74 + 75 + spin_lock_irqsave(&m48t59->lock, flags); 76 + /* Issue the READ command */ 77 + M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); 78 + 79 + tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); 80 + /* tm_mon is 0-11 */ 81 + tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; 82 + tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); 83 + 84 + val = M48T59_READ(M48T59_WDAY); 85 + if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { 86 + dev_dbg(dev, "Century bit is enabled\n"); 87 + tm->tm_year += 100; /* one century */ 88 + } 89 + 90 + tm->tm_wday = BCD2BIN(val & 0x07); 91 + tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F); 92 + tm->tm_min = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F); 93 + tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F); 94 + 95 + /* Clear the READ bit */ 96 + M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); 97 + spin_unlock_irqrestore(&m48t59->lock, flags); 98 + 99 + dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", 100 + tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, 101 + tm->tm_hour, tm->tm_min, tm->tm_sec); 102 + return 0; 103 + } 104 + 105 + static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) 106 + { 107 + struct platform_device *pdev = to_platform_device(dev); 108 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 109 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 110 + unsigned long flags; 111 + u8 val = 0; 112 + 113 + dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", 114 + tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, 115 + tm->tm_hour, tm->tm_min, tm->tm_sec); 116 + 117 + spin_lock_irqsave(&m48t59->lock, flags); 118 + /* Issue the WRITE command */ 119 + M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); 120 + 121 + M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC); 122 + M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN); 123 + M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR); 124 + M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY); 125 + /* tm_mon is 0-11 */ 126 + M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); 127 + M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); 128 + 129 + if (tm->tm_year/100) 130 + val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); 131 + val |= (BIN2BCD(tm->tm_wday) & 0x07); 132 + M48T59_WRITE(val, M48T59_WDAY); 133 + 134 + /* Clear the WRITE bit */ 135 + M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); 136 + spin_unlock_irqrestore(&m48t59->lock, flags); 137 + return 0; 138 + } 139 + 140 + /* 141 + * Read alarm time and date in RTC 142 + */ 143 + static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) 144 + { 145 + struct platform_device *pdev = to_platform_device(dev); 146 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 147 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 148 + struct rtc_time *tm = &alrm->time; 149 + unsigned long flags; 150 + u8 val; 151 + 152 + /* If no irq, we don't support ALARM */ 153 + if (m48t59->irq == NO_IRQ) 154 + return -EIO; 155 + 156 + spin_lock_irqsave(&m48t59->lock, flags); 157 + /* Issue the READ command */ 158 + M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); 159 + 160 + tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); 161 + /* tm_mon is 0-11 */ 162 + tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; 163 + 164 + val = M48T59_READ(M48T59_WDAY); 165 + if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) 166 + tm->tm_year += 100; /* one century */ 167 + 168 + tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE)); 169 + tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR)); 170 + tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN)); 171 + tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC)); 172 + 173 + /* Clear the READ bit */ 174 + M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); 175 + spin_unlock_irqrestore(&m48t59->lock, flags); 176 + 177 + dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", 178 + tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, 179 + tm->tm_hour, tm->tm_min, tm->tm_sec); 180 + return 0; 181 + } 182 + 183 + /* 184 + * Set alarm time and date in RTC 185 + */ 186 + static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 187 + { 188 + struct platform_device *pdev = to_platform_device(dev); 189 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 190 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 191 + struct rtc_time *tm = &alrm->time; 192 + u8 mday, hour, min, sec; 193 + unsigned long flags; 194 + 195 + /* If no irq, we don't support ALARM */ 196 + if (m48t59->irq == NO_IRQ) 197 + return -EIO; 198 + 199 + /* 200 + * 0xff means "always match" 201 + */ 202 + mday = tm->tm_mday; 203 + mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff; 204 + if (mday == 0xff) 205 + mday = M48T59_READ(M48T59_MDAY); 206 + 207 + hour = tm->tm_hour; 208 + hour = (hour < 24) ? BIN2BCD(hour) : 0x00; 209 + 210 + min = tm->tm_min; 211 + min = (min < 60) ? BIN2BCD(min) : 0x00; 212 + 213 + sec = tm->tm_sec; 214 + sec = (sec < 60) ? BIN2BCD(sec) : 0x00; 215 + 216 + spin_lock_irqsave(&m48t59->lock, flags); 217 + /* Issue the WRITE command */ 218 + M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); 219 + 220 + M48T59_WRITE(mday, M48T59_ALARM_DATE); 221 + M48T59_WRITE(hour, M48T59_ALARM_HOUR); 222 + M48T59_WRITE(min, M48T59_ALARM_MIN); 223 + M48T59_WRITE(sec, M48T59_ALARM_SEC); 224 + 225 + /* Clear the WRITE bit */ 226 + M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); 227 + spin_unlock_irqrestore(&m48t59->lock, flags); 228 + 229 + dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n", 230 + tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, 231 + tm->tm_hour, tm->tm_min, tm->tm_sec); 232 + return 0; 233 + } 234 + 235 + /* 236 + * Handle commands from user-space 237 + */ 238 + static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd, 239 + unsigned long arg) 240 + { 241 + struct platform_device *pdev = to_platform_device(dev); 242 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 243 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 244 + unsigned long flags; 245 + int ret = 0; 246 + 247 + spin_lock_irqsave(&m48t59->lock, flags); 248 + switch (cmd) { 249 + case RTC_AIE_OFF: /* alarm interrupt off */ 250 + M48T59_WRITE(0x00, M48T59_INTR); 251 + break; 252 + case RTC_AIE_ON: /* alarm interrupt on */ 253 + M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); 254 + break; 255 + default: 256 + ret = -ENOIOCTLCMD; 257 + break; 258 + } 259 + spin_unlock_irqrestore(&m48t59->lock, flags); 260 + 261 + return ret; 262 + } 263 + 264 + static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) 265 + { 266 + struct platform_device *pdev = to_platform_device(dev); 267 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 268 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 269 + unsigned long flags; 270 + u8 val; 271 + 272 + spin_lock_irqsave(&m48t59->lock, flags); 273 + val = M48T59_READ(M48T59_FLAGS); 274 + spin_unlock_irqrestore(&m48t59->lock, flags); 275 + 276 + seq_printf(seq, "battery\t\t: %s\n", 277 + (val & M48T59_FLAGS_BF) ? "low" : "normal"); 278 + return 0; 279 + } 280 + 281 + /* 282 + * IRQ handler for the RTC 283 + */ 284 + static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id) 285 + { 286 + struct device *dev = (struct device *)dev_id; 287 + struct platform_device *pdev = to_platform_device(dev); 288 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 289 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 290 + u8 event; 291 + 292 + spin_lock(&m48t59->lock); 293 + event = M48T59_READ(M48T59_FLAGS); 294 + spin_unlock(&m48t59->lock); 295 + 296 + if (event & M48T59_FLAGS_AF) { 297 + rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF)); 298 + return IRQ_HANDLED; 299 + } 300 + 301 + return IRQ_NONE; 302 + } 303 + 304 + static const struct rtc_class_ops m48t59_rtc_ops = { 305 + .ioctl = m48t59_rtc_ioctl, 306 + .read_time = m48t59_rtc_read_time, 307 + .set_time = m48t59_rtc_set_time, 308 + .read_alarm = m48t59_rtc_readalarm, 309 + .set_alarm = m48t59_rtc_setalarm, 310 + .proc = m48t59_rtc_proc, 311 + }; 312 + 313 + static ssize_t m48t59_nvram_read(struct kobject *kobj, 314 + struct bin_attribute *bin_attr, 315 + char *buf, loff_t pos, size_t size) 316 + { 317 + struct device *dev = container_of(kobj, struct device, kobj); 318 + struct platform_device *pdev = to_platform_device(dev); 319 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 320 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 321 + ssize_t cnt = 0; 322 + unsigned long flags; 323 + 324 + for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 325 + spin_lock_irqsave(&m48t59->lock, flags); 326 + *buf++ = M48T59_READ(cnt); 327 + spin_unlock_irqrestore(&m48t59->lock, flags); 328 + } 329 + 330 + return cnt; 331 + } 332 + 333 + static ssize_t m48t59_nvram_write(struct kobject *kobj, 334 + struct bin_attribute *bin_attr, 335 + char *buf, loff_t pos, size_t size) 336 + { 337 + struct device *dev = container_of(kobj, struct device, kobj); 338 + struct platform_device *pdev = to_platform_device(dev); 339 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 340 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 341 + ssize_t cnt = 0; 342 + unsigned long flags; 343 + 344 + for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 345 + spin_lock_irqsave(&m48t59->lock, flags); 346 + M48T59_WRITE(*buf++, cnt); 347 + spin_unlock_irqrestore(&m48t59->lock, flags); 348 + } 349 + 350 + return cnt; 351 + } 352 + 353 + static struct bin_attribute m48t59_nvram_attr = { 354 + .attr = { 355 + .name = "nvram", 356 + .mode = S_IRUGO | S_IWUGO, 357 + .owner = THIS_MODULE, 358 + }, 359 + .read = m48t59_nvram_read, 360 + .write = m48t59_nvram_write, 361 + }; 362 + 363 + static int __devinit m48t59_rtc_probe(struct platform_device *pdev) 364 + { 365 + struct m48t59_plat_data *pdata = pdev->dev.platform_data; 366 + struct m48t59_private *m48t59 = NULL; 367 + struct resource *res; 368 + int ret = -ENOMEM; 369 + 370 + /* This chip could be memory-mapped or I/O-mapped */ 371 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 372 + if (!res) { 373 + res = platform_get_resource(pdev, IORESOURCE_IO, 0); 374 + if (!res) 375 + return -EINVAL; 376 + } 377 + 378 + if (res->flags & IORESOURCE_IO) { 379 + /* If we are I/O-mapped, the platform should provide 380 + * the operations accessing chip registers. 381 + */ 382 + if (!pdata || !pdata->write_byte || !pdata->read_byte) 383 + return -EINVAL; 384 + } else if (res->flags & IORESOURCE_MEM) { 385 + /* we are memory-mapped */ 386 + if (!pdata) { 387 + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 388 + if (!pdata) 389 + return -ENOMEM; 390 + /* Ensure we only kmalloc platform data once */ 391 + pdev->dev.platform_data = pdata; 392 + } 393 + 394 + /* Try to use the generic memory read/write ops */ 395 + if (!pdata->write_byte) 396 + pdata->write_byte = m48t59_mem_writeb; 397 + if (!pdata->read_byte) 398 + pdata->read_byte = m48t59_mem_readb; 399 + } 400 + 401 + m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL); 402 + if (!m48t59) 403 + return -ENOMEM; 404 + 405 + m48t59->size = res->end - res->start + 1; 406 + m48t59->ioaddr = ioremap(res->start, m48t59->size); 407 + if (!m48t59->ioaddr) 408 + goto out; 409 + 410 + /* Try to get irq number. We also can work in 411 + * the mode without IRQ. 412 + */ 413 + m48t59->irq = platform_get_irq(pdev, 0); 414 + if (m48t59->irq < 0) 415 + m48t59->irq = NO_IRQ; 416 + 417 + if (m48t59->irq != NO_IRQ) { 418 + ret = request_irq(m48t59->irq, m48t59_rtc_interrupt, 419 + IRQF_SHARED, "rtc-m48t59", &pdev->dev); 420 + if (ret) 421 + goto out; 422 + } 423 + 424 + m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, 425 + &m48t59_rtc_ops, THIS_MODULE); 426 + if (IS_ERR(m48t59->rtc)) { 427 + ret = PTR_ERR(m48t59->rtc); 428 + goto out; 429 + } 430 + 431 + ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 432 + if (ret) 433 + goto out; 434 + 435 + spin_lock_init(&m48t59->lock); 436 + platform_set_drvdata(pdev, m48t59); 437 + return 0; 438 + 439 + out: 440 + if (!IS_ERR(m48t59->rtc)) 441 + rtc_device_unregister(m48t59->rtc); 442 + if (m48t59->irq != NO_IRQ) 443 + free_irq(m48t59->irq, &pdev->dev); 444 + if (m48t59->ioaddr) 445 + iounmap(m48t59->ioaddr); 446 + if (m48t59) 447 + kfree(m48t59); 448 + return ret; 449 + } 450 + 451 + static int __devexit m48t59_rtc_remove(struct platform_device *pdev) 452 + { 453 + struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 454 + 455 + sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 456 + if (!IS_ERR(m48t59->rtc)) 457 + rtc_device_unregister(m48t59->rtc); 458 + if (m48t59->ioaddr) 459 + iounmap(m48t59->ioaddr); 460 + if (m48t59->irq != NO_IRQ) 461 + free_irq(m48t59->irq, &pdev->dev); 462 + platform_set_drvdata(pdev, NULL); 463 + kfree(m48t59); 464 + return 0; 465 + } 466 + 467 + static struct platform_driver m48t59_rtc_platdrv = { 468 + .driver = { 469 + .name = "rtc-m48t59", 470 + .owner = THIS_MODULE, 471 + }, 472 + .probe = m48t59_rtc_probe, 473 + .remove = __devexit_p(m48t59_rtc_remove), 474 + }; 475 + 476 + static int __init m48t59_rtc_init(void) 477 + { 478 + return platform_driver_register(&m48t59_rtc_platdrv); 479 + } 480 + 481 + static void __exit m48t59_rtc_exit(void) 482 + { 483 + platform_driver_unregister(&m48t59_rtc_platdrv); 484 + } 485 + 486 + module_init(m48t59_rtc_init); 487 + module_exit(m48t59_rtc_exit); 488 + 489 + MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); 490 + MODULE_DESCRIPTION("M48T59 RTC driver"); 491 + MODULE_LICENSE("GPL");
+57
include/linux/rtc/m48t59.h
··· 1 + /* 2 + * include/linux/rtc/m48t59.h 3 + * 4 + * Definitions for the platform data of m48t59 RTC chip driver. 5 + * 6 + * Copyright (c) 2007 Wind River Systems, Inc. 7 + * 8 + * Mark Zhan <rongkai.zhan@windriver.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + */ 14 + 15 + #ifndef _LINUX_RTC_M48T59_H_ 16 + #define _LINUX_RTC_M48T59_H_ 17 + 18 + /* 19 + * M48T59 Register Offset 20 + */ 21 + #define M48T59_YEAR 0x1fff 22 + #define M48T59_MONTH 0x1ffe 23 + #define M48T59_MDAY 0x1ffd /* Day of Month */ 24 + #define M48T59_WDAY 0x1ffc /* Day of Week */ 25 + #define M48T59_WDAY_CB 0x20 /* Century Bit */ 26 + #define M48T59_WDAY_CEB 0x10 /* Century Enable Bit */ 27 + #define M48T59_HOUR 0x1ffb 28 + #define M48T59_MIN 0x1ffa 29 + #define M48T59_SEC 0x1ff9 30 + #define M48T59_CNTL 0x1ff8 31 + #define M48T59_CNTL_READ 0x40 32 + #define M48T59_CNTL_WRITE 0x80 33 + #define M48T59_WATCHDOG 0x1ff7 34 + #define M48T59_INTR 0x1ff6 35 + #define M48T59_INTR_AFE 0x80 /* Alarm Interrupt Enable */ 36 + #define M48T59_INTR_ABE 0x20 37 + #define M48T59_ALARM_DATE 0x1ff5 38 + #define M48T59_ALARM_HOUR 0x1ff4 39 + #define M48T59_ALARM_MIN 0x1ff3 40 + #define M48T59_ALARM_SEC 0x1ff2 41 + #define M48T59_UNUSED 0x1ff1 42 + #define M48T59_FLAGS 0x1ff0 43 + #define M48T59_FLAGS_WDT 0x80 /* watchdog timer expired */ 44 + #define M48T59_FLAGS_AF 0x40 /* alarm */ 45 + #define M48T59_FLAGS_BF 0x10 /* low battery */ 46 + 47 + #define M48T59_NVRAM_SIZE 0x1ff0 48 + 49 + struct m48t59_plat_data { 50 + /* The method to access M48T59 registers, 51 + * NOTE: The 'ofs' should be 0x00~0x1fff 52 + */ 53 + void (*write_byte)(struct device *dev, u32 ofs, u8 val); 54 + unsigned char (*read_byte)(struct device *dev, u32 ofs); 55 + }; 56 + 57 + #endif /* _LINUX_RTC_M48T59_H_ */