From patchwork Fri Jul 10 18:57:25 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Klossner X-Patchwork-Id: 29686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-yx0-f158.google.com (mail-yx0-f158.google.com [209.85.210.158]) by bilbo.ozlabs.org (Postfix) with ESMTP id 3F7C4B7082 for ; Sat, 11 Jul 2009 04:57:44 +1000 (EST) Received: by yxe30 with SMTP id 30so1266631yxe.29 for ; Fri, 10 Jul 2009 11:57:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=beta; h=domainkey-signature:received:received:x-sender:x-apparently-to :received:received:received-spf:authentication-results:received :received:received:x-xeroxint-source-ip:x-xeroxint-source-name :x-xeroxint-reported-name:received:received:message-id:to:subject :date:from:reply-to:sender:precedence:x-google-loop:mailing-list :list-id:list-post:list-help:list-unsubscribe:x-beenthere-env :x-beenthere; bh=3yheaqoAPHBs8bOiXeDA3rdWFRpKroE1LUc67ZxRYhk=; b=J8lLiRp/0IztYfnugPaK3pRue49mfiE/8R2NVvPzTrlLtcQFxCrjW3N7Wq3qD/S2Ko kOqf65XOlzPkcqz5q3b3X0YHzdl0NdNQv5UbkCh56OBKY/cYb85QeVobu2igSCFFj6dP gr92A8jdKp6tHJU8uGeX9Scb7K+eEEkWVbCvI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlegroups.com; s=beta; h=x-sender:x-apparently-to:received-spf:authentication-results :x-xeroxint-source-ip:x-xeroxint-source-name :x-xeroxint-reported-name:message-id:to:subject:date:from:reply-to :sender:precedence:x-google-loop:mailing-list:list-id:list-post :list-help:list-unsubscribe:x-beenthere-env:x-beenthere; b=RnUrugHLQVy4nJnGPb94M8t5Z7JZx9xsHmTweQXw96NJnF6U6wGLQwWcPWYw4JHdYf LRnOmf3q8uAYz0KNBAjmdAF2s4/nmiMky2YwqxbLjhPvIJRaMI1aAl4QdjidxyKadAHw 9RaHHXaDg7ihbRreSroxLnF3mj1BbNgUOZjKM= Received: by 10.151.15.19 with SMTP id s19mr637531ybi.17.1247252258732; Fri, 10 Jul 2009 11:57:38 -0700 (PDT) Received: by 10.176.94.13 with SMTP id r13gr2558yqb.0; Fri, 10 Jul 2009 11:57:38 -0700 (PDT) X-Sender: andrew@cesa.opbu.xerox.com X-Apparently-To: rtc-linux@googlegroups.com Received: by 10.114.157.11 with SMTP id f11mr201504wae.5.1247252258026; Fri, 10 Jul 2009 11:57:38 -0700 (PDT) Received: from wvmler6.mail.xerox.com (wvmler6.mail.xerox.com [13.8.138.231]) by gmr-mx.google.com with ESMTP id k32si407157wah.1.2009.07.10.11.57.37; Fri, 10 Jul 2009 11:57:37 -0700 (PDT) Received-SPF: pass (google.com: domain of andrew@cesa.opbu.xerox.com designates 13.8.138.231 as permitted sender) client-ip=13.8.138.231; Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of andrew@cesa.opbu.xerox.com designates 13.8.138.231 as permitted sender) smtp.mail=andrew@cesa.opbu.xerox.com Received: from wvmlir1.mail.xerox.com (wvmlir1.mail.xerox.com [13.147.8.221]) by wvmler6.mail.xerox.com (8.14.2/8.13.8) with ESMTP id n6AIva5B016178 for ; Fri, 10 Jul 2009 11:57:37 -0700 Received: from wvmlir1.mail.xerox.com (localhost.localdomain [127.0.0.1]) by wvmlir1.mail.xerox.com (8.14.2/8.13.6) with ESMTP id n6AIvQ4u016803 for ; Fri, 10 Jul 2009 11:57:26 -0700 Received: from hermes.opbu.xerox.com (hermes.opbu.xerox.com [13.62.6.81]) by wvmlir1.mail.xerox.com (8.14.2/8.13.6) with ESMTP id n6AIvQE3016798 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 10 Jul 2009 11:57:26 -0700 X-XeroxINT-Source-Ip: 13.62.6.81 X-XeroxINT-Source-Name: hermes.opbu.xerox.com X-XeroxINT-Reported-Name: hermes.opbu.xerox.com Received: from pogo.cesa.opbu.xerox.com (ns158-4.cesa.opbu.xerox.com [13.253.158.23]) by hermes.opbu.xerox.com (8.13.8+Sun/8.13.8) with ESMTP id n6AIvQQh022582 for ; Fri, 10 Jul 2009 11:57:26 -0700 (PDT) Received: from cesa.opbu.xerox.com (gto.cesa.opbu.xerox.com [13.62.136.98]) by pogo.cesa.opbu.xerox.com (8.13.6+Sun/8.13.6) with ESMTP id n6AIvP7J001896 for ; Fri, 10 Jul 2009 11:57:26 -0700 (PDT) Message-Id: <200907101857.n6AIvP7J001896@pogo.cesa.opbu.xerox.com> To: rtc-linux@googlegroups.com Subject: [rtc-linux] rtc: add support for the M48T201 chip to rtc-m48t59.c Date: Fri, 10 Jul 2009 11:57:25 -0700 From: Andrew Klossner Reply-To: rtc-linux@googlegroups.com Sender: rtc-linux@googlegroups.com Precedence: bulk X-Google-Loop: groups Mailing-List: list rtc-linux@googlegroups.com; contact rtc-linux+owner@googlegroups.com List-Id: List-Post: List-Help: List-Unsubscribe: , X-BeenThere-Env: rtc-linux@googlegroups.com X-BeenThere: rtc-linux@googlegroups.com rtc-m48t59: add support for the M48T201 chip. Also: Fix a bug in m48t59_rtc_probe failure return that would iounmap an address that hadn't been ioremapped. Fix a Y2K bug for the M48T59: 31-Dec-1999 would step to 1-Jan-1900. Fix diagnostic outputs to show the date correctly. Add a FIXME comment describing a likely bug in alarm-setting code. Signed-off-by: Andrew Klossner --- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. -~----------~----~----~----~------~----~------~--~--- diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 33921a6..c06e88f 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -82,8 +82,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY)); val = M48T59_READ(M48T59_WDAY); - if ((pdata->type == M48T59RTC_TYPE_M48T59) && - (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { + if (pdata->type == M48T59RTC_TYPE_M48T201) + tm->tm_year += (bcd2bin(M48T59_READ(M48T59_CENTURY))-19) * 100; + else if ((pdata->type == M48T59RTC_TYPE_M48T59) && + (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { dev_dbg(dev, "Century bit is enabled\n"); tm->tm_year += 100; /* one century */ } @@ -101,8 +103,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); - dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } @@ -121,8 +123,8 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) year -= 68; #endif - dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", - year + 1900, tm->tm_mon, tm->tm_mday, + dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); if (year < 0) @@ -139,11 +141,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) /* tm_mon is 0-11 */ M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR); - - if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100)) - val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); + if (pdata->type == M48T59RTC_TYPE_M48T59) { + /* The Century Enable Bit must be set regardless of whether + * the Century Bit is set, otherwise the clock would advance + * from 31-Dec-1999 to 1-Jan-1900. + */ + val = M48T59_WDAY_CEB | (year >= 100 ? M48T59_WDAY_CB : 0); + } val |= (bin2bcd(tm->tm_wday) & 0x07); M48T59_WRITE(val, M48T59_WDAY); + if (pdata->type == M48T59RTC_TYPE_M48T201) + M48T59_WRITE(bin2bcd(year / 100 + 19), M48T59_CENTURY); /* Clear the WRITE bit */ M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); @@ -177,10 +185,15 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) tm->tm_year += 68; #endif /* tm_mon is 0-11 */ - tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; + if (pdata->type == M48T59RTC_TYPE_M48T201) + tm->tm_mon = bcd2bin(M48T59_READ(M48T59_INTR) & 0x1f) - 1; + else + tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; val = M48T59_READ(M48T59_WDAY); - if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) + if (pdata->type == M48T59RTC_TYPE_M48T201) + tm->tm_year += (bcd2bin(M48T59_READ(M48T59_CENTURY))-19) * 100; + else if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) tm->tm_year += 100; /* one century */ tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE)); @@ -192,8 +205,8 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); - dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } @@ -228,6 +241,10 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) */ mday = tm->tm_mday; mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; + /* + * FIXME: this is wrong when we're setting an alarm to go off after + * midnight tonight. The alarm will never happen. + */ if (mday == 0xff) mday = M48T59_READ(M48T59_MDAY); @@ -244,6 +261,10 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) /* Issue the WRITE command */ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); + if (pdata->type == M48T59RTC_TYPE_M48T201) + M48T59_WRITE((M48T59_READ(M48T59_INTR) & 0xe0) | + (bin2bcd(tm->tm_mon + 1) & 0x1f), + M48T59_INTR); M48T59_WRITE(mday, M48T59_ALARM_DATE); M48T59_WRITE(hour, M48T59_ALARM_HOUR); M48T59_WRITE(min, M48T59_ALARM_MIN); @@ -253,8 +274,8 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); spin_unlock_irqrestore(&m48t59->lock, flags); - dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n", - year + 1900, tm->tm_mon, tm->tm_mday, + dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d:%02d:%02d\n", + tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } @@ -272,12 +293,16 @@ static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd, int ret = 0; spin_lock_irqsave(&m48t59->lock, flags); + /* + * Preserve the other fields in M48T59_INTR in case it's an M48T201 + * and they contain the alarm month. + */ switch (cmd) { case RTC_AIE_OFF: /* alarm interrupt off */ - M48T59_WRITE(0x00, M48T59_INTR); + M48T59_CLEAR_BITS(M48T59_INTR_AFE, M48T59_INTR); break; case RTC_AIE_ON: /* alarm interrupt on */ - M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); + M48T59_SET_BITS(M48T59_INTR_AFE, M48T59_INTR); break; default: ret = -ENOIOCTLCMD; @@ -475,6 +500,11 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) ops = &m48t02_rtc_ops; pdata->offset = 0x1ff0; break; + case M48T59RTC_TYPE_M48T201: + name = "m48t201"; + ops = &m48t59_rtc_ops; + pdata->offset = 0x7fff0; + break; default: dev_err(&pdev->dev, "Unknown RTC type\n"); ret = -ENODEV; @@ -502,7 +532,7 @@ out: rtc_device_unregister(m48t59->rtc); if (m48t59->irq != NO_IRQ) free_irq(m48t59->irq, &pdev->dev); - if (m48t59->ioaddr) + if (m48t59->ioaddr && !pdata->ioaddr) iounmap(m48t59->ioaddr); if (m48t59) kfree(m48t59); diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h index 6fc9614..8e2df6f 100644 --- a/include/linux/rtc/m48t59.h +++ b/include/linux/rtc/m48t59.h @@ -38,7 +38,7 @@ #define M48T59_ALARM_HOUR 0x4 #define M48T59_ALARM_MIN 0x3 #define M48T59_ALARM_SEC 0x2 -#define M48T59_UNUSED 0x1 +#define M48T59_CENTURY 0x1 /* Century (M48T201 only) */ #define M48T59_FLAGS 0x0 #define M48T59_FLAGS_WDT 0x80 /* watchdog timer expired */ #define M48T59_FLAGS_AF 0x40 /* alarm */ @@ -47,6 +47,7 @@ #define M48T59RTC_TYPE_M48T59 0 /* to keep compatibility */ #define M48T59RTC_TYPE_M48T02 1 #define M48T59RTC_TYPE_M48T08 2 +#define M48T59RTC_TYPE_M48T201 3 struct m48t59_plat_data { /* The method to access M48T59 registers */