From patchwork Fri Oct 15 11:12:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lan Chunhe-B25806 X-Patchwork-Id: 67935 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-ww0-f56.google.com (mail-ww0-f56.google.com [74.125.82.56]) by ozlabs.org (Postfix) with ESMTP id 169E3B70E6 for ; Fri, 15 Oct 2010 22:11:10 +1100 (EST) Received: by wwi14 with SMTP id 14sf528718wwi.11 for ; Fri, 15 Oct 2010 04:11:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=beta; h=domainkey-signature:received:x-beenthere:received:received:received :received:received-spf:received:received:x-spamscore:x-bigfish :x-spam-tcs-scl:received:received:received:received:received :received:from:to:cc:subject:date:message-id:x-mailer :x-originalarrivaltime:mime-version:x-reverse-dns:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:list-post:list-help:list-archive:sender:list-subscribe :list-unsubscribe:content-type; bh=M1+NtZiXo9m2VU36/JWiapMFn4yOHAmWz3QbU2peEoo=; b=EpmkbB+UJKZnh6t4oRrnSiID6M6Jg9wHsF4F++vrjEvusGvqGt45ZMC9QwFE8VLjlh XieYgbAZaDqQiDyKLI6KMlQocNTiqs2Y+7rAFrvQX5xV7nD4xREfzOJ6fz+aBd5NU0Bt TAogHdUcR3c4dMjspMSI0VqYs8eCykMz9+Iv8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlegroups.com; s=beta; h=x-beenthere:received-spf:x-spamscore:x-bigfish:x-spam-tcs-scl:from :to:cc:subject:date:message-id:x-mailer:x-originalarrivaltime :mime-version:x-reverse-dns:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:list-post:list-help:list-archive:sender:list-subscribe :list-unsubscribe:content-type; b=EGc+3MGopG9D1Dlloi6qsonohjvzOEJSXVMMINRlNFzzPb1XY/npZy3x/CJ6PsJxZE nzk5K1yVXEw6IcZYtMWH3XTkK16wGrgX1h4gvI4imvF1YxtPMBwkubuPdmK1xmwNNxGI xCudUoEIS6ePM4Ek3Fo7vpEQLgxxlG+qUZNC0= Received: by 10.216.12.11 with SMTP id 11mr113571wey.25.1287141067403; Fri, 15 Oct 2010 04:11:07 -0700 (PDT) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.227.198.213 with SMTP id ep21ls153469wbb.2.p; Fri, 15 Oct 2010 04:11:06 -0700 (PDT) Received: by 10.227.176.79 with SMTP id bd15mr36467wbb.16.1287141066461; Fri, 15 Oct 2010 04:11:06 -0700 (PDT) Received: by 10.227.176.79 with SMTP id bd15mr36466wbb.16.1287141066429; Fri, 15 Oct 2010 04:11:06 -0700 (PDT) Received: from DB3EHSOBE003.bigfish.com (db3ehsobe003.messaging.microsoft.com [213.199.154.141]) by gmr-mx.google.com with ESMTP id h9si830636wbe.4.2010.10.15.04.11.06; Fri, 15 Oct 2010 04:11:06 -0700 (PDT) Received-SPF: neutral (google.com: 213.199.154.141 is neither permitted nor denied by best guess record for domain of B25806@freescale.com) client-ip=213.199.154.141; Received: from mail78-db3-R.bigfish.com (10.3.81.249) by DB3EHSOBE003.bigfish.com (10.3.84.23) with Microsoft SMTP Server id 14.1.225.8; Fri, 15 Oct 2010 11:11:06 +0000 Received: from mail78-db3 (localhost.localdomain [127.0.0.1]) by mail78-db3-R.bigfish.com (Postfix) with ESMTP id B7517F387E6 for ; Fri, 15 Oct 2010 11:11:05 +0000 (UTC) X-SpamScore: 3 X-BigFish: VS3(zzc8kzz1202hzz8275bhz2dh2a8h62h) X-Spam-TCS-SCL: 1:0 Received: from mail78-db3 (localhost.localdomain [127.0.0.1]) by mail78-db3 (MessageSwitch) id 1287141065162651_16619; Fri, 15 Oct 2010 11:11:05 +0000 (UTC) Received: from DB3EHSMHS001.bigfish.com (unknown [10.3.81.248]) by mail78-db3.bigfish.com (Postfix) with ESMTP id 25C154D0046 for ; Fri, 15 Oct 2010 11:11:05 +0000 (UTC) Received: from az33egw01.freescale.net (192.88.158.102) by DB3EHSMHS001.bigfish.com (10.3.87.101) with Microsoft SMTP Server (TLS) id 14.0.482.44; Fri, 15 Oct 2010 11:11:04 +0000 Received: from az33smr01.freescale.net (az33smr01.freescale.net [10.64.34.199]) by az33egw01.freescale.net (8.14.3/8.14.3) with ESMTP id o9FBB2aE008609 for ; Fri, 15 Oct 2010 04:11:02 -0700 (MST) Received: from zch01exm28.fsl.freescale.net (zch01exm28.ap.freescale.net [10.192.129.225]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id o9FBB1O8005124 for ; Fri, 15 Oct 2010 06:11:01 -0500 (CDT) Received: from localhost.localdomain ([10.193.20.71]) by zch01exm28.fsl.freescale.net with Microsoft SMTPSVC(6.0.3790.4675); Fri, 15 Oct 2010 19:11:13 +0800 From: Lan Chunhe-B25806 To: CC: , , Lan Chunhe-B25806 Subject: [rtc-linux] [PATCH] Add the alarm function for driver of DS3232 RTC Date: Fri, 15 Oct 2010 19:12:25 +0800 Message-ID: <1287141145-3217-1-git-send-email-b25806@freescale.com> X-Mailer: git-send-email 1.5.4.5 X-OriginalArrivalTime: 15 Oct 2010 11:11:13.0542 (UTC) FILETIME=[ADE31260:01CB6C59] MIME-Version: 1.0 X-Reverse-DNS: az33egw01.freescale.net X-Original-Sender: b25806@freescale.com X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 213.199.154.141 is neither permitted nor denied by best guess record for domain of B25806@freescale.com) smtp.mail=B25806@freescale.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: List-Post: , List-Help: , List-Archive: Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , The former driver of DS3232 RTC only has the tick function, and now add the alarm function for driver of DS3232 RTC. So, the driver of DS3232 RTC is complete. Signed-off-by: Lan Chunhe-B25806 --- drivers/rtc/rtc-ds3232.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 182 insertions(+), 0 deletions(-) diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 9daed8d..a9eda7a 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -2,6 +2,7 @@ * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C * * Copyright (C) 2009-2010 Freescale Semiconductor. + * Author: Jack Lan * * 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 @@ -175,6 +176,183 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time) DS3232_REG_SECONDS, 7, buf); } +/* + * DS3232 has two alarm, we only use alarm1 + * According to linux specification, only support one-shot alarm + * no periodic alarm mode + */ +static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds3232 *ds3232 = i2c_get_clientdata(client); + int control, stat; + int ret = 0; + u8 buf[4]; + + mutex_lock(&ds3232->mutex); + + ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); + if (ret < 0) + goto out; + stat = ret; + ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); + if (ret < 0) + goto out; + control = ret; + ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); + if (ret < 0) + goto out; + + alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F); + alarm->time.tm_min = bcd2bin(buf[1] & 0x7F); + alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); + alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); + + alarm->time.tm_mon = -1; + alarm->time.tm_year = -1; + alarm->time.tm_wday = -1; + alarm->time.tm_yday = -1; + alarm->time.tm_isdst = -1; + + alarm->enabled = !!(control & DS3232_REG_CR_A1IE); + alarm->pending = !!(stat & DS3232_REG_SR_A1F); + + mutex_unlock(&ds3232->mutex); + return 0; +out: + mutex_unlock(&ds3232->mutex); + return ret; +} + +/* + * linux rtc-module does not support wday alarm + * and only 24h time mode supported indeed + */ +static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds3232 *ds3232 = i2c_get_clientdata(client); + int control, stat; + int ret; + u8 buf[4]; + + if (client->irq <= 0) + return -EINVAL; + + mutex_lock(&ds3232->mutex); + + buf[0] = bin2bcd(alarm->time.tm_sec); + buf[1] = bin2bcd(alarm->time.tm_min); + buf[2] = bin2bcd(alarm->time.tm_hour); + buf[3] = bin2bcd(alarm->time.tm_mday); + + /* clear alarm interrupt enable bit */ + ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); + if (ret < 0) + goto out; + control = ret; + control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); + ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); + if (ret < 0) + goto out; + + /* clear any pending alarm flag */ + ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); + if (ret < 0) + goto out; + stat = ret; + stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); + ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); + if (ret < 0) + goto out; + + ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); + + if (alarm->enabled) { + control |= DS3232_REG_CR_A1IE; + ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); + } +out: + mutex_unlock(&ds3232->mutex); + return ret; +} + +static void ds3232_update_alarm(struct i2c_client *client) +{ + struct ds3232 *ds3232 = i2c_get_clientdata(client); + int control; + int ret; + u8 buf[4]; + + mutex_lock(&ds3232->mutex); + + ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); + if (ret < 0) + goto unlock; + + buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? + 0x80 : buf[0]; + buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? + 0x80 : buf[1]; + buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? + 0x80 : buf[2]; + buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? + 0x80 : buf[3]; + + ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); + if (ret < 0) + goto unlock; + + control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); + if (control < 0) + goto unlock; + + if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF)) + /* enable alarm1 interrupt */ + control |= DS3232_REG_CR_A1IE; + else + /* disable alarm1 interrupt */ + control &= ~(DS3232_REG_CR_A1IE); + i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); + +unlock: + mutex_unlock(&ds3232->mutex); +} + +static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds3232 *ds3232 = i2c_get_clientdata(client); + + if (client->irq <= 0) + return -EINVAL; + + if (enabled) + ds3232->rtc->irq_data |= RTC_AF; + else + ds3232->rtc->irq_data &= ~RTC_AF; + + ds3232_update_alarm(client); + return 0; +} + +static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds3232 *ds3232 = i2c_get_clientdata(client); + + if (client->irq <= 0) + return -EINVAL; + + if (enabled) + ds3232->rtc->irq_data |= RTC_UF; + else + ds3232->rtc->irq_data &= ~RTC_UF; + + ds3232_update_alarm(client); + return 0; +} + static irqreturn_t ds3232_irq(int irq, void *dev_id) { struct i2c_client *client = dev_id; @@ -222,6 +400,10 @@ unlock: static const struct rtc_class_ops ds3232_rtc_ops = { .read_time = ds3232_read_time, .set_time = ds3232_set_time, + .read_alarm = ds3232_read_alarm, + .set_alarm = ds3232_set_alarm, + .alarm_irq_enable = ds3232_alarm_irq_enable, + .update_irq_enable = ds3232_update_irq_enable, }; static int __devinit ds3232_probe(struct i2c_client *client,