From patchwork Sat Jan 17 21:16:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Brownell X-Patchwork-Id: 19139 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.165]) by ozlabs.org (Postfix) with ESMTP id 61BE2DDF5C for ; Sun, 18 Jan 2009 08:22:23 +1100 (EST) Received: by wa-out-1516.google.com with SMTP id l32so1277304waf.1 for ; Sat, 17 Jan 2009 13:22:21 -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:date:user-agent :mime-version:content-type:content-transfer-encoding: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=mMggP7DRclGFoheJLwaZmuE1XMV9n7K2v+KJXzT3XRQ=; b=4RlXRjEmFUz7F4CRbEbwMQOkRZvycV5QJK6LB0Sq4iGXApYVYYqdvCu60iEjUnwH3X Hjluf5th/bpWJQiNk2/QpNUZPJpGCVeuIFE2tHWgRo8Z6n69SgToosHJP7moijujbN/J ReI5Qzl+bF82cpBaIe/GnCp9EDJJQep1XqJuc= 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:date:user-agent :mime-version:content-type:content-transfer-encoding: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=Ug+IZ+J7c6edCnK0auc3xaC3bNfngzp7VaJ4HKVAwCSPiAG7NSosLLXL8IpCDAfBN3 T6wigVOECbRgkV2Jj3T6tyiv6eKkwAx2hnXTmyiJwey90PlyC1V4+5hezyK7sukB4SFd 8q7Vqscsglml2RlFxrF6L5ayKbJYKMJUkfCb8= Received: by 10.114.158.1 with SMTP id g1mr349707wae.0.1232227338830; Sat, 17 Jan 2009 13:22:18 -0800 (PST) Received: by 10.106.25.29 with SMTP id 29gr1835pry.0; Sat, 17 Jan 2009 13:22:18 -0800 (PST) X-Sender: david-b@pacbell.net X-Apparently-To: rtc-linux@googlegroups.com Received: by 10.114.190.6 with SMTP id n6mr582915waf.19.1232227337849; Sat, 17 Jan 2009 13:22:17 -0800 (PST) Received: from smtp116.sbc.mail.sp1.yahoo.com (smtp116.sbc.mail.sp1.yahoo.com [69.147.64.89]) by mx.google.com with SMTP id k19si1963592waf.2.2009.01.17.13.22.16; Sat, 17 Jan 2009 13:22:16 -0800 (PST) Received-SPF: neutral (google.com: 69.147.64.89 is neither permitted nor denied by best guess record for domain of david-b@pacbell.net) client-ip=69.147.64.89; DomainKey-Status: good (test mode) Authentication-Results: mx.google.com; spf=neutral (google.com: 69.147.64.89 is neither permitted nor denied by best guess record for domain of david-b@pacbell.net) smtp.mail=david-b@pacbell.net; domainkeys=pass (test mode) header.From=david-b@pacbell.net Received: (qmail 93834 invoked from network); 17 Jan 2009 21:22:16 -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:Date:User-Agent:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-Disposition:Message-Id; b=29SScZEfJBE5osnWHvUuIwrYDRc/CC1e1vlcpwRuzgjIVX5oFl/5VkTWBG4zbrvH9wRc0QrVb2Ica4AO/pX4lGflmVtVfSM1VV7OjWjwOz6H8Uaaz4Gupoww81iZssOi2m1jQW0lv17YV3TZ4OabFPNdwBV+z4ZPXviJMXW+51U= ; Received: from unknown (HELO pogo) (david-b@69.226.224.20 with plain) by smtp116.sbc.mail.sp1.yahoo.com with SMTP; 17 Jan 2009 21:22:15 -0000 X-YMail-OSG: V7vY9JcVM1n9vjRKEMiVA_iyk_S3L60zukARBt3YVLUF8ZEY18CYyN86C.TmX2euuSK0gNelrPSfPHBBfDM7ozDIoJkNJJCpKIe676GutCEPR9xm5Nyax9NmyYukZYo0YZTzpCU2yW9bB54dolS6yrUWqvdpWCalETmEN2G.8v_NT7ywCk_cj4Y2xX18IG5YyG5TQTkJ.NVcfkYQ6o579QFC9DfB5cTbVq8I1g-- X-Yahoo-Newman-Property: ymail-3 From: David Brownell To: Andrew Morton , rtc-linux@googlegroups.com Subject: [rtc-linux] [patch 2.6.29-rc2] RTC: rtc-dm355evm driver Date: Sat, 17 Jan 2009 13:16:15 -0800 User-Agent: KMail/1.9.10 Mime-Version: 1.0 Message-Id: <200901171316.15712.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 Subject: RTC: rtc-dm355evm driver 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 reasonable as a basic no-alarm RTC. Signed-off-by: David Brownell Signed-off-by: Kevin Hilman --- 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 @@ -241,6 +241,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_AU1XXX) += rtc-au1xxx.o obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.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");