1 /* rtc-bq4802.c: TI BQ4802 RTC driver. 2 * 3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net> 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/module.h> 8 #include <linux/init.h> 9 #include <linux/io.h> 10 #include <linux/platform_device.h> 11 #include <linux/rtc.h> 12 #include <linux/bcd.h> 13 #include <linux/slab.h> 14 15 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); 16 MODULE_DESCRIPTION("TI BQ4802 RTC driver"); 17 MODULE_LICENSE("GPL"); 18 19 struct bq4802 { 20 void __iomem *regs; 21 unsigned long ioport; 22 struct rtc_device *rtc; 23 spinlock_t lock; 24 struct resource *r; 25 u8 (*read)(struct bq4802 *, int); 26 void (*write)(struct bq4802 *, int, u8); 27 }; 28 29 static u8 bq4802_read_io(struct bq4802 *p, int off) 30 { 31 return inb(p->ioport + off); 32 } 33 34 static void bq4802_write_io(struct bq4802 *p, int off, u8 val) 35 { 36 outb(val, p->ioport + off); 37 } 38 39 static u8 bq4802_read_mem(struct bq4802 *p, int off) 40 { 41 return readb(p->regs + off); 42 } 43 44 static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) 45 { 46 writeb(val, p->regs + off); 47 } 48 49 static int bq4802_read_time(struct device *dev, struct rtc_time *tm) 50 { 51 struct bq4802 *p = dev_get_drvdata(dev); 52 unsigned long flags; 53 unsigned int century; 54 u8 val; 55 56 spin_lock_irqsave(&p->lock, flags); 57 58 val = p->read(p, 0x0e); 59 p->write(p, 0xe, val | 0x08); 60 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); 69 70 p->write(p, 0x0e, val); 71 72 spin_unlock_irqrestore(&p->lock, flags); 73 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); 82 83 tm->tm_year += (century * 100); 84 tm->tm_year -= 1900; 85 86 tm->tm_mon--; 87 88 return 0; 89 } 90 91 static int bq4802_set_time(struct device *dev, struct rtc_time *tm) 92 { 93 struct bq4802 *p = dev_get_drvdata(dev); 94 u8 sec, min, hrs, day, mon, yrs, century, val; 95 unsigned long flags; 96 unsigned int year; 97 98 year = tm->tm_year + 1900; 99 century = year / 100; 100 yrs = year % 100; 101 102 mon = tm->tm_mon + 1; /* tm_mon starts at zero */ 103 day = tm->tm_mday; 104 hrs = tm->tm_hour; 105 min = tm->tm_min; 106 sec = tm->tm_sec; 107 108 sec = bin2bcd(sec); 109 min = bin2bcd(min); 110 hrs = bin2bcd(hrs); 111 day = bin2bcd(day); 112 mon = bin2bcd(mon); 113 yrs = bin2bcd(yrs); 114 century = bin2bcd(century); 115 116 spin_lock_irqsave(&p->lock, flags); 117 118 val = p->read(p, 0x0e); 119 p->write(p, 0x0e, val | 0x08); 120 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); 128 129 p->write(p, 0x0e, val); 130 131 spin_unlock_irqrestore(&p->lock, flags); 132 133 return 0; 134 } 135 136 static const struct rtc_class_ops bq4802_ops = { 137 .read_time = bq4802_read_time, 138 .set_time = bq4802_set_time, 139 }; 140 141 static int bq4802_probe(struct platform_device *pdev) 142 { 143 struct bq4802 *p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); 144 int err = -ENOMEM; 145 146 if (!p) 147 goto out; 148 149 spin_lock_init(&p->lock); 150 151 p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 152 if (!p->r) { 153 p->r = platform_get_resource(pdev, IORESOURCE_IO, 0); 154 err = -EINVAL; 155 if (!p->r) 156 goto out; 157 } 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)); 165 p->read = bq4802_read_mem; 166 p->write = bq4802_write_mem; 167 } else { 168 err = -EINVAL; 169 goto out; 170 } 171 172 platform_set_drvdata(pdev, p); 173 174 p->rtc = devm_rtc_device_register(&pdev->dev, "bq4802", 175 &bq4802_ops, THIS_MODULE); 176 if (IS_ERR(p->rtc)) { 177 err = PTR_ERR(p->rtc); 178 goto out; 179 } 180 181 err = 0; 182 out: 183 return err; 184 185 } 186 187 /* work with hotplug and coldplug */ 188 MODULE_ALIAS("platform:rtc-bq4802"); 189 190 static struct platform_driver bq4802_driver = { 191 .driver = { 192 .name = "rtc-bq4802", 193 }, 194 .probe = bq4802_probe, 195 }; 196 197 module_platform_driver(bq4802_driver); 198