From patchwork Thu May 4 10:33:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 758492 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-lf0-x23a.google.com (mail-lf0-x23a.google.com [IPv6:2a00:1450:4010:c07::23a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wJWbV1kL1z9ryr for ; Thu, 4 May 2017 20:33:57 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b="ohJFl4wm"; dkim-atps=neutral Received: by mail-lf0-x23a.google.com with SMTP id q70sf980623lfi.1 for ; Thu, 04 May 2017 03:33:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:mime-version:from:to:cc:subject:date:message-id :x-original-sender:x-original-authentication-results:reply-to :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post :list-help:list-archive:list-subscribe:list-unsubscribe; bh=wMRCR7xPHeUmDibc41zeLzMVf6yF3tiCGlw6GhjSPrM=; b=ohJFl4wmXCyYfLd2ysrkYxaOD2n2wcV5FNDALFV+2f2RL0VIobbgzsrl919PrfHLyy LcJcT0Gl+X8ZDYxT1iLowSM/PLlJZN/AMLUmN56Lz3fDCh9xduFWMdSJnLelZz7CA/Jm ZHTkX2E99hkw/YQYPZLBWZEfp97C3+9+tbfOjjxgw6+4ZBPs072LvJo65nPtQGMGGTDt zjtthPlQmQ1n3EW02y2BdE8nIASBf1Az6nC/NEO+SJ9mro4Pxsln79XOSwpHa8So7ubV e+nM4s+Finc9JVEPm5FHAS832RHy0Ht30DcFCfvrS7ZcPC8XeC33OxZ1+h7DtXRvr1pJ B0MQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:mime-version:from:to:cc:subject:date :message-id:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=wMRCR7xPHeUmDibc41zeLzMVf6yF3tiCGlw6GhjSPrM=; b=B1jyellZnM2j34J+4R3jGYU6TAY4CNksowjbUZwxlbIpfvANEPUBWbL4pCAp72c2Rn YMZ/657WjGbEkSL41e7pSi/cIQe9rjFWUT4+4ynwk5yVbNzt6ufNRX5qwzPUntpqlgCb 9L/C//8ezGgU5Y/lh6PMfLuhaW5b5ghZ1OQsMUdE1TVvgX9gn5A2K6PERVtQDqo97IW5 DzMYT/pnsG6cOogSWmbFdT7J4N5cNk7MonGE70pvBQgvzNvib6OfD282bVC3WkPM0h5r x8tEi53Wr4qOFQ7Sd9SIhbjCaPY1x6HxtAgJQsNXons/j+lcxmacoMeNFW/flobb/i12 Ypnw== Sender: rtc-linux@googlegroups.com X-Gm-Message-State: AN3rC/4VJUOHpMqCx6SJ6JHCHk7kynmQBO/wEPHUwY0QGGdcgEe7cvOL pZX1jio793M+fw== X-Received: by 10.28.215.196 with SMTP id o187mr988wmg.14.1493894034398; Thu, 04 May 2017 03:33:54 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.28.47.86 with SMTP id v83ls236539wmv.1.canary-gmail; Thu, 04 May 2017 03:33:53 -0700 (PDT) X-Received: by 10.223.141.175 with SMTP id o44mr1958306wrb.7.1493894033376; Thu, 04 May 2017 03:33:53 -0700 (PDT) Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.9]) by gmr-mx.google.com with ESMTPS id f136si77982wme.1.2017.05.04.03.33.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 May 2017 03:33:53 -0700 (PDT) Received-SPF: neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of marex@denx.de) client-ip=212.18.0.9; Received: from mail.nefkom.net (unknown [192.168.6.184]) by mail-out.m-online.net (Postfix) with ESMTP id 3wJWbN5yNxz1qrsr; Thu, 4 May 2017 12:33:52 +0200 (CEST) X-Auth-Info: D8VpMYlASppW8btn1PloNEEjqE2WDH0flwTXhagVLPM= Received: from kurokawa.lan (p578adb1c.dip0.t-ipconnect.de [87.138.219.28]) by smtp-auth.mnet-online.de (Postfix) with ESMTPA id 3wJWbN0pt1zvdWS; Thu, 4 May 2017 12:33:51 +0200 (CEST) From: Marek Vasut To: rtc-linux@googlegroups.com Cc: Marek Vasut , Alexandre Belloni , Arnd Bergmann , Felipe Balbi , Nishanth Menon , Tony Lindgren Subject: [rtc-linux] [PATCH] rtc: ds1307: Add support for Epson RX8130CE Date: Thu, 4 May 2017 12:33:46 +0200 Message-Id: <20170504103346.10842-1-marex@denx.de> X-Mailer: git-send-email 2.11.0 X-Original-Sender: marex@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.9 is neither permitted nor denied by best guess record for domain of marex@denx.de) smtp.mailfrom=marex@denx.de Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: rtc-linux@googlegroups.com X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Add support for yet another RTC chip, Epson RX8130CE. This time around, the chip has slightly permutated registers and also the register starts at 0x10 instead of 0x0 . Signed-off-by: Marek Vasut Cc: Alexandre Belloni Cc: Arnd Bergmann Cc: Felipe Balbi Cc: Nishanth Menon Cc: Tony Lindgren --- drivers/rtc/rtc-ds1307.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 77339b3d50a1..4a3c41c9e040 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -43,6 +43,7 @@ enum ds_type { m41t00, mcp794xx, rx_8025, + rx_8130, last_ds_type /* always last */ /* rs5c372 too? different address... */ }; @@ -169,6 +170,12 @@ static struct chip_desc chips[last_ds_type] = { [ds_3231] = { .alarm = 1, }, + [rx_8130] = { + .alarm = 1, + /* this is battery backed SRAM */ + .nvram_offset = 0x20, + .nvram_size = 4, /* 32bit (4 word x 8 bit) */ + }, [mcp794xx] = { .alarm = 1, /* this is battery backed SRAM */ @@ -192,6 +199,7 @@ static const struct i2c_device_id ds1307_id[] = { { "pt7c4338", ds_1307 }, { "rx8025", rx_8025 }, { "isl12057", ds_1337 }, + { "rx8130", rx_8130 }, { } }; MODULE_DEVICE_TABLE(i2c, ds1307_id); @@ -729,6 +737,169 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { /*----------------------------------------------------------------------*/ /* + * Alarm support for rx8130 devices. + */ + +#define RX8130_REG_ALARM_MIN 0x07 +#define RX8130_REG_ALARM_HOUR 0x08 +#define RX8130_REG_ALARM_WEEK_OR_DAY 0x09 +#define RX8130_REG_EXTENSION 0x0c +#define RX8130_REG_EXTENSION_WADA (1 << 3) +#define RX8130_REG_FLAG 0x0d +#define RX8130_REG_FLAG_AF (1 << 3) +#define RX8130_REG_CONTROL0 0x0e +#define RX8130_REG_CONTROL0_AIE (1 << 3) + +static irqreturn_t rx8130_irq(int irq, void *dev_id) +{ + struct i2c_client *client = dev_id; + struct ds1307 *ds1307 = i2c_get_clientdata(client); + struct mutex *lock = &ds1307->rtc->ops_lock; + u8 ctl[3]; + int ret; + + mutex_lock(lock); + + /* Read control registers. */ + ret = ds1307->read_block_data(client, RX8130_REG_EXTENSION, 3, ctl); + if (ret < 0) + goto out; + if (!(ctl[1] & RX8130_REG_FLAG_AF)) + goto out; + ctl[1] &= ~RX8130_REG_FLAG_AF; + ctl[2] &= ~RX8130_REG_CONTROL0_AIE; + + ret = ds1307->write_block_data(client, RX8130_REG_EXTENSION, 3, ctl); + if (ret < 0) + goto out; + + rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); + +out: + mutex_unlock(lock); + + return IRQ_HANDLED; +} + +static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1307 *ds1307 = i2c_get_clientdata(client); + u8 ald[3], ctl[3]; + int ret; + + if (!test_bit(HAS_ALARM, &ds1307->flags)) + return -EINVAL; + + /* Read alarm registers. */ + ret = ds1307->read_block_data(client, RX8130_REG_ALARM_MIN, 3, ald); + if (ret < 0) + return ret; + + /* Read control registers. */ + ret = ds1307->read_block_data(client, RX8130_REG_EXTENSION, 3, ctl); + if (ret < 0) + return ret; + + t->enabled = !!(ctl[2] & RX8130_REG_CONTROL0_AIE); + t->pending = !!(ctl[1] & RX8130_REG_FLAG_AF); + + /* Report alarm 0 time assuming 24-hour and day-of-month modes. */ + t->time.tm_sec = -1; + t->time.tm_min = bcd2bin(ald[0] & 0x7f); + t->time.tm_hour = bcd2bin(ald[1] & 0x7f); + t->time.tm_wday = -1; + t->time.tm_mday = bcd2bin(ald[2] & 0x7f); + t->time.tm_mon = -1; + t->time.tm_year = -1; + t->time.tm_yday = -1; + t->time.tm_isdst = -1; + + dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d enabled=%d\n", + __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, + t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled); + + return 0; +} + +static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1307 *ds1307 = i2c_get_clientdata(client); + u8 ald[3], ctl[3]; + int ret; + + if (!test_bit(HAS_ALARM, &ds1307->flags)) + return -EINVAL; + + dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " + "enabled=%d pending=%d\n", __func__, + t->time.tm_sec, t->time.tm_min, t->time.tm_hour, + t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, + t->enabled, t->pending); + + /* Read control registers. */ + ret = ds1307->read_block_data(client, RX8130_REG_EXTENSION, 3, ctl); + if (ret < 0) + return ret; + + ctl[0] &= ~RX8130_REG_EXTENSION_WADA; + ctl[1] |= RX8130_REG_FLAG_AF; + ctl[2] &= ~RX8130_REG_CONTROL0_AIE; + + ret = ds1307->write_block_data(client, RX8130_REG_EXTENSION, 3, ctl); + if (ret < 0) + return ret; + + /* Hardware alarm precision is 1 minute! */ + ald[0] = bin2bcd(t->time.tm_min); + ald[1] = bin2bcd(t->time.tm_hour); + ald[2] = bin2bcd(t->time.tm_mday); + + ret = ds1307->write_block_data(client, RX8130_REG_ALARM_MIN, 3, ald); + if (ret < 0) + return ret; + + if (!t->enabled) + return 0; + + ctl[2] |= RX8130_REG_CONTROL0_AIE; + + return ds1307->write_block_data(client, RX8130_REG_EXTENSION, 3, ctl); +} + +static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1307 *ds1307 = i2c_get_clientdata(client); + int reg; + + if (!test_bit(HAS_ALARM, &ds1307->flags)) + return -EINVAL; + + reg = i2c_smbus_read_byte_data(client, RX8130_REG_CONTROL0); + if (reg < 0) + return reg; + + if (enabled) + reg |= RX8130_REG_CONTROL0_AIE; + else + reg &= ~RX8130_REG_CONTROL0_AIE; + + return i2c_smbus_write_byte_data(client, RX8130_REG_CONTROL0, reg); +} + +static const struct rtc_class_ops rx8130_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, + .read_alarm = rx8130_read_alarm, + .set_alarm = rx8130_set_alarm, + .alarm_irq_enable = rx8130_alarm_irq_enable, +}; + +/*----------------------------------------------------------------------*/ + +/* * Alarm support for mcp794xx devices. */ @@ -1562,6 +1733,14 @@ static int ds1307_probe(struct i2c_client *client, hour); } break; + case rx_8130: + ds1307->offset = 0x10; /* Seconds starts at 0x10 */ + rtc_ops = &rx8130_rtc_ops; + if (ds1307->client->irq > 0 && chip->alarm) { + irq_handler = rx8130_irq; + want_irq = true; + } + break; case ds_1388: ds1307->offset = 1; /* Seconds starts at 1 */ break;