From patchwork Sun Dec 7 19:59:39 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Brownell X-Patchwork-Id: 12641 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from wa-out-1516.google.com (wa-out-1516.google.com [209.85.146.166]) by ozlabs.org (Postfix) with ESMTP id E4365DDDEA for ; Mon, 8 Dec 2008 07:04:01 +1100 (EST) Received: by wa-out-1516.google.com with SMTP id l32so499300waf.1 for ; Sun, 07 Dec 2008 12:03:59 -0800 (PST) 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:domainkey-status :authentication-results:received:domainkey-signature:received :x-ymail-osg:x-yahoo-newman-property:from:to:subject:user-agent:cc :mime-version:content-type:date:message-id:reply-to:sender :precedence:x-google-loop:mailing-list:list-id:list-post:list-help :list-unsubscribe:x-beenthere-env:x-beenthere; bh=WeXHh7r4QTwtYAK/bT7/mpn3YjJyyxIq8cu3Oxb2jcI=; b=UCqhS9u8CBg0NBSHCMif031Zf1J2EjX8O3aGx3LewC837AMauh2Xda78iRJLZo1hnJ DcdJWyKl4YtOXocbXntNPVxSkhXMLQmQ814y/+FKnMHnYA/9euQym4siOD74mt+Ckq+n pF6mWNuRf98KsHP6iUjBWQgUby38uU6X/0Y0w= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlegroups.com; s=beta; h=x-sender:x-apparently-to:received-spf:domainkey-status :authentication-results:domainkey-signature:x-ymail-osg :x-yahoo-newman-property:from:to:subject:user-agent:cc:mime-version :content-type:date:message-id:reply-to:sender:precedence :x-google-loop:mailing-list:list-id:list-post:list-help :list-unsubscribe:x-beenthere-env:x-beenthere; b=UWjgTQ9VBZfpIt/f9hD3f+riKjEEUzQ/4TvmPxUXfYQmQZNpQbLnjLmGtp9ApbT7yL JXBFxqpavWb9vd0Vb5vt6DkB795E0NwlehX1qE1X6fBGYwPa42PGNIvBX3quWeYx3w8i Z7z8h6RkWclcUFN7l1yAUu3VNclAMnhwEQ6+E= Received: by 10.114.149.2 with SMTP id w2mr137697wad.12.1228680236407; Sun, 07 Dec 2008 12:03:56 -0800 (PST) Received: by 10.106.144.6 with SMTP id r6gr1721prd.0; Sun, 07 Dec 2008 12:03:56 -0800 (PST) X-Sender: david-b@pacbell.net X-Apparently-To: rtc-linux@googlegroups.com Received: by 10.115.109.18 with SMTP id l18mr1078437wam.8.1228680235834; Sun, 07 Dec 2008 12:03:55 -0800 (PST) Received: from smtp115.sbc.mail.sp1.yahoo.com (smtp115.sbc.mail.sp1.yahoo.com [69.147.64.88]) by mx.google.com with SMTP id m37si1442544waf.0.2008.12.07.12.03.54; Sun, 07 Dec 2008 12:03:54 -0800 (PST) Received-SPF: neutral (google.com: 69.147.64.88 is neither permitted nor denied by domain of david-b@pacbell.net) client-ip=69.147.64.88; DomainKey-Status: good (test mode) Authentication-Results: mx.google.com; spf=neutral (google.com: 69.147.64.88 is neither permitted nor denied by domain of david-b@pacbell.net) smtp.mail=david-b@pacbell.net; domainkeys=pass (test mode) header.From=david-b@pacbell.net Received: (qmail 41707 invoked from network); 7 Dec 2008 20:03:54 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=pacbell.net; h=Received:X-YMail-OSG:X-Yahoo-Newman-Property:From:To:Subject:User-Agent:Cc:MIME-Version:Content-Disposition:Date:Message-Id:Content-Type:Content-Transfer-Encoding; b=he2OPCIJhKdTYCTquu5Sg8LlEsWU73TFmHrzWw5wAprhwezJrNt7lK3klm+QGu68sFC/NlF9TU6jnLQ31DR9VLe5M206312fXy0Glyde4odUyMqbWUTjTShcjQ4eAoZSmQVV8OaESJ8XP5WlZOhxUD6eeyMMOM5RB6UxaImjMFA= ; Received: from unknown (HELO pogo.local) (david-b@69.226.235.54 with plain) by smtp115.sbc.mail.sp1.yahoo.com with SMTP; 7 Dec 2008 20:03:53 -0000 X-YMail-OSG: wr5dvsQVM1lFLmoXV5Fz78.uU2VcPbI6XfytGFz0rGRtkWFPeSR6.Jqb9c5UQzCtASgOVJiEa0MYqfZdAPkPJoo9poewuTeyKtQsvaS7Q_vE59GNX.H_ihVTJr3P63bpBFpcq0dZB4F3bw.chpE49eUN X-Yahoo-Newman-Property: ymail-3 From: David Brownell To: davinci-linux-open-source@linux.davincidsp.com Subject: [rtc-linux] [patch 2.6.28-rc6-davinci1 4/6] dm355evm rtc driver User-Agent: KMail/1.9.10 Cc: Felipe Balbi , rtc-linux@googlegroups.com Mime-Version: 1.0 Date: Sun, 7 Dec 2008 11:59:39 -0800 Message-Id: <200812071159.40197.david-b@pacbell.net> 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 From: David Brownell Simple RTC driver for the MSP430 firmware on the DM355 EVM board. Other than not supporting atomic reads/writes of all four bytes, this is quite reasonable as a basic no-alarm RTC. Signed-off-by: David Brownell --- Depends on the patch for the parent MFD driver. NOTE: not suitable for mainline until the dm355evm board support (and parent MFD driver) is in the merge queue. drivers/rtc/Kconfig | 6 + drivers/rtc/Makefile | 1 drivers/rtc/rtc-dm355evm.c | 175 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) --~--~---------~--~----~------------~-------~--~----~ 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. -~----------~----~----~----~------~----~------~--~--- --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -246,6 +246,12 @@ config RTC_DRV_M41T80_WDT If you say Y here you will get support for the watchdog timer in the ST M41T60 and M41T80 RTC chips series. +config RTC_DRV_DM355EVM + tristate "TI DaVinci DM355 EVM RTC" + depends on MFD_DM355EVM_MSP + help + Supports the RTC firmware in the MSP430 on the DM355 EVM. + config RTC_DRV_TWL92330 boolean "TI TWL92330/Menelaus" depends on MENELAUS --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_DAVINCI_EVM) += rtc-davinci-evm.o +obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o --- /dev/null +++ b/drivers/rtc/rtc-dm355evm.c @@ -0,0 +1,175 @@ +/* + * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware + * + * Copyright (c) 2008 by David Brownell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include + +#include + + +/* + * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed + * a 1 Hz counter. When a backup battery is supplied, that makes a + * reasonable RTC for applications where alarms and non-NTP drift + * compensation aren't important. + * + * The only real glitch is the inability to read or write all four + * counter bytes atomically: the count may increment in the middle + * of an operation, causing trouble when the LSB rolls over. + * + * This driver was tested with firmware revision A4. + */ +union evm_time { + u8 bytes[4]; + u32 value; +}; + +static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + union evm_time time; + int status; + int tries = 0; + + do { + /* + * Read LSB(0) to MSB(3) bytes. Defend against the counter + * rolling over by re-reading until the value is stable, + * and assuming the four reads take at most a few seconds. + */ + status = dm355evm_msp_read(DM355EVM_MSP_RTC_0); + if (status < 0) + return status; + if (tries && time.bytes[0] == status) + break; + time.bytes[0] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_1); + if (status < 0) + return status; + if (tries && time.bytes[1] == status) + break; + time.bytes[1] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_2); + if (status < 0) + return status; + if (tries && time.bytes[2] == status) + break; + time.bytes[2] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_3); + if (status < 0) + return status; + if (tries && time.bytes[3] == status) + break; + time.bytes[3] = status; + + } while (++tries < 5); + + dev_dbg(dev, "read timestamp %08x\n", time.value); + + rtc_time_to_tm(le32_to_cpu(time.value), tm); + return 0; +} + +static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + union evm_time time; + unsigned long value; + int status; + + rtc_tm_to_time(tm, &value); + time.value = cpu_to_le32(value); + + dev_dbg(dev, "write timestamp %08x\n", time.value); + + /* + * REVISIT handle non-atomic writes ... maybe just retry until + * byte[1] sticks (no rollover)? + */ + status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3); + if (status < 0) + return status; + + return 0; +} + +static struct rtc_class_ops dm355evm_rtc_ops = { + .read_time = dm355evm_rtc_read_time, + .set_time = dm355evm_rtc_set_time, +}; + +/*----------------------------------------------------------------------*/ + +static int __devinit dm355evm_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + + rtc = rtc_device_register(pdev->name, + &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "can't register RTC device, err %ld\n", + PTR_ERR(rtc)); + return PTR_ERR(rtc); + } + platform_set_drvdata(pdev, rtc); + + return 0; +} + +static int __devexit dm355evm_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev); + + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + return 0; +} + +/* + * I2C is used to talk to the MSP430, but this platform device is + * exposed by an MFD driver that manages I2C communications. + */ +static struct platform_driver rtc_dm355evm_driver = { + .probe = dm355evm_rtc_probe, + .remove = __devexit_p(dm355evm_rtc_remove), + .driver = { + .owner = THIS_MODULE, + .name = "rtc-dm355evm", + }, +}; + +static int __init dm355evm_rtc_init(void) +{ + return platform_driver_register(&rtc_dm355evm_driver); +} +module_init(dm355evm_rtc_init); + +static void __exit dm355evm_rtc_exit(void) +{ + platform_driver_unregister(&rtc_dm355evm_driver); +} +module_exit(dm355evm_rtc_exit); + +MODULE_LICENSE("GPL");