1 /* rtc-bq4802.c: TI BQ4802 RTC driver.
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/init.h>
10 #include <linux/platform_device.h>
11 #include <linux/rtc.h>
12 #include <linux/bcd.h>
13 #include <linux/slab.h>
15 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
16 MODULE_DESCRIPTION("TI BQ4802 RTC driver");
17 MODULE_LICENSE("GPL");
22 struct rtc_device
*rtc
;
25 u8 (*read
)(struct bq4802
*, int);
26 void (*write
)(struct bq4802
*, int, u8
);
29 static u8
bq4802_read_io(struct bq4802
*p
, int off
)
31 return inb(p
->ioport
+ off
);
34 static void bq4802_write_io(struct bq4802
*p
, int off
, u8 val
)
36 outb(val
, p
->ioport
+ off
);
39 static u8
bq4802_read_mem(struct bq4802
*p
, int off
)
41 return readb(p
->regs
+ off
);
44 static void bq4802_write_mem(struct bq4802
*p
, int off
, u8 val
)
46 writeb(val
, p
->regs
+ off
);
49 static int bq4802_read_time(struct device
*dev
, struct rtc_time
*tm
)
51 struct bq4802
*p
= dev_get_drvdata(dev
);
56 spin_lock_irqsave(&p
->lock
, flags
);
58 val
= p
->read(p
, 0x0e);
59 p
->write(p
, 0xe, val
| 0x08);
61 tm
->tm_sec
= p
->read(p
, 0x00);
62 tm
->tm_min
= p
->read(p
, 0x02);
63 tm
->tm_hour
= p
->read(p
, 0x04);
64 tm
->tm_mday
= p
->read(p
, 0x06);
65 tm
->tm_mon
= p
->read(p
, 0x09);
66 tm
->tm_year
= p
->read(p
, 0x0a);
67 tm
->tm_wday
= p
->read(p
, 0x08);
68 century
= p
->read(p
, 0x0f);
70 p
->write(p
, 0x0e, val
);
72 spin_unlock_irqrestore(&p
->lock
, flags
);
74 tm
->tm_sec
= bcd2bin(tm
->tm_sec
);
75 tm
->tm_min
= bcd2bin(tm
->tm_min
);
76 tm
->tm_hour
= bcd2bin(tm
->tm_hour
);
77 tm
->tm_mday
= bcd2bin(tm
->tm_mday
);
78 tm
->tm_mon
= bcd2bin(tm
->tm_mon
);
79 tm
->tm_year
= bcd2bin(tm
->tm_year
);
80 tm
->tm_wday
= bcd2bin(tm
->tm_wday
);
81 century
= bcd2bin(century
);
83 tm
->tm_year
+= (century
* 100);
91 static int bq4802_set_time(struct device
*dev
, struct rtc_time
*tm
)
93 struct bq4802
*p
= dev_get_drvdata(dev
);
94 u8 sec
, min
, hrs
, day
, mon
, yrs
, century
, val
;
98 year
= tm
->tm_year
+ 1900;
102 mon
= tm
->tm_mon
+ 1; /* tm_mon starts at zero */
114 century
= bin2bcd(century
);
116 spin_lock_irqsave(&p
->lock
, flags
);
118 val
= p
->read(p
, 0x0e);
119 p
->write(p
, 0x0e, val
| 0x08);
121 p
->write(p
, 0x00, sec
);
122 p
->write(p
, 0x02, min
);
123 p
->write(p
, 0x04, hrs
);
124 p
->write(p
, 0x06, day
);
125 p
->write(p
, 0x09, mon
);
126 p
->write(p
, 0x0a, yrs
);
127 p
->write(p
, 0x0f, century
);
129 p
->write(p
, 0x0e, val
);
131 spin_unlock_irqrestore(&p
->lock
, flags
);
136 static const struct rtc_class_ops bq4802_ops
= {
137 .read_time
= bq4802_read_time
,
138 .set_time
= bq4802_set_time
,
141 static int bq4802_probe(struct platform_device
*pdev
)
143 struct bq4802
*p
= devm_kzalloc(&pdev
->dev
, sizeof(*p
), GFP_KERNEL
);
149 spin_lock_init(&p
->lock
);
151 p
->r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
153 p
->r
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
158 if (p
->r
->flags
& IORESOURCE_IO
) {
159 p
->ioport
= p
->r
->start
;
160 p
->read
= bq4802_read_io
;
161 p
->write
= bq4802_write_io
;
162 } else if (p
->r
->flags
& IORESOURCE_MEM
) {
163 p
->regs
= devm_ioremap(&pdev
->dev
, p
->r
->start
,
164 resource_size(p
->r
));
169 p
->read
= bq4802_read_mem
;
170 p
->write
= bq4802_write_mem
;
176 platform_set_drvdata(pdev
, p
);
178 p
->rtc
= devm_rtc_device_register(&pdev
->dev
, "bq4802",
179 &bq4802_ops
, THIS_MODULE
);
180 if (IS_ERR(p
->rtc
)) {
181 err
= PTR_ERR(p
->rtc
);
191 /* work with hotplug and coldplug */
192 MODULE_ALIAS("platform:rtc-bq4802");
194 static struct platform_driver bq4802_driver
= {
196 .name
= "rtc-bq4802",
198 .probe
= bq4802_probe
,
201 module_platform_driver(bq4802_driver
);