Browse Source

implement writing of the alarm timer and enabling the irq

Helmut Pozimski 5 years ago
parent
commit
a690627768
1 changed files with 56 additions and 11 deletions
  1. 56 11
      rtc-ds13307.c

+ 56 - 11
rtc-ds13307.c

@@ -205,19 +205,14 @@ static int ds13307_set_time(struct device *dev, struct rtc_time *time) {
 
 static int ds13307_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) {
 	struct i2c_client *client;
-	u8 buf[5], ctl[2], addr = DS1337_CTL;
+	u8 buf[9], addr = DS1337_ALRM1;
 	int h12;
 	client = to_i2c_client(dev);
-	if(ds13307_read_bytes(client, &addr, ctl, 2)) {
-		return -EIO;
-	}
-	// select for A1IE bit
-	alarm->enabled = ctl[0] & 0x01;
-	// select for A1F bit
-	alarm->pending = ctl[1] & 0x01;
-
-	addr = DS1337_ALRM1;
-	if (!ds13307_read_bytes(client, &addr, buf, 4)) {
+	if (!ds13307_read_bytes(client, &addr, buf, 9)) {
+		// select for A1IE bit
+		alarm->enabled = buf[7] & 0x01;
+		// select for A1F bit
+		alarm->pending = buf[8] & 0x01;
 		alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
 		alarm->time.tm_min = bcd2bin(buf[1] & 0x7F);
 		h12 = ds13307_check_12h_am_pm(&buf[2]);
@@ -238,6 +233,51 @@ static int ds13307_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) {
 	return -EIO;
 }
 
+/* Sets the alarm to the values passed to the function */
+static int ds13307_write_alarm(struct device *dev, struct rtc_wkalrm *alarm) {
+	struct i2c_client *client;
+	u8 buf[9], addr = DS1337_ALRM1;
+	client = to_i2c_client(dev);
+	if(!ds13307_read_bytes(client, &addr, buf, 9)) {
+		// enable or disable the alarm as requested
+		if ((alarm->enabled && (!(buf[7] & 0x01))) || ((!alarm->enabled && (buf[7] & 0x01)))) {
+			buf[7] ^= 0x01;
+		}
+		// disable alarm 2
+		if (buf[7] & 0x02) {
+			buf[7] ^= 0x02;
+		}
+		// clear the status bit
+		if (buf[8] & 0x01) {
+			buf[8] ^= 0x01;
+		}
+		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);
+		if(!ds13307_write_bytes(client, &addr, buf, 9)) {
+			return 0;
+		}
+	}
+	return -EIO;
+}
+
+static int ds13307_alarm_irq_enable(struct device *dev, unsigned int enabled) {
+	struct i2c_client *client;
+	u8 buf, addr = DS1337_CTL;
+	client = to_i2c_client(dev);
+	if (ds13307_read_bytes(client, &addr, &buf, 1)) {
+		return -EIO;
+	}
+	if ((!enabled && (buf & 0x01)) || (enabled & (!(buf & 0x01)))) {
+		buf ^= 0x01;
+	}
+	if(!ds13307_write_bytes(client, &addr, &buf, 1)) {
+		return 0;
+	}
+	return -EIO;
+}
+
 static struct rtc_class_ops ds13307_rtc_ops = {
 	.read_time = ds13307_read_time,
 	.set_time = ds13307_set_time
@@ -296,6 +336,9 @@ static int ds13307_probe(struct i2c_client *client,
 	if (IS_ERR(rtc)) {
 		return PTR_ERR(rtc);
 	}
+	rtc->uie_unsupported = 1;
+	device_set_wakeup_capable(&client->dev, 0);
+	client->irq = 0;
 	if (model_detected == DEVICE_DS1307) {
 		ds1307_nvmem.name = "ds1307_nvram";
 		ds1307_nvmem.word_size = 1;
@@ -306,6 +349,8 @@ static int ds13307_probe(struct i2c_client *client,
 		rtc->nvmem_config = &ds1307_nvmem;
 	} else {
 		ds13307_rtc_ops.read_alarm = ds13307_read_alarm;
+		ds13307_rtc_ops.set_alarm = ds13307_write_alarm;
+		ds13307_rtc_ops.alarm_irq_enable = ds13307_alarm_irq_enable;
 	}
 	rtc->ops = &ds13307_rtc_ops;
 	i2c_set_clientdata(client,rtc);