Browse Source

implemented clearing the oscillator stop bit for both models

Helmut Pozimski 5 years ago
parent
commit
0cffee634f
1 changed files with 35 additions and 0 deletions
  1. 35 0
      rtc-ds13307.c

+ 35 - 0
rtc-ds13307.c

@@ -17,9 +17,11 @@
 #define DEVICE_DS1307 1
 #define DEVICE_DS1337 2
 
+#define DS1307_SEC 0x00
 #define DS1307_MAX_ADDR 0x3F
 
 #define DS1337_CTL 0x0E
+#define DS1337_STAT 0x0F
 
 static int model_detected;
 
@@ -75,12 +77,45 @@ static int ds13307_detect_device(struct i2c_client *client) {
 	return -1;
 }
 
+/* The oscillator is stopped for both chips when power is first applied,
+ * therefore this function checks its status and clears the stop bit.
+ */
+static int ds13307_start_oscillator(struct i2c_client *client) {
+	u8 data;
+	int r, v;
+       	unsigned char addr;
+	char buf[2];
+	if (model_detected == DEVICE_DS1307) {
+		addr = DS1307_SEC;
+	} else {
+		addr = DS1337_STAT;
+	}
+	r = ds13307_read_single_byte(client, &addr, &data);
+	if (data & 0x80) {
+		buf[0] = addr;
+		buf[1] = data ^ 0x80;
+		v = i2c_master_send(client, buf, 2);
+	} else {
+		v = 2;
+	}
+	if ((r<0) || (v!=2)) {
+		return -EIO;
+	}
+	return 0;	
+}
+
 static int ds13307_probe(struct i2c_client *client,
 		const struct i2c_device_id *id) {
 	model_detected = ds13307_detect_device(client);
 	if ((model_detected != DEVICE_DS1307) && (model_detected != DEVICE_DS1337)) {
 		return -EIO;
 	}
+	if (ds13307_start_oscillator(client)) {
+		printk(KERN_ERR "%s: failed to initialize the oscillator\n", M_NAME);
+		return -EIO;
+	} else {
+		printk(KERN_DEBUG "%s: oscillator stop bit successfully cleared\n", M_NAME);
+	}
 	return 0;
 }