Blame view
drivers/rtc/rtc-m48t59.c
13.8 KB
2e774c7ca
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * ST M48T59 RTC driver * * Copyright (c) 2007 Wind River Systems, Inc. * * Author: Mark Zhan <rongkai.zhan@windriver.com> * * 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/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/io.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/rtc.h> #include <linux/rtc/m48t59.h> #include <linux/bcd.h> |
5a0e3ad6a
|
22 |
#include <linux/slab.h> |
2e774c7ca
|
23 24 25 26 |
#ifndef NO_IRQ #define NO_IRQ (-1) #endif |
94fe7424a
|
27 28 29 |
#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg)) #define M48T59_WRITE(val, reg) \ (pdata->write_byte(dev, pdata->offset + reg, val)) |
2e774c7ca
|
30 31 32 33 34 35 36 37 |
#define M48T59_SET_BITS(mask, reg) \ M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) #define M48T59_CLEAR_BITS(mask, reg) \ M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg)) struct m48t59_private { void __iomem *ioaddr; |
0439208a8
|
38 |
int irq; |
2e774c7ca
|
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
struct rtc_device *rtc; spinlock_t lock; /* serialize the NVRAM and RTC access */ }; /* * This is the generic access method when the chip is memory-mapped */ static void m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val) { struct platform_device *pdev = to_platform_device(dev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev); writeb(val, m48t59->ioaddr+ofs); } static u8 m48t59_mem_readb(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); struct m48t59_private *m48t59 = platform_get_drvdata(pdev); return readb(m48t59->ioaddr+ofs); } /* * NOTE: M48T59 only uses BCD mode */ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
70 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
71 72 73 74 75 76 77 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; u8 val; spin_lock_irqsave(&m48t59->lock, flags); /* Issue the READ command */ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
fe20ba70a
|
78 |
tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); |
2e774c7ca
|
79 |
/* tm_mon is 0-11 */ |
fe20ba70a
|
80 81 |
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY)); |
2e774c7ca
|
82 83 |
val = M48T59_READ(M48T59_WDAY); |
833be4e1f
|
84 85 |
if ((pdata->type == M48T59RTC_TYPE_M48T59) && (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { |
2e774c7ca
|
86 87 88 89 |
dev_dbg(dev, "Century bit is enabled "); tm->tm_year += 100; /* one century */ } |
12a9ee3cc
|
90 91 92 93 |
#ifdef CONFIG_SPARC /* Sun SPARC machines count years since 1968 */ tm->tm_year += 68; #endif |
2e774c7ca
|
94 |
|
fe20ba70a
|
95 96 97 98 |
tm->tm_wday = bcd2bin(val & 0x07); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); tm->tm_min = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F); tm->tm_sec = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F); |
2e774c7ca
|
99 100 101 102 103 104 105 106 107 |
/* Clear the READ bit */ M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
caf1e1068
|
108 |
return rtc_valid_tm(tm); |
2e774c7ca
|
109 110 111 112 113 |
} static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
114 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
115 116 117 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; u8 val = 0; |
12a9ee3cc
|
118 119 120 121 122 123 |
int year = tm->tm_year; #ifdef CONFIG_SPARC /* Sun SPARC machines count years since 1968 */ year -= 68; #endif |
2e774c7ca
|
124 125 126 |
dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d ", |
12a9ee3cc
|
127 |
year + 1900, tm->tm_mon, tm->tm_mday, |
2e774c7ca
|
128 |
tm->tm_hour, tm->tm_min, tm->tm_sec); |
12a9ee3cc
|
129 130 |
if (year < 0) return -EINVAL; |
2e774c7ca
|
131 132 133 |
spin_lock_irqsave(&m48t59->lock, flags); /* Issue the WRITE command */ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); |
fe20ba70a
|
134 135 136 137 |
M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC); M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN); M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR); M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY); |
2e774c7ca
|
138 |
/* tm_mon is 0-11 */ |
fe20ba70a
|
139 |
M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); |
12a9ee3cc
|
140 |
M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR); |
2e774c7ca
|
141 |
|
12a9ee3cc
|
142 |
if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100)) |
2e774c7ca
|
143 |
val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); |
fe20ba70a
|
144 |
val |= (bin2bcd(tm->tm_wday) & 0x07); |
2e774c7ca
|
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
M48T59_WRITE(val, M48T59_WDAY); /* Clear the WRITE bit */ M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); return 0; } /* * Read alarm time and date in RTC */ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
159 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
160 161 162 163 164 165 166 167 168 169 170 171 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); struct rtc_time *tm = &alrm->time; unsigned long flags; u8 val; /* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) return -EIO; spin_lock_irqsave(&m48t59->lock, flags); /* Issue the READ command */ M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); |
fe20ba70a
|
172 |
tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); |
12a9ee3cc
|
173 174 175 176 |
#ifdef CONFIG_SPARC /* Sun SPARC machines count years since 1968 */ tm->tm_year += 68; #endif |
2e774c7ca
|
177 |
/* tm_mon is 0-11 */ |
fe20ba70a
|
178 |
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; |
2e774c7ca
|
179 180 181 182 |
val = M48T59_READ(M48T59_WDAY); if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) tm->tm_year += 100; /* one century */ |
fe20ba70a
|
183 184 185 186 |
tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE)); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR)); tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN)); tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC)); |
2e774c7ca
|
187 188 189 190 191 192 193 194 195 |
/* Clear the READ bit */ M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); |
caf1e1068
|
196 |
return rtc_valid_tm(tm); |
2e774c7ca
|
197 198 199 200 201 202 203 204 |
} /* * Set alarm time and date in RTC */ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
205 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
206 207 208 209 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); struct rtc_time *tm = &alrm->time; u8 mday, hour, min, sec; unsigned long flags; |
12a9ee3cc
|
210 211 212 213 214 215 |
int year = tm->tm_year; #ifdef CONFIG_SPARC /* Sun SPARC machines count years since 1968 */ year -= 68; #endif |
2e774c7ca
|
216 217 218 219 |
/* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) return -EIO; |
12a9ee3cc
|
220 221 |
if (year < 0) return -EINVAL; |
2e774c7ca
|
222 223 224 225 |
/* * 0xff means "always match" */ mday = tm->tm_mday; |
fe20ba70a
|
226 |
mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; |
2e774c7ca
|
227 228 229 230 |
if (mday == 0xff) mday = M48T59_READ(M48T59_MDAY); hour = tm->tm_hour; |
fe20ba70a
|
231 |
hour = (hour < 24) ? bin2bcd(hour) : 0x00; |
2e774c7ca
|
232 233 |
min = tm->tm_min; |
fe20ba70a
|
234 |
min = (min < 60) ? bin2bcd(min) : 0x00; |
2e774c7ca
|
235 236 |
sec = tm->tm_sec; |
fe20ba70a
|
237 |
sec = (sec < 60) ? bin2bcd(sec) : 0x00; |
2e774c7ca
|
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
spin_lock_irqsave(&m48t59->lock, flags); /* Issue the WRITE command */ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); M48T59_WRITE(mday, M48T59_ALARM_DATE); M48T59_WRITE(hour, M48T59_ALARM_HOUR); M48T59_WRITE(min, M48T59_ALARM_MIN); M48T59_WRITE(sec, M48T59_ALARM_SEC); /* Clear the WRITE bit */ M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d ", |
12a9ee3cc
|
254 |
year + 1900, tm->tm_mon, tm->tm_mday, |
2e774c7ca
|
255 256 257 258 259 260 261 |
tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } /* * Handle commands from user-space */ |
16380c153
|
262 |
static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
2e774c7ca
|
263 264 |
{ struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
265 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
266 267 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; |
2e774c7ca
|
268 269 |
spin_lock_irqsave(&m48t59->lock, flags); |
16380c153
|
270 |
if (enabled) |
2e774c7ca
|
271 |
M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); |
16380c153
|
272 273 |
else M48T59_WRITE(0x00, M48T59_INTR); |
2e774c7ca
|
274 |
spin_unlock_irqrestore(&m48t59->lock, flags); |
16380c153
|
275 |
return 0; |
2e774c7ca
|
276 277 278 279 280 |
} static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) { struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
281 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; u8 val; spin_lock_irqsave(&m48t59->lock, flags); val = M48T59_READ(M48T59_FLAGS); spin_unlock_irqrestore(&m48t59->lock, flags); seq_printf(seq, "battery\t\t: %s ", (val & M48T59_FLAGS_BF) ? "low" : "normal"); return 0; } /* * IRQ handler for the RTC */ static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id) { struct device *dev = (struct device *)dev_id; struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
303 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); u8 event; spin_lock(&m48t59->lock); event = M48T59_READ(M48T59_FLAGS); spin_unlock(&m48t59->lock); if (event & M48T59_FLAGS_AF) { rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF)); return IRQ_HANDLED; } return IRQ_NONE; } static const struct rtc_class_ops m48t59_rtc_ops = { |
2e774c7ca
|
320 321 322 323 324 |
.read_time = m48t59_rtc_read_time, .set_time = m48t59_rtc_set_time, .read_alarm = m48t59_rtc_readalarm, .set_alarm = m48t59_rtc_setalarm, .proc = m48t59_rtc_proc, |
16380c153
|
325 |
.alarm_irq_enable = m48t59_rtc_alarm_irq_enable, |
2e774c7ca
|
326 |
}; |
94fe7424a
|
327 328 329 330 |
static const struct rtc_class_ops m48t02_rtc_ops = { .read_time = m48t59_rtc_read_time, .set_time = m48t59_rtc_set_time, }; |
2c3c8bea6
|
331 |
static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, |
2e774c7ca
|
332 333 334 335 336 |
struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
337 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
338 339 340 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); ssize_t cnt = 0; unsigned long flags; |
99be3e371
|
341 342 343 |
spin_lock_irqsave(&m48t59->lock, flags); for (; cnt < size; cnt++) |
2e774c7ca
|
344 |
*buf++ = M48T59_READ(cnt); |
99be3e371
|
345 346 |
spin_unlock_irqrestore(&m48t59->lock, flags); |
2e774c7ca
|
347 348 349 |
return cnt; } |
2c3c8bea6
|
350 |
static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, |
2e774c7ca
|
351 352 353 354 355 |
struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = to_platform_device(dev); |
8136032ba
|
356 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
357 358 359 |
struct m48t59_private *m48t59 = platform_get_drvdata(pdev); ssize_t cnt = 0; unsigned long flags; |
99be3e371
|
360 361 362 |
spin_lock_irqsave(&m48t59->lock, flags); for (; cnt < size; cnt++) |
2e774c7ca
|
363 |
M48T59_WRITE(*buf++, cnt); |
99be3e371
|
364 365 |
spin_unlock_irqrestore(&m48t59->lock, flags); |
2e774c7ca
|
366 367 368 369 370 371 372 |
return cnt; } static struct bin_attribute m48t59_nvram_attr = { .attr = { .name = "nvram", |
a4b1d50e6
|
373 |
.mode = S_IRUGO | S_IWUSR, |
2e774c7ca
|
374 375 376 377 |
}, .read = m48t59_nvram_read, .write = m48t59_nvram_write, }; |
5a167f454
|
378 |
static int m48t59_rtc_probe(struct platform_device *pdev) |
2e774c7ca
|
379 |
{ |
8136032ba
|
380 |
struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev); |
2e774c7ca
|
381 382 383 |
struct m48t59_private *m48t59 = NULL; struct resource *res; int ret = -ENOMEM; |
94fe7424a
|
384 385 |
char *name; const struct rtc_class_ops *ops; |
2e774c7ca
|
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 |
/* This chip could be memory-mapped or I/O-mapped */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!res) return -EINVAL; } if (res->flags & IORESOURCE_IO) { /* If we are I/O-mapped, the platform should provide * the operations accessing chip registers. */ if (!pdata || !pdata->write_byte || !pdata->read_byte) return -EINVAL; } else if (res->flags & IORESOURCE_MEM) { /* we are memory-mapped */ if (!pdata) { |
19b8d8875
|
404 405 |
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
2e774c7ca
|
406 407 408 409 410 |
if (!pdata) return -ENOMEM; /* Ensure we only kmalloc platform data once */ pdev->dev.platform_data = pdata; } |
94fe7424a
|
411 412 |
if (!pdata->type) pdata->type = M48T59RTC_TYPE_M48T59; |
2e774c7ca
|
413 414 415 416 417 418 419 |
/* Try to use the generic memory read/write ops */ if (!pdata->write_byte) pdata->write_byte = m48t59_mem_writeb; if (!pdata->read_byte) pdata->read_byte = m48t59_mem_readb; } |
19b8d8875
|
420 |
m48t59 = devm_kzalloc(&pdev->dev, sizeof(*m48t59), GFP_KERNEL); |
2e774c7ca
|
421 422 |
if (!m48t59) return -ENOMEM; |
64151ad5b
|
423 424 425 426 |
m48t59->ioaddr = pdata->ioaddr; if (!m48t59->ioaddr) { /* ioaddr not mapped externally */ |
19b8d8875
|
427 428 |
m48t59->ioaddr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
64151ad5b
|
429 |
if (!m48t59->ioaddr) |
19b8d8875
|
430 |
return ret; |
64151ad5b
|
431 |
} |
2e774c7ca
|
432 433 434 435 436 |
/* Try to get irq number. We also can work in * the mode without IRQ. */ m48t59->irq = platform_get_irq(pdev, 0); |
2fac6674d
|
437 |
if (m48t59->irq <= 0) |
2e774c7ca
|
438 439 440 |
m48t59->irq = NO_IRQ; if (m48t59->irq != NO_IRQ) { |
19b8d8875
|
441 442 443 |
ret = devm_request_irq(&pdev->dev, m48t59->irq, m48t59_rtc_interrupt, IRQF_SHARED, "rtc-m48t59", &pdev->dev); |
2e774c7ca
|
444 |
if (ret) |
19b8d8875
|
445 |
return ret; |
2e774c7ca
|
446 |
} |
94fe7424a
|
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
switch (pdata->type) { case M48T59RTC_TYPE_M48T59: name = "m48t59"; ops = &m48t59_rtc_ops; pdata->offset = 0x1ff0; break; case M48T59RTC_TYPE_M48T02: name = "m48t02"; ops = &m48t02_rtc_ops; pdata->offset = 0x7f0; break; case M48T59RTC_TYPE_M48T08: name = "m48t08"; ops = &m48t02_rtc_ops; pdata->offset = 0x1ff0; break; default: dev_err(&pdev->dev, "Unknown RTC type "); |
19b8d8875
|
466 |
return -ENODEV; |
94fe7424a
|
467 |
} |
2e774c7ca
|
468 |
|
b74d2caa6
|
469 470 |
spin_lock_init(&m48t59->lock); platform_set_drvdata(pdev, m48t59); |
19b8d8875
|
471 472 473 474 |
m48t59->rtc = devm_rtc_device_register(&pdev->dev, name, ops, THIS_MODULE); if (IS_ERR(m48t59->rtc)) return PTR_ERR(m48t59->rtc); |
2e774c7ca
|
475 |
|
94fe7424a
|
476 |
m48t59_nvram_attr.size = pdata->offset; |
2e774c7ca
|
477 |
ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
19b8d8875
|
478 479 |
if (ret) return ret; |
2e774c7ca
|
480 |
|
2e774c7ca
|
481 |
return 0; |
2e774c7ca
|
482 |
} |
5a167f454
|
483 |
static int m48t59_rtc_remove(struct platform_device *pdev) |
2e774c7ca
|
484 |
{ |
2e774c7ca
|
485 |
sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
2e774c7ca
|
486 487 |
return 0; } |
ad28a07bc
|
488 489 |
/* work with hotplug and coldplug */ MODULE_ALIAS("platform:rtc-m48t59"); |
127309265
|
490 |
static struct platform_driver m48t59_rtc_driver = { |
2e774c7ca
|
491 492 |
.driver = { .name = "rtc-m48t59", |
2e774c7ca
|
493 494 |
}, .probe = m48t59_rtc_probe, |
5a167f454
|
495 |
.remove = m48t59_rtc_remove, |
2e774c7ca
|
496 |
}; |
0c4eae665
|
497 |
module_platform_driver(m48t59_rtc_driver); |
2e774c7ca
|
498 499 |
MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
94fe7424a
|
500 |
MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
2e774c7ca
|
501 |
MODULE_LICENSE("GPL"); |