linux/drivers/rtc/rtc-tx4939.c
<<
>>
Prefs
   1/*
   2 * TX4939 internal RTC driver
   3 * Based on RBTX49xx patch from CELF patch archive.
   4 *
   5 * This file is subject to the terms and conditions of the GNU General Public
   6 * License.  See the file "COPYING" in the main directory of this archive
   7 * for more details.
   8 *
   9 * (C) Copyright TOSHIBA CORPORATION 2005-2007
  10 */
  11#include <linux/rtc.h>
  12#include <linux/platform_device.h>
  13#include <linux/interrupt.h>
  14#include <linux/module.h>
  15#include <linux/io.h>
  16#include <linux/gfp.h>
  17#include <asm/txx9/tx4939.h>
  18
  19struct tx4939rtc_plat_data {
  20        struct rtc_device *rtc;
  21        struct tx4939_rtc_reg __iomem *rtcreg;
  22        spinlock_t lock;
  23};
  24
  25static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev)
  26{
  27        return platform_get_drvdata(to_platform_device(dev));
  28}
  29
  30static int tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem *rtcreg, int cmd)
  31{
  32        int i = 0;
  33
  34        __raw_writel(cmd, &rtcreg->ctl);
  35        /* This might take 30us (next 32.768KHz clock) */
  36        while (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_BUSY) {
  37                /* timeout on approx. 100us (@ GBUS200MHz) */
  38                if (i++ > 200 * 100)
  39                        return -EBUSY;
  40                cpu_relax();
  41        }
  42        return 0;
  43}
  44
  45static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs)
  46{
  47        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
  48        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
  49        int i, ret;
  50        unsigned char buf[6];
  51
  52        buf[0] = 0;
  53        buf[1] = 0;
  54        buf[2] = secs;
  55        buf[3] = secs >> 8;
  56        buf[4] = secs >> 16;
  57        buf[5] = secs >> 24;
  58        spin_lock_irq(&pdata->lock);
  59        __raw_writel(0, &rtcreg->adr);
  60        for (i = 0; i < 6; i++)
  61                __raw_writel(buf[i], &rtcreg->dat);
  62        ret = tx4939_rtc_cmd(rtcreg,
  63                             TX4939_RTCCTL_COMMAND_SETTIME |
  64                             (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
  65        spin_unlock_irq(&pdata->lock);
  66        return ret;
  67}
  68
  69static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
  70{
  71        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
  72        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
  73        int i, ret;
  74        unsigned long sec;
  75        unsigned char buf[6];
  76
  77        spin_lock_irq(&pdata->lock);
  78        ret = tx4939_rtc_cmd(rtcreg,
  79                             TX4939_RTCCTL_COMMAND_GETTIME |
  80                             (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
  81        if (ret) {
  82                spin_unlock_irq(&pdata->lock);
  83                return ret;
  84        }
  85        __raw_writel(2, &rtcreg->adr);
  86        for (i = 2; i < 6; i++)
  87                buf[i] = __raw_readl(&rtcreg->dat);
  88        spin_unlock_irq(&pdata->lock);
  89        sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
  90        rtc_time_to_tm(sec, tm);
  91        return rtc_valid_tm(tm);
  92}
  93
  94static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  95{
  96        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
  97        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
  98        int i, ret;
  99        unsigned long sec;
 100        unsigned char buf[6];
 101
 102        if (alrm->time.tm_sec < 0 ||
 103            alrm->time.tm_min < 0 ||
 104            alrm->time.tm_hour < 0 ||
 105            alrm->time.tm_mday < 0 ||
 106            alrm->time.tm_mon < 0 ||
 107            alrm->time.tm_year < 0)
 108                return -EINVAL;
 109        rtc_tm_to_time(&alrm->time, &sec);
 110        buf[0] = 0;
 111        buf[1] = 0;
 112        buf[2] = sec;
 113        buf[3] = sec >> 8;
 114        buf[4] = sec >> 16;
 115        buf[5] = sec >> 24;
 116        spin_lock_irq(&pdata->lock);
 117        __raw_writel(0, &rtcreg->adr);
 118        for (i = 0; i < 6; i++)
 119                __raw_writel(buf[i], &rtcreg->dat);
 120        ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM |
 121                             (alrm->enabled ? TX4939_RTCCTL_ALME : 0));
 122        spin_unlock_irq(&pdata->lock);
 123        return ret;
 124}
 125
 126static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 127{
 128        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 129        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 130        int i, ret;
 131        unsigned long sec;
 132        unsigned char buf[6];
 133        u32 ctl;
 134
 135        spin_lock_irq(&pdata->lock);
 136        ret = tx4939_rtc_cmd(rtcreg,
 137                             TX4939_RTCCTL_COMMAND_GETALARM |
 138                             (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
 139        if (ret) {
 140                spin_unlock_irq(&pdata->lock);
 141                return ret;
 142        }
 143        __raw_writel(2, &rtcreg->adr);
 144        for (i = 2; i < 6; i++)
 145                buf[i] = __raw_readl(&rtcreg->dat);
 146        ctl = __raw_readl(&rtcreg->ctl);
 147        alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
 148        alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
 149        spin_unlock_irq(&pdata->lock);
 150        sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
 151        rtc_time_to_tm(sec, &alrm->time);
 152        return rtc_valid_tm(&alrm->time);
 153}
 154
 155static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 156{
 157        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 158
 159        spin_lock_irq(&pdata->lock);
 160        tx4939_rtc_cmd(pdata->rtcreg,
 161                       TX4939_RTCCTL_COMMAND_NOP |
 162                       (enabled ? TX4939_RTCCTL_ALME : 0));
 163        spin_unlock_irq(&pdata->lock);
 164        return 0;
 165}
 166
 167static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id)
 168{
 169        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev_id);
 170        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 171        unsigned long events = RTC_IRQF;
 172
 173        spin_lock(&pdata->lock);
 174        if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) {
 175                events |= RTC_AF;
 176                tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 177        }
 178        spin_unlock(&pdata->lock);
 179        rtc_update_irq(pdata->rtc, 1, events);
 180
 181        return IRQ_HANDLED;
 182}
 183
 184static const struct rtc_class_ops tx4939_rtc_ops = {
 185        .read_time              = tx4939_rtc_read_time,
 186        .read_alarm             = tx4939_rtc_read_alarm,
 187        .set_alarm              = tx4939_rtc_set_alarm,
 188        .set_mmss               = tx4939_rtc_set_mmss,
 189        .alarm_irq_enable       = tx4939_rtc_alarm_irq_enable,
 190};
 191
 192static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj,
 193                                     struct bin_attribute *bin_attr,
 194                                     char *buf, loff_t pos, size_t size)
 195{
 196        struct device *dev = container_of(kobj, struct device, kobj);
 197        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 198        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 199        ssize_t count;
 200
 201        spin_lock_irq(&pdata->lock);
 202        for (count = 0; count < size; count++) {
 203                __raw_writel(pos++, &rtcreg->adr);
 204                *buf++ = __raw_readl(&rtcreg->dat);
 205        }
 206        spin_unlock_irq(&pdata->lock);
 207        return count;
 208}
 209
 210static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj,
 211                                      struct bin_attribute *bin_attr,
 212                                      char *buf, loff_t pos, size_t size)
 213{
 214        struct device *dev = container_of(kobj, struct device, kobj);
 215        struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 216        struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 217        ssize_t count;
 218
 219        spin_lock_irq(&pdata->lock);
 220        for (count = 0; count < size; count++) {
 221                __raw_writel(pos++, &rtcreg->adr);
 222                __raw_writel(*buf++, &rtcreg->dat);
 223        }
 224        spin_unlock_irq(&pdata->lock);
 225        return count;
 226}
 227
 228static struct bin_attribute tx4939_rtc_nvram_attr = {
 229        .attr = {
 230                .name = "nvram",
 231                .mode = S_IRUGO | S_IWUSR,
 232        },
 233        .size = TX4939_RTC_REG_RAMSIZE,
 234        .read = tx4939_rtc_nvram_read,
 235        .write = tx4939_rtc_nvram_write,
 236};
 237
 238static int __init tx4939_rtc_probe(struct platform_device *pdev)
 239{
 240        struct rtc_device *rtc;
 241        struct tx4939rtc_plat_data *pdata;
 242        struct resource *res;
 243        int irq, ret;
 244
 245        irq = platform_get_irq(pdev, 0);
 246        if (irq < 0)
 247                return -ENODEV;
 248        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 249        if (!pdata)
 250                return -ENOMEM;
 251        platform_set_drvdata(pdev, pdata);
 252
 253        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 254        pdata->rtcreg = devm_ioremap_resource(&pdev->dev, res);
 255        if (IS_ERR(pdata->rtcreg))
 256                return PTR_ERR(pdata->rtcreg);
 257
 258        spin_lock_init(&pdata->lock);
 259        tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 260        if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
 261                             0, pdev->name, &pdev->dev) < 0)
 262                return -EBUSY;
 263        rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 264                                  &tx4939_rtc_ops, THIS_MODULE);
 265        if (IS_ERR(rtc))
 266                return PTR_ERR(rtc);
 267        pdata->rtc = rtc;
 268        ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
 269
 270        return ret;
 271}
 272
 273static int __exit tx4939_rtc_remove(struct platform_device *pdev)
 274{
 275        struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
 276
 277        sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
 278        spin_lock_irq(&pdata->lock);
 279        tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 280        spin_unlock_irq(&pdata->lock);
 281        return 0;
 282}
 283
 284static struct platform_driver tx4939_rtc_driver = {
 285        .remove         = __exit_p(tx4939_rtc_remove),
 286        .driver         = {
 287                .name   = "tx4939rtc",
 288        },
 289};
 290
 291module_platform_driver_probe(tx4939_rtc_driver, tx4939_rtc_probe);
 292
 293MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 294MODULE_DESCRIPTION("TX4939 internal RTC driver");
 295MODULE_LICENSE("GPL");
 296MODULE_ALIAS("platform:tx4939rtc");
 297