linux/drivers/rtc/rtc-ab3100.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007-2009 ST-Ericsson AB
   3 * License terms: GNU General Public License (GPL) version 2
   4 * RTC clock driver for the AB3100 Analog Baseband Chip
   5 * Author: Linus Walleij <linus.walleij@stericsson.com>
   6 */
   7#include <linux/module.h>
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/platform_device.h>
  11#include <linux/rtc.h>
  12#include <linux/mfd/ab3100.h>
  13
  14/* Clock rate in Hz */
  15#define AB3100_RTC_CLOCK_RATE   32768
  16
  17/*
  18 * The AB3100 RTC registers. These are the same for
  19 * AB3000 and AB3100.
  20 * Control register:
  21 * Bit 0: RTC Monitor cleared=0, active=1, if you set it
  22 *        to 1 it remains active until RTC power is lost.
  23 * Bit 1: 32 kHz Oscillator, 0 = on, 1 = bypass
  24 * Bit 2: Alarm on, 0 = off, 1 = on
  25 * Bit 3: 32 kHz buffer disabling, 0 = enabled, 1 = disabled
  26 */
  27#define AB3100_RTC              0x53
  28/* default setting, buffer disabled, alarm on */
  29#define RTC_SETTING             0x30
  30/* Alarm when AL0-AL3 == TI0-TI3  */
  31#define AB3100_AL0              0x56
  32#define AB3100_AL1              0x57
  33#define AB3100_AL2              0x58
  34#define AB3100_AL3              0x59
  35/* This 48-bit register that counts up at 32768 Hz */
  36#define AB3100_TI0              0x5a
  37#define AB3100_TI1              0x5b
  38#define AB3100_TI2              0x5c
  39#define AB3100_TI3              0x5d
  40#define AB3100_TI4              0x5e
  41#define AB3100_TI5              0x5f
  42
  43/*
  44 * RTC clock functions and device struct declaration
  45 */
  46static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
  47{
  48        struct ab3100 *ab3100_data = dev_get_drvdata(dev);
  49        u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
  50                     AB3100_TI3, AB3100_TI4, AB3100_TI5};
  51        unsigned char buf[6];
  52        u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
  53        int err = 0;
  54        int i;
  55
  56        buf[0] = (fat_time) & 0xFF;
  57        buf[1] = (fat_time >> 8) & 0xFF;
  58        buf[2] = (fat_time >> 16) & 0xFF;
  59        buf[3] = (fat_time >> 24) & 0xFF;
  60        buf[4] = (fat_time >> 32) & 0xFF;
  61        buf[5] = (fat_time >> 40) & 0xFF;
  62
  63        for (i = 0; i < 6; i++) {
  64                err = ab3100_set_register_interruptible(ab3100_data,
  65                                                        regs[i], buf[i]);
  66                if (err)
  67                        return err;
  68        }
  69
  70        /* Set the flag to mark that the clock is now set */
  71        return ab3100_mask_and_set_register_interruptible(ab3100_data,
  72                                                          AB3100_RTC,
  73                                                          0xFE, 0x01);
  74
  75}
  76
  77static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
  78{
  79        struct ab3100 *ab3100_data = dev_get_drvdata(dev);
  80        unsigned long time;
  81        u8 rtcval;
  82        int err;
  83
  84        err = ab3100_get_register_interruptible(ab3100_data,
  85                                                AB3100_RTC, &rtcval);
  86        if (err)
  87                return err;
  88
  89        if (!(rtcval & 0x01)) {
  90                dev_info(dev, "clock not set (lost power)");
  91                return -EINVAL;
  92        } else {
  93                u64 fat_time;
  94                u8 buf[6];
  95
  96                /* Read out time registers */
  97                err = ab3100_get_register_page_interruptible(ab3100_data,
  98                                                             AB3100_TI0,
  99                                                             buf, 6);
 100                if (err != 0)
 101                        return err;
 102
 103                fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) |
 104                        ((u64) buf[3] << 24) | ((u64) buf[2] << 16) |
 105                        ((u64) buf[1] << 8) | (u64) buf[0];
 106                time = (unsigned long) (fat_time /
 107                                        (u64) (AB3100_RTC_CLOCK_RATE * 2));
 108        }
 109
 110        rtc_time_to_tm(time, tm);
 111
 112        return rtc_valid_tm(tm);
 113}
 114
 115static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 116{
 117        struct ab3100 *ab3100_data = dev_get_drvdata(dev);
 118        unsigned long time;
 119        u64 fat_time;
 120        u8 buf[6];
 121        u8 rtcval;
 122        int err;
 123
 124        /* Figure out if alarm is enabled or not */
 125        err = ab3100_get_register_interruptible(ab3100_data,
 126                                                AB3100_RTC, &rtcval);
 127        if (err)
 128                return err;
 129        if (rtcval & 0x04)
 130                alarm->enabled = 1;
 131        else
 132                alarm->enabled = 0;
 133        /* No idea how this could be represented */
 134        alarm->pending = 0;
 135        /* Read out alarm registers, only 4 bytes */
 136        err = ab3100_get_register_page_interruptible(ab3100_data,
 137                                                     AB3100_AL0, buf, 4);
 138        if (err)
 139                return err;
 140        fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) |
 141                ((u64) buf[1] << 24) | ((u64) buf[0] << 16);
 142        time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2));
 143
 144        rtc_time_to_tm(time, &alarm->time);
 145
 146        return rtc_valid_tm(&alarm->time);
 147}
 148
 149static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 150{
 151        struct ab3100 *ab3100_data = dev_get_drvdata(dev);
 152        u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
 153        unsigned char buf[4];
 154        unsigned long secs;
 155        u64 fat_time;
 156        int err;
 157        int i;
 158
 159        rtc_tm_to_time(&alarm->time, &secs);
 160        fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
 161        buf[0] = (fat_time >> 16) & 0xFF;
 162        buf[1] = (fat_time >> 24) & 0xFF;
 163        buf[2] = (fat_time >> 32) & 0xFF;
 164        buf[3] = (fat_time >> 40) & 0xFF;
 165
 166        /* Set the alarm */
 167        for (i = 0; i < 4; i++) {
 168                err = ab3100_set_register_interruptible(ab3100_data,
 169                                                        regs[i], buf[i]);
 170                if (err)
 171                        return err;
 172        }
 173        /* Then enable the alarm */
 174        return ab3100_mask_and_set_register_interruptible(ab3100_data,
 175                                                          AB3100_RTC, ~(1 << 2),
 176                                                          alarm->enabled << 2);
 177}
 178
 179static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
 180{
 181        struct ab3100 *ab3100_data = dev_get_drvdata(dev);
 182
 183        /*
 184         * It's not possible to enable/disable the alarm IRQ for this RTC.
 185         * It does not actually trigger any IRQ: instead its only function is
 186         * to power up the system, if it wasn't on. This will manifest as
 187         * a "power up cause" in the AB3100 power driver (battery charging etc)
 188         * and need to be handled there instead.
 189         */
 190        if (enabled)
 191                return ab3100_mask_and_set_register_interruptible(ab3100_data,
 192                                                    AB3100_RTC, ~(1 << 2),
 193                                                    1 << 2);
 194        else
 195                return ab3100_mask_and_set_register_interruptible(ab3100_data,
 196                                                    AB3100_RTC, ~(1 << 2),
 197                                                    0);
 198}
 199
 200static const struct rtc_class_ops ab3100_rtc_ops = {
 201        .read_time      = ab3100_rtc_read_time,
 202        .set_mmss       = ab3100_rtc_set_mmss,
 203        .read_alarm     = ab3100_rtc_read_alarm,
 204        .set_alarm      = ab3100_rtc_set_alarm,
 205        .alarm_irq_enable = ab3100_rtc_irq_enable,
 206};
 207
 208static int __init ab3100_rtc_probe(struct platform_device *pdev)
 209{
 210        int err;
 211        u8 regval;
 212        struct rtc_device *rtc;
 213        struct ab3100 *ab3100_data = platform_get_drvdata(pdev);
 214
 215        /* The first RTC register needs special treatment */
 216        err = ab3100_get_register_interruptible(ab3100_data,
 217                                                AB3100_RTC, &regval);
 218        if (err) {
 219                dev_err(&pdev->dev, "unable to read RTC register\n");
 220                return -ENODEV;
 221        }
 222
 223        if ((regval & 0xFE) != RTC_SETTING) {
 224                dev_warn(&pdev->dev, "not default value in RTC reg 0x%x\n",
 225                         regval);
 226        }
 227
 228        if ((regval & 1) == 0) {
 229                /*
 230                 * Set bit to detect power loss.
 231                 * This bit remains until RTC power is lost.
 232                 */
 233                regval = 1 | RTC_SETTING;
 234                err = ab3100_set_register_interruptible(ab3100_data,
 235                                                        AB3100_RTC, regval);
 236                /* Ignore any error on this write */
 237        }
 238
 239        rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops,
 240                                  THIS_MODULE);
 241        if (IS_ERR(rtc)) {
 242                err = PTR_ERR(rtc);
 243                return err;
 244        }
 245
 246        return 0;
 247}
 248
 249static int __exit ab3100_rtc_remove(struct platform_device *pdev)
 250{
 251        struct rtc_device *rtc = platform_get_drvdata(pdev);
 252
 253        rtc_device_unregister(rtc);
 254        return 0;
 255}
 256
 257static struct platform_driver ab3100_rtc_driver = {
 258        .driver = {
 259                .name = "ab3100-rtc",
 260                .owner = THIS_MODULE,
 261        },
 262        .remove  = __exit_p(ab3100_rtc_remove),
 263};
 264
 265static int __init ab3100_rtc_init(void)
 266{
 267        return platform_driver_probe(&ab3100_rtc_driver,
 268                                     ab3100_rtc_probe);
 269}
 270
 271static void __exit ab3100_rtc_exit(void)
 272{
 273        platform_driver_unregister(&ab3100_rtc_driver);
 274}
 275
 276module_init(ab3100_rtc_init);
 277module_exit(ab3100_rtc_exit);
 278
 279MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 280MODULE_DESCRIPTION("AB3100 RTC Driver");
 281MODULE_LICENSE("GPL");
 282