1 // SPDX-License-Identifier: GPL-2.0-only
2 /* rtc-bq4802.c: TI BQ4802 RTC driver.
4 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/init.h>
11 #include <linux/platform_device.h>
12 #include <linux/rtc.h>
13 #include <linux/bcd.h>
14 #include <linux/slab.h>
16 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
17 MODULE_DESCRIPTION("TI BQ4802 RTC driver");
18 MODULE_LICENSE("GPL");
23 struct rtc_device
*rtc
;
26 u8 (*read
)(struct bq4802
*, int);
27 void (*write
)(struct bq4802
*, int, u8
);
30 static u8
bq4802_read_io(struct bq4802
*p
, int off
)
32 return inb(p
->ioport
+ off
);
35 static void bq4802_write_io(struct bq4802
*p
, int off
, u8 val
)
37 outb(val
, p
->ioport
+ off
);
40 static u8
bq4802_read_mem(struct bq4802
*p
, int off
)
42 return readb(p
->regs
+ off
);
45 static void bq4802_write_mem(struct bq4802
*p
, int off
, u8 val
)
47 writeb(val
, p
->regs
+ off
);
50 static int bq4802_read_time(struct device
*dev
, struct rtc_time
*tm
)
52 struct bq4802
*p
= dev_get_drvdata(dev
);
57 spin_lock_irqsave(&p
->lock
, flags
);
59 val
= p
->read(p
, 0x0e);
60 p
->write(p
, 0xe, val
| 0x08);
62 tm
->tm_sec
= p
->read(p
, 0x00);
63 tm
->tm_min
= p
->read(p
, 0x02);
64 tm
->tm_hour
= p
->read(p
, 0x04);
65 tm
->tm_mday
= p
->read(p
, 0x06);
66 tm
->tm_mon
= p
->read(p
, 0x09);
67 tm
->tm_year
= p
->read(p
, 0x0a);
68 tm
->tm_wday
= p
->read(p
, 0x08);
69 century
= p
->read(p
, 0x0f);
71 p
->write(p
, 0x0e, val
);
73 spin_unlock_irqrestore(&p
->lock
, flags
);
75 tm
->tm_sec
= bcd2bin(tm
->tm_sec
);
76 tm
->tm_min
= bcd2bin(tm
->tm_min
);
77 tm
->tm_hour
= bcd2bin(tm
->tm_hour
);
78 tm
->tm_mday
= bcd2bin(tm
->tm_mday
);
79 tm
->tm_mon
= bcd2bin(tm
->tm_mon
);
80 tm
->tm_year
= bcd2bin(tm
->tm_year
);
81 tm
->tm_wday
= bcd2bin(tm
->tm_wday
);
82 century
= bcd2bin(century
);
84 tm
->tm_year
+= (century
* 100);
92 static int bq4802_set_time(struct device
*dev
, struct rtc_time
*tm
)
94 struct bq4802
*p
= dev_get_drvdata(dev
);
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 bq4802_probe(struct platform_device
*pdev
)
144 struct bq4802
*p
= devm_kzalloc(&pdev
->dev
, 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
= devm_ioremap(&pdev
->dev
, p
->r
->start
,
165 resource_size(p
->r
));
170 p
->read
= bq4802_read_mem
;
171 p
->write
= bq4802_write_mem
;
177 platform_set_drvdata(pdev
, p
);
179 p
->rtc
= devm_rtc_device_register(&pdev
->dev
, "bq4802",
180 &bq4802_ops
, THIS_MODULE
);
181 if (IS_ERR(p
->rtc
)) {
182 err
= PTR_ERR(p
->rtc
);
192 /* work with hotplug and coldplug */
193 MODULE_ALIAS("platform:rtc-bq4802");
195 static struct platform_driver bq4802_driver
= {
197 .name
= "rtc-bq4802",
199 .probe
= bq4802_probe
,
202 module_platform_driver(bq4802_driver
);