1453b4c6dSJonas Jensen /* 2453b4c6dSJonas Jensen * MOXA ART RTC driver. 3453b4c6dSJonas Jensen * 4453b4c6dSJonas Jensen * Copyright (C) 2013 Jonas Jensen 5453b4c6dSJonas Jensen * 6453b4c6dSJonas Jensen * Jonas Jensen <jonas.jensen@gmail.com> 7453b4c6dSJonas Jensen * 8453b4c6dSJonas Jensen * Based on code from 9453b4c6dSJonas Jensen * Moxa Technology Co., Ltd. <www.moxa.com> 10453b4c6dSJonas Jensen * 11453b4c6dSJonas Jensen * This file is licensed under the terms of the GNU General Public 12453b4c6dSJonas Jensen * License version 2. This program is licensed "as is" without any 13453b4c6dSJonas Jensen * warranty of any kind, whether express or implied. 14453b4c6dSJonas Jensen */ 15453b4c6dSJonas Jensen 16453b4c6dSJonas Jensen #include <linux/init.h> 17453b4c6dSJonas Jensen #include <linux/kernel.h> 18453b4c6dSJonas Jensen #include <linux/delay.h> 19453b4c6dSJonas Jensen #include <linux/rtc.h> 20453b4c6dSJonas Jensen #include <linux/platform_device.h> 21453b4c6dSJonas Jensen #include <linux/module.h> 22453b4c6dSJonas Jensen #include <linux/gpio.h> 23453b4c6dSJonas Jensen #include <linux/of_gpio.h> 24453b4c6dSJonas Jensen 25453b4c6dSJonas Jensen #define GPIO_RTC_RESERVED 0x0C 26453b4c6dSJonas Jensen #define GPIO_RTC_DATA_SET 0x10 27453b4c6dSJonas Jensen #define GPIO_RTC_DATA_CLEAR 0x14 28453b4c6dSJonas Jensen #define GPIO_RTC_PIN_PULL_ENABLE 0x18 29453b4c6dSJonas Jensen #define GPIO_RTC_PIN_PULL_TYPE 0x1C 30453b4c6dSJonas Jensen #define GPIO_RTC_INT_ENABLE 0x20 31453b4c6dSJonas Jensen #define GPIO_RTC_INT_RAW_STATE 0x24 32453b4c6dSJonas Jensen #define GPIO_RTC_INT_MASKED_STATE 0x28 33453b4c6dSJonas Jensen #define GPIO_RTC_INT_MASK 0x2C 34453b4c6dSJonas Jensen #define GPIO_RTC_INT_CLEAR 0x30 35453b4c6dSJonas Jensen #define GPIO_RTC_INT_TRIGGER 0x34 36453b4c6dSJonas Jensen #define GPIO_RTC_INT_BOTH 0x38 37453b4c6dSJonas Jensen #define GPIO_RTC_INT_RISE_NEG 0x3C 38453b4c6dSJonas Jensen #define GPIO_RTC_BOUNCE_ENABLE 0x40 39453b4c6dSJonas Jensen #define GPIO_RTC_BOUNCE_PRE_SCALE 0x44 40453b4c6dSJonas Jensen #define GPIO_RTC_PROTECT_W 0x8E 41453b4c6dSJonas Jensen #define GPIO_RTC_PROTECT_R 0x8F 42453b4c6dSJonas Jensen #define GPIO_RTC_YEAR_W 0x8C 43453b4c6dSJonas Jensen #define GPIO_RTC_YEAR_R 0x8D 44453b4c6dSJonas Jensen #define GPIO_RTC_DAY_W 0x8A 45453b4c6dSJonas Jensen #define GPIO_RTC_DAY_R 0x8B 46453b4c6dSJonas Jensen #define GPIO_RTC_MONTH_W 0x88 47453b4c6dSJonas Jensen #define GPIO_RTC_MONTH_R 0x89 48453b4c6dSJonas Jensen #define GPIO_RTC_DATE_W 0x86 49453b4c6dSJonas Jensen #define GPIO_RTC_DATE_R 0x87 50453b4c6dSJonas Jensen #define GPIO_RTC_HOURS_W 0x84 51453b4c6dSJonas Jensen #define GPIO_RTC_HOURS_R 0x85 52453b4c6dSJonas Jensen #define GPIO_RTC_MINUTES_W 0x82 53453b4c6dSJonas Jensen #define GPIO_RTC_MINUTES_R 0x83 54453b4c6dSJonas Jensen #define GPIO_RTC_SECONDS_W 0x80 55453b4c6dSJonas Jensen #define GPIO_RTC_SECONDS_R 0x81 56453b4c6dSJonas Jensen #define GPIO_RTC_DELAY_TIME 8 57453b4c6dSJonas Jensen 58453b4c6dSJonas Jensen struct moxart_rtc { 59453b4c6dSJonas Jensen struct rtc_device *rtc; 60453b4c6dSJonas Jensen spinlock_t rtc_lock; 61453b4c6dSJonas Jensen int gpio_data, gpio_sclk, gpio_reset; 62453b4c6dSJonas Jensen }; 63453b4c6dSJonas Jensen 64453b4c6dSJonas Jensen static int day_of_year[12] = { 0, 31, 59, 90, 120, 151, 181, 65453b4c6dSJonas Jensen 212, 243, 273, 304, 334 }; 66453b4c6dSJonas Jensen 67453b4c6dSJonas Jensen static void moxart_rtc_write_byte(struct device *dev, u8 data) 68453b4c6dSJonas Jensen { 69453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 70453b4c6dSJonas Jensen int i; 71453b4c6dSJonas Jensen 72453b4c6dSJonas Jensen for (i = 0; i < 8; i++, data >>= 1) { 73453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 0); 74453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1)); 75453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 76453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 1); 77453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 78453b4c6dSJonas Jensen } 79453b4c6dSJonas Jensen } 80453b4c6dSJonas Jensen 81453b4c6dSJonas Jensen static u8 moxart_rtc_read_byte(struct device *dev) 82453b4c6dSJonas Jensen { 83453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 84453b4c6dSJonas Jensen int i; 85453b4c6dSJonas Jensen u8 data = 0; 86453b4c6dSJonas Jensen 87453b4c6dSJonas Jensen for (i = 0; i < 8; i++) { 88453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 0); 89453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 90453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 1); 91453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 92453b4c6dSJonas Jensen if (gpio_get_value(moxart_rtc->gpio_data)) 93453b4c6dSJonas Jensen data |= (1 << i); 94453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 95453b4c6dSJonas Jensen } 96453b4c6dSJonas Jensen return data; 97453b4c6dSJonas Jensen } 98453b4c6dSJonas Jensen 99453b4c6dSJonas Jensen static u8 moxart_rtc_read_register(struct device *dev, u8 cmd) 100453b4c6dSJonas Jensen { 101453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 102453b4c6dSJonas Jensen u8 data; 103453b4c6dSJonas Jensen unsigned long flags; 104453b4c6dSJonas Jensen 105453b4c6dSJonas Jensen local_irq_save(flags); 106453b4c6dSJonas Jensen 107453b4c6dSJonas Jensen gpio_direction_output(moxart_rtc->gpio_data, 0); 108453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_reset, 1); 109453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 110453b4c6dSJonas Jensen moxart_rtc_write_byte(dev, cmd); 111453b4c6dSJonas Jensen gpio_direction_input(moxart_rtc->gpio_data); 112453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 113453b4c6dSJonas Jensen data = moxart_rtc_read_byte(dev); 114453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 0); 115453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_reset, 0); 116453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 117453b4c6dSJonas Jensen 118453b4c6dSJonas Jensen local_irq_restore(flags); 119453b4c6dSJonas Jensen 120453b4c6dSJonas Jensen return data; 121453b4c6dSJonas Jensen } 122453b4c6dSJonas Jensen 123453b4c6dSJonas Jensen static void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data) 124453b4c6dSJonas Jensen { 125453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 126453b4c6dSJonas Jensen unsigned long flags; 127453b4c6dSJonas Jensen 128453b4c6dSJonas Jensen local_irq_save(flags); 129453b4c6dSJonas Jensen 130453b4c6dSJonas Jensen gpio_direction_output(moxart_rtc->gpio_data, 0); 131453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_reset, 1); 132453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 133453b4c6dSJonas Jensen moxart_rtc_write_byte(dev, cmd); 134453b4c6dSJonas Jensen moxart_rtc_write_byte(dev, data); 135453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_sclk, 0); 136453b4c6dSJonas Jensen gpio_set_value(moxart_rtc->gpio_reset, 0); 137453b4c6dSJonas Jensen udelay(GPIO_RTC_DELAY_TIME); 138453b4c6dSJonas Jensen 139453b4c6dSJonas Jensen local_irq_restore(flags); 140453b4c6dSJonas Jensen } 141453b4c6dSJonas Jensen 142453b4c6dSJonas Jensen static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm) 143453b4c6dSJonas Jensen { 144453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 145453b4c6dSJonas Jensen 146453b4c6dSJonas Jensen spin_lock_irq(&moxart_rtc->rtc_lock); 147453b4c6dSJonas Jensen 148453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0); 149453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W, 150453b4c6dSJonas Jensen (((tm->tm_year - 100) / 10) << 4) | 151453b4c6dSJonas Jensen ((tm->tm_year - 100) % 10)); 152453b4c6dSJonas Jensen 153453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W, 154453b4c6dSJonas Jensen (((tm->tm_mon + 1) / 10) << 4) | 155453b4c6dSJonas Jensen ((tm->tm_mon + 1) % 10)); 156453b4c6dSJonas Jensen 157453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_DATE_W, 158453b4c6dSJonas Jensen ((tm->tm_mday / 10) << 4) | 159453b4c6dSJonas Jensen (tm->tm_mday % 10)); 160453b4c6dSJonas Jensen 161453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W, 162453b4c6dSJonas Jensen ((tm->tm_hour / 10) << 4) | 163453b4c6dSJonas Jensen (tm->tm_hour % 10)); 164453b4c6dSJonas Jensen 165453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W, 166453b4c6dSJonas Jensen ((tm->tm_min / 10) << 4) | 167453b4c6dSJonas Jensen (tm->tm_min % 10)); 168453b4c6dSJonas Jensen 169453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W, 170453b4c6dSJonas Jensen ((tm->tm_sec / 10) << 4) | 171453b4c6dSJonas Jensen (tm->tm_sec % 10)); 172453b4c6dSJonas Jensen 173453b4c6dSJonas Jensen moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80); 174453b4c6dSJonas Jensen 175453b4c6dSJonas Jensen spin_unlock_irq(&moxart_rtc->rtc_lock); 176453b4c6dSJonas Jensen 177453b4c6dSJonas Jensen dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n" 178453b4c6dSJonas Jensen "tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n", 179453b4c6dSJonas Jensen __func__, tm->tm_year, tm->tm_mon, tm->tm_mday, 180453b4c6dSJonas Jensen tm->tm_hour, tm->tm_min, tm->tm_sec); 181453b4c6dSJonas Jensen 182453b4c6dSJonas Jensen return 0; 183453b4c6dSJonas Jensen } 184453b4c6dSJonas Jensen 185453b4c6dSJonas Jensen static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm) 186453b4c6dSJonas Jensen { 187453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev); 188453b4c6dSJonas Jensen unsigned char v; 189453b4c6dSJonas Jensen 190453b4c6dSJonas Jensen spin_lock_irq(&moxart_rtc->rtc_lock); 191453b4c6dSJonas Jensen 192453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R); 193453b4c6dSJonas Jensen tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F); 194453b4c6dSJonas Jensen 195453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R); 196453b4c6dSJonas Jensen tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F); 197453b4c6dSJonas Jensen 198453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R); 199453b4c6dSJonas Jensen if (v & 0x80) { /* 12-hour mode */ 200453b4c6dSJonas Jensen tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F); 201453b4c6dSJonas Jensen if (v & 0x20) { /* PM mode */ 202453b4c6dSJonas Jensen tm->tm_hour += 12; 203453b4c6dSJonas Jensen if (tm->tm_hour >= 24) 204453b4c6dSJonas Jensen tm->tm_hour = 0; 205453b4c6dSJonas Jensen } 206453b4c6dSJonas Jensen } else { /* 24-hour mode */ 207453b4c6dSJonas Jensen tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F); 208453b4c6dSJonas Jensen } 209453b4c6dSJonas Jensen 210453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R); 211453b4c6dSJonas Jensen tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F); 212453b4c6dSJonas Jensen 213453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R); 214453b4c6dSJonas Jensen tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F); 215453b4c6dSJonas Jensen tm->tm_mon--; 216453b4c6dSJonas Jensen 217453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R); 218453b4c6dSJonas Jensen tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F); 219453b4c6dSJonas Jensen tm->tm_year += 100; 220453b4c6dSJonas Jensen if (tm->tm_year <= 69) 221453b4c6dSJonas Jensen tm->tm_year += 100; 222453b4c6dSJonas Jensen 223453b4c6dSJonas Jensen v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R); 224453b4c6dSJonas Jensen tm->tm_wday = (v & 0x0f) - 1; 225453b4c6dSJonas Jensen tm->tm_yday = day_of_year[tm->tm_mon]; 226453b4c6dSJonas Jensen tm->tm_yday += (tm->tm_mday - 1); 227453b4c6dSJonas Jensen if (tm->tm_mon >= 2) { 228453b4c6dSJonas Jensen if (!(tm->tm_year % 4) && (tm->tm_year % 100)) 229453b4c6dSJonas Jensen tm->tm_yday++; 230453b4c6dSJonas Jensen } 231453b4c6dSJonas Jensen 232453b4c6dSJonas Jensen tm->tm_isdst = 0; 233453b4c6dSJonas Jensen 234453b4c6dSJonas Jensen spin_unlock_irq(&moxart_rtc->rtc_lock); 235453b4c6dSJonas Jensen 236453b4c6dSJonas Jensen return 0; 237453b4c6dSJonas Jensen } 238453b4c6dSJonas Jensen 239453b4c6dSJonas Jensen static const struct rtc_class_ops moxart_rtc_ops = { 240453b4c6dSJonas Jensen .read_time = moxart_rtc_read_time, 241453b4c6dSJonas Jensen .set_time = moxart_rtc_set_time, 242453b4c6dSJonas Jensen }; 243453b4c6dSJonas Jensen 244453b4c6dSJonas Jensen static int moxart_rtc_probe(struct platform_device *pdev) 245453b4c6dSJonas Jensen { 246453b4c6dSJonas Jensen struct moxart_rtc *moxart_rtc; 247453b4c6dSJonas Jensen int ret = 0; 248453b4c6dSJonas Jensen 249453b4c6dSJonas Jensen moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL); 2504410af6eSJingoo Han if (!moxart_rtc) 251453b4c6dSJonas Jensen return -ENOMEM; 252453b4c6dSJonas Jensen 253453b4c6dSJonas Jensen moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node, 254453b4c6dSJonas Jensen "gpio-rtc-data", 0); 255453b4c6dSJonas Jensen if (!gpio_is_valid(moxart_rtc->gpio_data)) { 256453b4c6dSJonas Jensen dev_err(&pdev->dev, "invalid gpio (data): %d\n", 257453b4c6dSJonas Jensen moxart_rtc->gpio_data); 258453b4c6dSJonas Jensen return moxart_rtc->gpio_data; 259453b4c6dSJonas Jensen } 260453b4c6dSJonas Jensen 261453b4c6dSJonas Jensen moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node, 262453b4c6dSJonas Jensen "gpio-rtc-sclk", 0); 263453b4c6dSJonas Jensen if (!gpio_is_valid(moxart_rtc->gpio_sclk)) { 264453b4c6dSJonas Jensen dev_err(&pdev->dev, "invalid gpio (sclk): %d\n", 265453b4c6dSJonas Jensen moxart_rtc->gpio_sclk); 266453b4c6dSJonas Jensen return moxart_rtc->gpio_sclk; 267453b4c6dSJonas Jensen } 268453b4c6dSJonas Jensen 269453b4c6dSJonas Jensen moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node, 270453b4c6dSJonas Jensen "gpio-rtc-reset", 0); 271453b4c6dSJonas Jensen if (!gpio_is_valid(moxart_rtc->gpio_reset)) { 272453b4c6dSJonas Jensen dev_err(&pdev->dev, "invalid gpio (reset): %d\n", 273453b4c6dSJonas Jensen moxart_rtc->gpio_reset); 274453b4c6dSJonas Jensen return moxart_rtc->gpio_reset; 275453b4c6dSJonas Jensen } 276453b4c6dSJonas Jensen 277453b4c6dSJonas Jensen spin_lock_init(&moxart_rtc->rtc_lock); 278453b4c6dSJonas Jensen platform_set_drvdata(pdev, moxart_rtc); 279453b4c6dSJonas Jensen 280453b4c6dSJonas Jensen ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data"); 281453b4c6dSJonas Jensen if (ret) { 282453b4c6dSJonas Jensen dev_err(&pdev->dev, "can't get rtc_data gpio\n"); 283453b4c6dSJonas Jensen return ret; 284453b4c6dSJonas Jensen } 285453b4c6dSJonas Jensen 286453b4c6dSJonas Jensen ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk, 287453b4c6dSJonas Jensen GPIOF_DIR_OUT, "rtc_sclk"); 288453b4c6dSJonas Jensen if (ret) { 289453b4c6dSJonas Jensen dev_err(&pdev->dev, "can't get rtc_sclk gpio\n"); 290453b4c6dSJonas Jensen return ret; 291453b4c6dSJonas Jensen } 292453b4c6dSJonas Jensen 293453b4c6dSJonas Jensen ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset, 294453b4c6dSJonas Jensen GPIOF_DIR_OUT, "rtc_reset"); 295453b4c6dSJonas Jensen if (ret) { 296453b4c6dSJonas Jensen dev_err(&pdev->dev, "can't get rtc_reset gpio\n"); 297453b4c6dSJonas Jensen return ret; 298453b4c6dSJonas Jensen } 299453b4c6dSJonas Jensen 300453b4c6dSJonas Jensen moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 301453b4c6dSJonas Jensen &moxart_rtc_ops, 302453b4c6dSJonas Jensen THIS_MODULE); 303453b4c6dSJonas Jensen if (IS_ERR(moxart_rtc->rtc)) { 304453b4c6dSJonas Jensen dev_err(&pdev->dev, "devm_rtc_device_register failed\n"); 305453b4c6dSJonas Jensen return PTR_ERR(moxart_rtc->rtc); 306453b4c6dSJonas Jensen } 307453b4c6dSJonas Jensen 308453b4c6dSJonas Jensen return 0; 309453b4c6dSJonas Jensen } 310453b4c6dSJonas Jensen 311453b4c6dSJonas Jensen static const struct of_device_id moxart_rtc_match[] = { 312453b4c6dSJonas Jensen { .compatible = "moxa,moxart-rtc" }, 313453b4c6dSJonas Jensen { }, 314453b4c6dSJonas Jensen }; 315*73798d5cSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, moxart_rtc_match); 316453b4c6dSJonas Jensen 317453b4c6dSJonas Jensen static struct platform_driver moxart_rtc_driver = { 318453b4c6dSJonas Jensen .probe = moxart_rtc_probe, 319453b4c6dSJonas Jensen .driver = { 320453b4c6dSJonas Jensen .name = "moxart-rtc", 321453b4c6dSJonas Jensen .of_match_table = moxart_rtc_match, 322453b4c6dSJonas Jensen }, 323453b4c6dSJonas Jensen }; 324453b4c6dSJonas Jensen module_platform_driver(moxart_rtc_driver); 325453b4c6dSJonas Jensen 326453b4c6dSJonas Jensen MODULE_DESCRIPTION("MOXART RTC driver"); 327453b4c6dSJonas Jensen MODULE_LICENSE("GPL"); 328453b4c6dSJonas Jensen MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>"); 329