Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2b84ee8 authored by Mylène Josserand's avatar Mylène Josserand Committed by Alexandre Belloni
Browse files

rtc: m41t80: replace i2c functions for smbus ones



The driver used i2c_transfer methods to read and set date/time.
The smbus methods should be used.

This commit replaces i2c_transfer functions by i2c_smbus_XX_i2c_block_data
for reading and setting the datetime.

Signed-off-by: default avatarMylène Josserand <mylene.josserand@free-electrons.com>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent ca91607f
Loading
Loading
Loading
Loading
+44 −90
Original line number Original line Diff line number Diff line
@@ -32,20 +32,20 @@
#include <linux/watchdog.h>
#include <linux/watchdog.h>
#endif
#endif


#define M41T80_REG_SSEC	0
#define M41T80_REG_SSEC		0x00
#define M41T80_REG_SEC	1
#define M41T80_REG_SEC		0x01
#define M41T80_REG_MIN	2
#define M41T80_REG_MIN		0x02
#define M41T80_REG_HOUR	3
#define M41T80_REG_HOUR		0x03
#define M41T80_REG_WDAY	4
#define M41T80_REG_WDAY		0x04
#define M41T80_REG_DAY	5
#define M41T80_REG_DAY		0x05
#define M41T80_REG_MON	6
#define M41T80_REG_MON		0x06
#define M41T80_REG_YEAR	7
#define M41T80_REG_YEAR		0x07
#define M41T80_REG_ALARM_MON	0xa
#define M41T80_REG_ALARM_MON	0x0a
#define M41T80_REG_ALARM_DAY	0xb
#define M41T80_REG_ALARM_DAY	0x0b
#define M41T80_REG_ALARM_HOUR	0xc
#define M41T80_REG_ALARM_HOUR	0x0c
#define M41T80_REG_ALARM_MIN	0xd
#define M41T80_REG_ALARM_MIN	0x0d
#define M41T80_REG_ALARM_SEC	0xe
#define M41T80_REG_ALARM_SEC	0x0e
#define M41T80_REG_FLAGS	0xf
#define M41T80_REG_FLAGS	0x0f
#define M41T80_REG_SQW		0x13
#define M41T80_REG_SQW		0x13


#define M41T80_DATETIME_REG_SIZE	(M41T80_REG_YEAR + 1)
#define M41T80_DATETIME_REG_SIZE	(M41T80_REG_YEAR + 1)
@@ -93,24 +93,13 @@ struct m41t80_data {
static int m41t80_get_datetime(struct i2c_client *client,
static int m41t80_get_datetime(struct i2c_client *client,
			       struct rtc_time *tm)
			       struct rtc_time *tm)
{
{
	u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC };
	unsigned char buf[8];
	struct i2c_msg msgs[] = {
	int err;
		{
			.addr	= client->addr,
			.flags	= 0,
			.len	= 1,
			.buf	= dt_addr,
		},
		{
			.addr	= client->addr,
			.flags	= I2C_M_RD,
			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
			.buf	= buf + M41T80_REG_SEC,
		},
	};


	if (i2c_transfer(client->adapter, msgs, 2) < 0) {
	err = i2c_smbus_read_i2c_block_data(client, M41T80_REG_SSEC,
		dev_err(&client->dev, "read error\n");
					    sizeof(buf), buf);
	if (err < 0) {
		dev_err(&client->dev, "Unable to read date\n");
		return -EIO;
		return -EIO;
	}
	}


@@ -129,67 +118,29 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* Sets the given date and time to the real time clock. */
/* Sets the given date and time to the real time clock. */
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
{
	u8 wbuf[1 + M41T80_DATETIME_REG_SIZE];
	unsigned char buf[8];
	u8 *buf = &wbuf[1];
	int err;
	u8 dt_addr[1] = { M41T80_REG_SEC };
	struct i2c_msg msgs_in[] = {
		{
			.addr	= client->addr,
			.flags	= 0,
			.len	= 1,
			.buf	= dt_addr,
		},
		{
			.addr	= client->addr,
			.flags	= I2C_M_RD,
			.len	= M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
			.buf	= buf + M41T80_REG_SEC,
		},
	};
	struct i2c_msg msgs[] = {
		{
			.addr	= client->addr,
			.flags	= 0,
			.len	= 1 + M41T80_DATETIME_REG_SIZE,
			.buf	= wbuf,
		 },
	};


	/* Read current reg values into buf[1..7] */
	if (tm->tm_year < 100 || tm->tm_year > 199)
	if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
		return -EINVAL;
		dev_err(&client->dev, "read error\n");
		return -EIO;
	}


	wbuf[0] = 0; /* offset into rtc's regs */
	/* Merge time-data and register flags into buf[0..7] */
	buf[M41T80_REG_SSEC] = 0;
	buf[M41T80_REG_SSEC] = 0;
	buf[M41T80_REG_SEC] =
	buf[M41T80_REG_SEC] = bin2bcd(tm->tm_sec);
		bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
	buf[M41T80_REG_MIN] = bin2bcd(tm->tm_min);
	buf[M41T80_REG_MIN] =
	buf[M41T80_REG_HOUR] = bin2bcd(tm->tm_hour);
		bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
	buf[M41T80_REG_DAY] = bin2bcd(tm->tm_mday);
	buf[M41T80_REG_HOUR] =
	buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1);
		bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f);
	buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100);
	buf[M41T80_REG_WDAY] =
	buf[M41T80_REG_WDAY] = tm->tm_wday;
		(tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
	buf[M41T80_REG_DAY] =
		bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
	buf[M41T80_REG_MON] =
		bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);

	/* assume 20YY not 19YY */
	if (tm->tm_year < 100 || tm->tm_year > 199) {
		dev_err(&client->dev, "Year must be between 2000 and 2099. It's %d.\n",
			tm->tm_year + 1900);
		return -EINVAL;
	}
	buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100);


	if (i2c_transfer(client->adapter, msgs, 1) != 1) {
	err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_SSEC,
		dev_err(&client->dev, "write error\n");
					     sizeof(buf), buf);
		return -EIO;
	if (err < 0) {
		dev_err(&client->dev, "Unable to write to date registers\n");
		return err;
	}
	}
	return 0;

	return err;
}
}


static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
@@ -631,14 +582,17 @@ static void m41t80_remove_sysfs_group(void *_dev)
static int m41t80_probe(struct i2c_client *client,
static int m41t80_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
			const struct i2c_device_id *id)
{
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	int rc = 0;
	int rc = 0;
	struct rtc_device *rtc = NULL;
	struct rtc_device *rtc = NULL;
	struct rtc_time tm;
	struct rtc_time tm;
	struct m41t80_data *clientdata = NULL;
	struct m41t80_data *clientdata = NULL;


	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
				     | I2C_FUNC_SMBUS_BYTE_DATA))
				     I2C_FUNC_SMBUS_BYTE_DATA)) {
		dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
		return -ENODEV;
		return -ENODEV;
	}


	clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
	clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
				GFP_KERNEL);
				GFP_KERNEL);