Browse Source

introduce write_bytes function and remove usage of i2c_master_send

Helmut Pozimski 5 years ago
parent
commit
ecdd0ef975
1 changed files with 43 additions and 20 deletions
  1. 43 20
      rtc-ds13307.c

+ 43 - 20
rtc-ds13307.c

@@ -12,6 +12,7 @@
 #include <linux/rtc.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
+#include <linux/slab.h>
 
 #define M_NAME "rtc-ds13307" /* Module name */
 
@@ -63,12 +64,37 @@ static int ds13307_read_bytes(struct i2c_client *client,
 	}
 }
 
+/* Writes a specified number of bytes via 2ic, returns 0 on success */
+static int ds13307_write_bytes(struct i2c_client *client,
+	u8 *addr, u8 *bytes, int length) {
+	int r;
+	u8 *buf;
+	struct i2c_msg msg;
+	buf = (u8*) kmalloc(length +1, GFP_KERNEL);
+	if (buf == NULL) {
+		printk(KERN_ERR "%s: Could not allocate memory for buffer\n", M_NAME);
+		return -EIO;
+	}
+	buf[0] = (*addr);
+	memmove(buf + 1, bytes, length);
+	msg.addr = client->addr;
+	msg.len = length + 1;
+	msg.buf = addr;
+	r = i2c_transfer(client->adapter, &msg, 1);
+	kfree(buf);
+	if (r == 1) {
+		return 0;
+	} else {
+		return r;
+	}
+}
+
 /* 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, addr, buf[2];
-	int r, v;
+	u8 data, addr, buf;
+	int r, v = 0;
 	if (model_detected == DEVICE_DS1307) {
 		addr = COMMON_SEC;
 	} else {
@@ -76,16 +102,13 @@ static int ds13307_start_oscillator(struct i2c_client *client) {
 	}
 	r = ds13307_read_bytes(client, &addr, &data, 1);
 	if (data & COMMON_HIGH_BIT) {
-		buf[0] = addr;
-		buf[1] = data ^ COMMON_HIGH_BIT;
-		v = i2c_master_send(client, buf, 2);
-		if (v == 2) {
+		buf = data ^ COMMON_HIGH_BIT;
+		v = ds13307_write_bytes(client, &addr, &buf, 1);
+		if (!v) {
 			printk(KERN_DEBUG "%s: oscillator stop bit successfully cleared\n", M_NAME);
 		}
-	} else {
-		v = 2;
 	}
-	if ((r<0) || (v!=2)) {
+	if ((r<0) || (v)) {
 		return -EIO;
 	}
 	return 0;
@@ -143,28 +166,28 @@ static int ds13307_read_time(struct device *dev, struct rtc_time *time) {
 
 static int ds13307_set_time(struct device *dev, struct rtc_time *time) {
 	struct i2c_client *client;
-	u8 buf[8];
+	u8 buf[7], addr;
 	client = to_i2c_client(dev);
 	if (ds13307_start_oscillator(client)) {
 		printk(KERN_ERR "%s: failed to initialize the oscillator\n", M_NAME);
 		return -EIO;
 	}
-	buf[0] = COMMON_SEC;
-	buf[1] = bin2bcd(time->tm_sec);
-	buf[2] = bin2bcd(time->tm_min);
-	buf[3] = bin2bcd(time->tm_hour);
-	buf[4] = bin2bcd(time->tm_wday);
-	buf[5] = bin2bcd(time->tm_mday);
+	addr = COMMON_SEC;
+	buf[0] = bin2bcd(time->tm_sec);
+	buf[1] = bin2bcd(time->tm_min);
+	buf[2] = bin2bcd(time->tm_hour);
+	buf[3] = bin2bcd(time->tm_wday);
+	buf[4] = bin2bcd(time->tm_mday);
 	if ((model_detected == DEVICE_DS1337) && (time->tm_year >= 100)) {
-		buf[6] = bin2bcd(time->tm_mon + 1) | COMMON_HIGH_BIT;
+		buf[5] = bin2bcd(time->tm_mon + 1) | COMMON_HIGH_BIT;
 	} else if ((model_detected == DEVICE_DS1307) && (time->tm_year < 100)) {
 		       printk(KERN_ERR "%s: device does not support century information, dates before 2000 are not possible\n", M_NAME);
 		       return -EINVAL;
 	} else {
-		buf[6] = bin2bcd(time->tm_mon + 1);
+		buf[5] = bin2bcd(time->tm_mon + 1);
 	}
-	buf[7] = bin2bcd(time->tm_year % 100);
-	if (i2c_master_send(client, buf, 8) != 8) {
+	buf[6] = bin2bcd(time->tm_year % 100);
+	if(ds13307_write_bytes(client, &addr, buf, 7)) {
 		return -EIO;
 	}
 	return 0;