Blame view
drivers/rtc/rtc-m41t94.c
4.29 KB
8fc2c767b rtc: add support ... |
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/* * Driver for ST M41T94 SPI RTC * * Copyright (C) 2008 Kim B. Heino * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/rtc.h> #include <linux/spi/spi.h> #include <linux/bcd.h> #define M41T94_REG_SECONDS 0x01 #define M41T94_REG_MINUTES 0x02 #define M41T94_REG_HOURS 0x03 #define M41T94_REG_WDAY 0x04 #define M41T94_REG_DAY 0x05 #define M41T94_REG_MONTH 0x06 #define M41T94_REG_YEAR 0x07 #define M41T94_REG_HT 0x0c #define M41T94_BIT_HALT 0x40 #define M41T94_BIT_STOP 0x80 #define M41T94_BIT_CB 0x40 #define M41T94_BIT_CEB 0x80 static int m41t94_set_time(struct device *dev, struct rtc_time *tm) { struct spi_device *spi = to_spi_device(dev); u8 buf[8]; /* write cmd + 7 registers */ dev_dbg(dev, "%s secs=%d, mins=%d, " "hours=%d, mday=%d, mon=%d, year=%d, wday=%d ", "write", tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */ |
fe20ba70a drivers/rtc/: use... |
45 46 47 48 49 50 |
buf[M41T94_REG_SECONDS] = bin2bcd(tm->tm_sec); buf[M41T94_REG_MINUTES] = bin2bcd(tm->tm_min); buf[M41T94_REG_HOURS] = bin2bcd(tm->tm_hour); buf[M41T94_REG_WDAY] = bin2bcd(tm->tm_wday + 1); buf[M41T94_REG_DAY] = bin2bcd(tm->tm_mday); buf[M41T94_REG_MONTH] = bin2bcd(tm->tm_mon + 1); |
8fc2c767b rtc: add support ... |
51 52 53 54 |
buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB; if (tm->tm_year >= 100) buf[M41T94_REG_HOURS] |= M41T94_BIT_CB; |
fe20ba70a drivers/rtc/: use... |
55 |
buf[M41T94_REG_YEAR] = bin2bcd(tm->tm_year % 100); |
8fc2c767b rtc: add support ... |
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
return spi_write(spi, buf, 8); } static int m41t94_read_time(struct device *dev, struct rtc_time *tm) { struct spi_device *spi = to_spi_device(dev); u8 buf[2]; int ret, hour; /* clear halt update bit */ ret = spi_w8r8(spi, M41T94_REG_HT); if (ret < 0) return ret; if (ret & M41T94_BIT_HALT) { buf[0] = 0x80 | M41T94_REG_HT; buf[1] = ret & ~M41T94_BIT_HALT; spi_write(spi, buf, 2); } /* clear stop bit */ ret = spi_w8r8(spi, M41T94_REG_SECONDS); if (ret < 0) return ret; if (ret & M41T94_BIT_STOP) { buf[0] = 0x80 | M41T94_REG_SECONDS; buf[1] = ret & ~M41T94_BIT_STOP; spi_write(spi, buf, 2); } |
fe20ba70a drivers/rtc/: use... |
85 86 |
tm->tm_sec = bcd2bin(spi_w8r8(spi, M41T94_REG_SECONDS)); tm->tm_min = bcd2bin(spi_w8r8(spi, M41T94_REG_MINUTES)); |
8fc2c767b rtc: add support ... |
87 |
hour = spi_w8r8(spi, M41T94_REG_HOURS); |
fe20ba70a drivers/rtc/: use... |
88 89 90 91 92 |
tm->tm_hour = bcd2bin(hour & 0x3f); tm->tm_wday = bcd2bin(spi_w8r8(spi, M41T94_REG_WDAY)) - 1; tm->tm_mday = bcd2bin(spi_w8r8(spi, M41T94_REG_DAY)); tm->tm_mon = bcd2bin(spi_w8r8(spi, M41T94_REG_MONTH)) - 1; tm->tm_year = bcd2bin(spi_w8r8(spi, M41T94_REG_YEAR)); |
8fc2c767b rtc: add support ... |
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB)) tm->tm_year += 100; dev_dbg(dev, "%s secs=%d, mins=%d, " "hours=%d, mday=%d, mon=%d, year=%d, wday=%d ", "read", tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); /* initial clock setting can be undefined */ return rtc_valid_tm(tm); } static const struct rtc_class_ops m41t94_rtc_ops = { .read_time = m41t94_read_time, .set_time = m41t94_set_time, }; static struct spi_driver m41t94_driver; static int __devinit m41t94_probe(struct spi_device *spi) { struct rtc_device *rtc; int res; spi->bits_per_word = 8; spi_setup(spi); res = spi_w8r8(spi, M41T94_REG_SECONDS); if (res < 0) { dev_err(&spi->dev, "not found. "); return res; } rtc = rtc_device_register(m41t94_driver.driver.name, &spi->dev, &m41t94_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) return PTR_ERR(rtc); dev_set_drvdata(&spi->dev, rtc); return 0; } static int __devexit m41t94_remove(struct spi_device *spi) { |
42fea15d6 spi/rtc-{ds1390,d... |
141 |
struct rtc_device *rtc = spi_get_drvdata(spi); |
8fc2c767b rtc: add support ... |
142 143 144 145 146 147 148 149 150 151 |
if (rtc) rtc_device_unregister(rtc); return 0; } static struct spi_driver m41t94_driver = { .driver = { .name = "rtc-m41t94", |
8fc2c767b rtc: add support ... |
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
.owner = THIS_MODULE, }, .probe = m41t94_probe, .remove = __devexit_p(m41t94_remove), }; static __init int m41t94_init(void) { return spi_register_driver(&m41t94_driver); } module_init(m41t94_init); static __exit void m41t94_exit(void) { spi_unregister_driver(&m41t94_driver); } module_exit(m41t94_exit); MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>"); MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); MODULE_LICENSE("GPL"); |
e0626e384 spi: prefix modal... |
175 |
MODULE_ALIAS("spi:rtc-m41t94"); |