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>
14 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
15 MODULE_DESCRIPTION("TI BQ4802 RTC driver");
16 MODULE_LICENSE("GPL");
21 struct rtc_device
*rtc
;
24 u8 (*read
)(struct bq4802
*, int);
25 void (*write
)(struct bq4802
*, int, u8
);
28 static u8
bq4802_read_io(struct bq4802
*p
, int off
)
30 return inb(p
->ioport
+ off
);
33 static void bq4802_write_io(struct bq4802
*p
, int off
, u8 val
)
35 outb(val
, p
->ioport
+ off
);
38 static u8
bq4802_read_mem(struct bq4802
*p
, int off
)
40 return readb(p
->regs
+ off
);
43 static void bq4802_write_mem(struct bq4802
*p
, int off
, u8 val
)
45 writeb(val
, p
->regs
+ off
);
48 static int bq4802_read_time(struct device
*dev
, struct rtc_time
*tm
)
50 struct platform_device
*pdev
= to_platform_device(dev
);
51 struct bq4802
*p
= platform_get_drvdata(pdev
);
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 platform_device
*pdev
= to_platform_device(dev
);
94 struct bq4802
*p
= platform_get_drvdata(pdev
);
95 u8 sec
, min
, hrs
, day
, mon
, yrs
, century
, val
;
99 year
= tm
->tm_year
+ 1900;
100 century
= year
/ 100;
103 mon
= tm
->tm_mon
+ 1; /* tm_mon starts at zero */
115 century
= bin2bcd(century
);
117 spin_lock_irqsave(&p
->lock
, flags
);
119 val
= p
->read(p
, 0x0e);
120 p
->write(p
, 0x0e, val
| 0x08);
122 p
->write(p
, 0x00, sec
);
123 p
->write(p
, 0x02, min
);
124 p
->write(p
, 0x04, hrs
);
125 p
->write(p
, 0x06, day
);
126 p
->write(p
, 0x09, mon
);
127 p
->write(p
, 0x0a, yrs
);
128 p
->write(p
, 0x0f, century
);
130 p
->write(p
, 0x0e, val
);
132 spin_unlock_irqrestore(&p
->lock
, flags
);
137 static const struct rtc_class_ops bq4802_ops
= {
138 .read_time
= bq4802_read_time
,
139 .set_time
= bq4802_set_time
,
142 static int __devinit
bq4802_probe(struct platform_device
*pdev
)
144 struct bq4802
*p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
150 spin_lock_init(&p
->lock
);
152 p
->r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
154 p
->r
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
159 if (p
->r
->flags
& IORESOURCE_IO
) {
160 p
->ioport
= p
->r
->start
;
161 p
->read
= bq4802_read_io
;
162 p
->write
= bq4802_write_io
;
163 } else if (p
->r
->flags
& IORESOURCE_MEM
) {
164 p
->regs
= ioremap(p
->r
->start
, resource_size(p
->r
));
165 p
->read
= bq4802_read_mem
;
166 p
->write
= bq4802_write_mem
;
172 p
->rtc
= rtc_device_register("bq4802", &pdev
->dev
,
173 &bq4802_ops
, THIS_MODULE
);
174 if (IS_ERR(p
->rtc
)) {
175 err
= PTR_ERR(p
->rtc
);
179 platform_set_drvdata(pdev
, p
);
185 if (p
->r
->flags
& IORESOURCE_MEM
)
192 static int __devexit
bq4802_remove(struct platform_device
*pdev
)
194 struct bq4802
*p
= platform_get_drvdata(pdev
);
196 rtc_device_unregister(p
->rtc
);
197 if (p
->r
->flags
& IORESOURCE_MEM
)
200 platform_set_drvdata(pdev
, NULL
);
207 /* work with hotplug and coldplug */
208 MODULE_ALIAS("platform:rtc-bq4802");
210 static struct platform_driver bq4802_driver
= {
212 .name
= "rtc-bq4802",
213 .owner
= THIS_MODULE
,
215 .probe
= bq4802_probe
,
216 .remove
= __devexit_p(bq4802_remove
),
219 static int __init
bq4802_init(void)
221 return platform_driver_register(&bq4802_driver
);
224 static void __exit
bq4802_exit(void)
226 platform_driver_unregister(&bq4802_driver
);
229 module_init(bq4802_init
);
230 module_exit(bq4802_exit
);