aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Guinot <simon.guinot@sequanux.org>2014-04-03 17:49:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:21:20 -0400
commit1d1945d261a2af4e1ddaf609308c30b83143c2da (patch)
tree975cd363f7e28cae601a814aeaa225e54daec1e2
parent5ea735144dd4d2716557ff62dbcc940d62d62208 (diff)
drivers/rtc/rtc-ds1307.c: add alarm support for mcp7941x chips
Add alarm support for the Microchip RTC devices MCP794xx. Note that two programmable alarms are provided by the chip but only one is used by the driver. Signed-off-by: Simon Guinot <simon.guinot@sequanux.org> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Andrew Lunn <andrew@lunn.ch> Cc: Gregory Clement <gregory.clement@free-electrons.com> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rtc/rtc-ds1307.c183
1 files changed, 182 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index f739be96cbc0..f03d5ba96db1 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -154,6 +154,7 @@ static const struct chip_desc chips[last_ds_type] = {
154 .alarm = 1, 154 .alarm = 1,
155 }, 155 },
156 [mcp7941x] = { 156 [mcp7941x] = {
157 .alarm = 1,
157 /* this is battery backed SRAM */ 158 /* this is battery backed SRAM */
158 .nvram_offset = 0x20, 159 .nvram_offset = 0x20,
159 .nvram_size = 0x40, 160 .nvram_size = 0x40,
@@ -606,6 +607,178 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
606 607
607/*----------------------------------------------------------------------*/ 608/*----------------------------------------------------------------------*/
608 609
610/*
611 * Alarm support for mcp7941x devices.
612 */
613
614#define MCP7941X_REG_CONTROL 0x07
615# define MCP7941X_BIT_ALM0_EN 0x10
616# define MCP7941X_BIT_ALM1_EN 0x20
617#define MCP7941X_REG_ALARM0_BASE 0x0a
618#define MCP7941X_REG_ALARM0_CTRL 0x0d
619#define MCP7941X_REG_ALARM1_BASE 0x11
620#define MCP7941X_REG_ALARM1_CTRL 0x14
621# define MCP7941X_BIT_ALMX_IF (1 << 3)
622# define MCP7941X_BIT_ALMX_C0 (1 << 4)
623# define MCP7941X_BIT_ALMX_C1 (1 << 5)
624# define MCP7941X_BIT_ALMX_C2 (1 << 6)
625# define MCP7941X_BIT_ALMX_POL (1 << 7)
626# define MCP7941X_MSK_ALMX_MATCH (MCP7941X_BIT_ALMX_C0 | \
627 MCP7941X_BIT_ALMX_C1 | \
628 MCP7941X_BIT_ALMX_C2)
629
630static void mcp7941x_work(struct work_struct *work)
631{
632 struct ds1307 *ds1307 = container_of(work, struct ds1307, work);
633 struct i2c_client *client = ds1307->client;
634 int reg, ret;
635
636 mutex_lock(&ds1307->rtc->ops_lock);
637
638 /* Check and clear alarm 0 interrupt flag. */
639 reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_ALARM0_CTRL);
640 if (reg < 0)
641 goto out;
642 if (!(reg & MCP7941X_BIT_ALMX_IF))
643 goto out;
644 reg &= ~MCP7941X_BIT_ALMX_IF;
645 ret = i2c_smbus_write_byte_data(client, MCP7941X_REG_ALARM0_CTRL, reg);
646 if (ret < 0)
647 goto out;
648
649 /* Disable alarm 0. */
650 reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_CONTROL);
651 if (reg < 0)
652 goto out;
653 reg &= ~MCP7941X_BIT_ALM0_EN;
654 ret = i2c_smbus_write_byte_data(client, MCP7941X_REG_CONTROL, reg);
655 if (ret < 0)
656 goto out;
657
658 rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
659
660out:
661 if (test_bit(HAS_ALARM, &ds1307->flags))
662 enable_irq(client->irq);
663 mutex_unlock(&ds1307->rtc->ops_lock);
664}
665
666static int mcp7941x_read_alarm(struct device *dev, struct rtc_wkalrm *t)
667{
668 struct i2c_client *client = to_i2c_client(dev);
669 struct ds1307 *ds1307 = i2c_get_clientdata(client);
670 u8 *regs = ds1307->regs;
671 int ret;
672
673 if (!test_bit(HAS_ALARM, &ds1307->flags))
674 return -EINVAL;
675
676 /* Read control and alarm 0 registers. */
677 ret = ds1307->read_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
678 if (ret < 0)
679 return ret;
680
681 t->enabled = !!(regs[0] & MCP7941X_BIT_ALM0_EN);
682
683 /* Report alarm 0 time assuming 24-hour and day-of-month modes. */
684 t->time.tm_sec = bcd2bin(ds1307->regs[3] & 0x7f);
685 t->time.tm_min = bcd2bin(ds1307->regs[4] & 0x7f);
686 t->time.tm_hour = bcd2bin(ds1307->regs[5] & 0x3f);
687 t->time.tm_wday = bcd2bin(ds1307->regs[6] & 0x7) - 1;
688 t->time.tm_mday = bcd2bin(ds1307->regs[7] & 0x3f);
689 t->time.tm_mon = bcd2bin(ds1307->regs[8] & 0x1f) - 1;
690 t->time.tm_year = -1;
691 t->time.tm_yday = -1;
692 t->time.tm_isdst = -1;
693
694 dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
695 "enabled=%d polarity=%d irq=%d match=%d\n", __func__,
696 t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
697 t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled,
698 !!(ds1307->regs[6] & MCP7941X_BIT_ALMX_POL),
699 !!(ds1307->regs[6] & MCP7941X_BIT_ALMX_IF),
700 (ds1307->regs[6] & MCP7941X_MSK_ALMX_MATCH) >> 4);
701
702 return 0;
703}
704
705static int mcp7941x_set_alarm(struct device *dev, struct rtc_wkalrm *t)
706{
707 struct i2c_client *client = to_i2c_client(dev);
708 struct ds1307 *ds1307 = i2c_get_clientdata(client);
709 unsigned char *regs = ds1307->regs;
710 int ret;
711
712 if (!test_bit(HAS_ALARM, &ds1307->flags))
713 return -EINVAL;
714
715 dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
716 "enabled=%d pending=%d\n", __func__,
717 t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
718 t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
719 t->enabled, t->pending);
720
721 /* Read control and alarm 0 registers. */
722 ret = ds1307->read_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
723 if (ret < 0)
724 return ret;
725
726 /* Set alarm 0, using 24-hour and day-of-month modes. */
727 regs[3] = bin2bcd(t->time.tm_sec);
728 regs[4] = bin2bcd(t->time.tm_min);
729 regs[5] = bin2bcd(t->time.tm_hour);
730 regs[6] = bin2bcd(t->time.tm_wday) + 1;
731 regs[7] = bin2bcd(t->time.tm_mday);
732 regs[8] = bin2bcd(t->time.tm_mon) + 1;
733
734 /* Clear the alarm 0 interrupt flag. */
735 regs[6] &= ~MCP7941X_BIT_ALMX_IF;
736 /* Set alarm match: second, minute, hour, day, date, month. */
737 regs[6] |= MCP7941X_MSK_ALMX_MATCH;
738
739 if (t->enabled)
740 regs[0] |= MCP7941X_BIT_ALM0_EN;
741 else
742 regs[0] &= ~MCP7941X_BIT_ALM0_EN;
743
744 ret = ds1307->write_block_data(client, MCP7941X_REG_CONTROL, 10, regs);
745 if (ret < 0)
746 return ret;
747
748 return 0;
749}
750
751static int mcp7941x_alarm_irq_enable(struct device *dev, unsigned int enabled)
752{
753 struct i2c_client *client = to_i2c_client(dev);
754 struct ds1307 *ds1307 = i2c_get_clientdata(client);
755 int reg;
756
757 if (!test_bit(HAS_ALARM, &ds1307->flags))
758 return -EINVAL;
759
760 reg = i2c_smbus_read_byte_data(client, MCP7941X_REG_CONTROL);
761 if (reg < 0)
762 return reg;
763
764 if (enabled)
765 reg |= MCP7941X_BIT_ALM0_EN;
766 else
767 reg &= ~MCP7941X_BIT_ALM0_EN;
768
769 return i2c_smbus_write_byte_data(client, MCP7941X_REG_CONTROL, reg);
770}
771
772static const struct rtc_class_ops mcp7941x_rtc_ops = {
773 .read_time = ds1307_get_time,
774 .set_time = ds1307_set_time,
775 .read_alarm = mcp7941x_read_alarm,
776 .set_alarm = mcp7941x_set_alarm,
777 .alarm_irq_enable = mcp7941x_alarm_irq_enable,
778};
779
780/*----------------------------------------------------------------------*/
781
609static ssize_t 782static ssize_t
610ds1307_nvram_read(struct file *filp, struct kobject *kobj, 783ds1307_nvram_read(struct file *filp, struct kobject *kobj,
611 struct bin_attribute *attr, 784 struct bin_attribute *attr,
@@ -678,6 +851,7 @@ static int ds1307_probe(struct i2c_client *client,
678 [ds_1339] = DS1339_BIT_BBSQI, 851 [ds_1339] = DS1339_BIT_BBSQI,
679 [ds_3231] = DS3231_BIT_BBSQW, 852 [ds_3231] = DS3231_BIT_BBSQW,
680 }; 853 };
854 const struct rtc_class_ops *rtc_ops = &ds13xx_rtc_ops;
681 855
682 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) 856 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)
683 && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 857 && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
@@ -816,6 +990,13 @@ static int ds1307_probe(struct i2c_client *client,
816 case ds_1388: 990 case ds_1388:
817 ds1307->offset = 1; /* Seconds starts at 1 */ 991 ds1307->offset = 1; /* Seconds starts at 1 */
818 break; 992 break;
993 case mcp7941x:
994 rtc_ops = &mcp7941x_rtc_ops;
995 if (ds1307->client->irq > 0 && chip->alarm) {
996 INIT_WORK(&ds1307->work, mcp7941x_work);
997 want_irq = true;
998 }
999 break;
819 default: 1000 default:
820 break; 1001 break;
821 } 1002 }
@@ -929,7 +1110,7 @@ read_rtc:
929 1110
930 device_set_wakeup_capable(&client->dev, want_irq); 1111 device_set_wakeup_capable(&client->dev, want_irq);
931 ds1307->rtc = devm_rtc_device_register(&client->dev, client->name, 1112 ds1307->rtc = devm_rtc_device_register(&client->dev, client->name,
932 &ds13xx_rtc_ops, THIS_MODULE); 1113 rtc_ops, THIS_MODULE);
933 if (IS_ERR(ds1307->rtc)) { 1114 if (IS_ERR(ds1307->rtc)) {
934 return PTR_ERR(ds1307->rtc); 1115 return PTR_ERR(ds1307->rtc);
935 } 1116 }