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/abx500.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        u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
  49                     AB3100_TI3, AB3100_TI4, AB3100_TI5};
  50        unsigned char buf[6];
  51        u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
  52        int err = 0;
  53        int i;
  54
  55        buf[0] = (fat_time) & 0xFF;
  56        buf[1] = (fat_time >> 8) & 0xFF;
  57        buf[2] = (fat_time >> 16) & 0xFF;
  58        buf[3] = (fat_time >> 24) & 0xFF;
  59        buf[4] = (fat_time >> 32) & 0xFF;
  60        buf[5] = (fat_time >> 40) & 0xFF;
  61
  62        for (i = 0; i < 6; i++) {
  63                err = abx500_set_register_interruptible(dev, 0,
  64                                                        regs[i], buf[i]);
  65                if (err)
  66                        return err;
  67        }
  68
  69        /* Set the flag to mark that the clock is now set */
  70        return abx500_mask_and_set_register_interruptible(dev, 0,
  71                                                          AB3100_RTC,
  72                                                          0x01, 0x01);
  73
  74}
  75
  76static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
  77{
  78        unsigned long time;
  79        u8 rtcval;
  80        int err;
  81
  82        err = abx500_get_register_interruptible(dev, 0,
  83                                                AB3100_RTC, &rtcval);
  84        if (err)
  85                return err;
  86
  87        if (!(rtcval & 0x01)) {
  88                dev_info(dev, "clock not set (lost power)");
  89                return -EINVAL;
  90        } else {
  91                u64 fat_time;
  92                u8 buf[6];
  93
  94                /* Read out time registers */
  95                err = abx500_get_register_page_interruptible(dev, 0,
  96                                                             AB3100_TI0,
  97                                                             buf, 6);
  98                if (err != 0)
  99                        return err;
 100
 101                fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) |
 102                        ((u64) buf[3] << 24) | ((u64) buf[2] << 16) |
 103                        ((u64) buf[1] << 8) | (u64) buf[0];
 104                time = (unsigned long) (fat_time /
 105                                        (u64) (AB3100_RTC_CLOCK_RATE * 2));
 106        }
 107
 108        rtc_time_to_tm(time, tm);
 109
 110        return rtc_valid_tm(tm);
 111}
 112
 113static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 114{
 115        unsigned long time;
 116        u64 fat_time;
 117        u8 buf[6];
 118        u8 rtcval;
 119        int err;
 120
 121        /* Figure out if alarm is enabled or not */
 122        err = abx500_get_register_interruptible(dev, 0,
 123                                                AB3100_RTC, &rtcval);
 124        if (err)
 125                return err;
 126        if (rtcval & 0x04)
 127                alarm->enabled = 1;
 128        else
 129                alarm->enabled = 0;
 130        /* No idea how this could be represented */
 131        alarm->pending = 0;
 132        /* Read out alarm registers, only 4 bytes */
 133        err = abx500_get_register_page_interruptible(dev, 0,
 134                                                     AB3100_AL0, buf, 4);
 135        if (err)
 136                return err;
 137        fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) |
 138                ((u64) buf[1] << 24) | ((u64) buf[0] << 16);
 139        time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2));
 140
 141        rtc_time_to_tm(time, &alarm->time);
 142
 143        return rtc_valid_tm(&alarm->time);
 144}
 145
 146static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 147{
 148        u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
 149        unsigned char buf[4];
 150        unsigned long secs;
 151        u64 fat_time;
 152        int err;
 153        int i;
 154
 155        rtc_tm_to_time(&alarm->time, &secs);
 156        fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2;
 157        buf[0] = (fat_time >> 16) & 0xFF;
 158        buf[1] = (fat_time >> 24) & 0xFF;
 159        buf[2] = (fat_time >> 32) & 0xFF;
 160        buf[3] = (fat_time >> 40) & 0xFF;
 161
 162        /* Set the alarm */
 163        for (i = 0; i < 4; i++) {
 164                err = abx500_set_register_interruptible(dev, 0,
 165                                                        regs[i], buf[i]);
 166                if (err)
 167                        return err;
 168        }
 169        /* Then enable the alarm */
 170        return abx500_mask_and_set_register_interruptible(dev, 0,
 171                                                          AB3100_RTC, (1 << 2),
 172                                                          alarm->enabled << 2);
 173}
 174
 175static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
 176{
 177        /*
 178         * It's not possible to enable/disable the alarm IRQ for this RTC.
 179         * It does not actually trigger any IRQ: instead its only function is
 180         * to power up the system, if it wasn't on. This will manifest as
 181         * a "power up cause" in the AB3100 power driver (battery charging etc)
 182         * and need to be handled there instead.
 183         */
 184        if (enabled)
 185                return abx500_mask_and_set_register_interruptible(dev, 0,
 186                                                    AB3100_RTC, (1 << 2),
 187                                                    1 << 2);
 188        else
 189                return abx500_mask_and_set_register_interruptible(dev, 0,
 190                                                    AB3100_RTC, (1 << 2),
 191                                                    0);
 192}
 193
 194static const struct rtc_class_ops ab3100_rtc_ops = {
 195        .read_time      = ab3100_rtc_read_time,
 196        .set_mmss       = ab3100_rtc_set_mmss,
 197        .read_alarm     = ab3100_rtc_read_alarm,
 198        .set_alarm      = ab3100_rtc_set_alarm,
 199        .alarm_irq_enable = ab3100_rtc_irq_enable,
 200};
 201
 202static int __init ab3100_rtc_probe(struct platform_device *pdev)
 203{
 204        int err;
 205        u8 regval;
 206        struct rtc_device *rtc;
 207
 208        /* The first RTC register needs special treatment */
 209        err = abx500_get_register_interruptible(&pdev->dev, 0,
 210                                                AB3100_RTC, &regval);
 211        if (err) {
 212                dev_err(&pdev->dev, "unable to read RTC register\n");
 213                return -ENODEV;
 214        }
 215
 216        if ((regval & 0xFE) != RTC_SETTING) {
 217                dev_warn(&pdev->dev, "not default value in RTC reg 0x%x\n",
 218                         regval);
 219        }
 220
 221        if ((regval & 1) == 0) {
 222                /*
 223                 * Set bit to detect power loss.
 224                 * This bit remains until RTC power is lost.
 225                 */
 226                regval = 1 | RTC_SETTING;
 227                err = abx500_set_register_interruptible(&pdev->dev, 0,
 228                                                        AB3100_RTC, regval);
 229                /* Ignore any error on this write */
 230        }
 231
 232        rtc = rtc_device_register("ab3100-rtc", &pdev->dev, &ab3100_rtc_ops,
 233                                  THIS_MODULE);
 234        if (IS_ERR(rtc)) {
 235                err = PTR_ERR(rtc);
 236                return err;
 237        }
 238        platform_set_drvdata(pdev, rtc);
 239
 240        return 0;
 241}
 242
 243static int __exit ab3100_rtc_remove(struct platform_device *pdev)
 244{
 245        struct rtc_device *rtc = platform_get_drvdata(pdev);
 246
 247        rtc_device_unregister(rtc);
 248        platform_set_drvdata(pdev, NULL);
 249        return 0;
 250}
 251
 252static struct platform_driver ab3100_rtc_driver = {
 253        .driver = {
 254                .name = "ab3100-rtc",
 255                .owner = THIS_MODULE,
 256        },
 257        .remove  = __exit_p(ab3100_rtc_remove),
 258};
 259
 260static int __init ab3100_rtc_init(void)
 261{
 262        return platform_driver_probe(&ab3100_rtc_driver,
 263                                     ab3100_rtc_probe);
 264}
 265
 266static void __exit ab3100_rtc_exit(void)
 267{
 268        platform_driver_unregister(&ab3100_rtc_driver);
 269}
 270
 271module_init(ab3100_rtc_init);
 272module_exit(ab3100_rtc_exit);
 273
 274MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
 275MODULE_DESCRIPTION("AB3100 RTC Driver");
 276MODULE_LICENSE("GPL");
 277
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.