brintos

brintos / linux-shallow public Read only

0
0
Text · 12.7 KiB · e3dc188 Raw
510 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Seiko Instruments S-35390A RTC Driver4 *5 * Copyright (c) 2007 Byron Bradley6 */7 8#include <linux/module.h>9#include <linux/rtc.h>10#include <linux/i2c.h>11#include <linux/bitrev.h>12#include <linux/bcd.h>13#include <linux/slab.h>14#include <linux/delay.h>15 16#define S35390A_CMD_STATUS1	017#define S35390A_CMD_STATUS2	118#define S35390A_CMD_TIME1	219#define S35390A_CMD_TIME2	320#define S35390A_CMD_INT2_REG1	521 22#define S35390A_BYTE_YEAR	023#define S35390A_BYTE_MONTH	124#define S35390A_BYTE_DAY	225#define S35390A_BYTE_WDAY	326#define S35390A_BYTE_HOURS	427#define S35390A_BYTE_MINS	528#define S35390A_BYTE_SECS	629 30#define S35390A_ALRM_BYTE_WDAY	031#define S35390A_ALRM_BYTE_HOURS	132#define S35390A_ALRM_BYTE_MINS	233 34/* flags for STATUS1 */35#define S35390A_FLAG_POC	BIT(0)36#define S35390A_FLAG_BLD	BIT(1)37#define S35390A_FLAG_INT2	BIT(2)38#define S35390A_FLAG_24H	BIT(6)39#define S35390A_FLAG_RESET	BIT(7)40 41/* flag for STATUS2 */42#define S35390A_FLAG_TEST	BIT(0)43 44/* INT2 pin output mode */45#define S35390A_INT2_MODE_MASK		0x0E46#define S35390A_INT2_MODE_NOINTR	0x0047#define S35390A_INT2_MODE_ALARM		BIT(1) /* INT2AE */48#define S35390A_INT2_MODE_PMIN_EDG	BIT(2) /* INT2ME */49#define S35390A_INT2_MODE_FREQ		BIT(3) /* INT2FE */50#define S35390A_INT2_MODE_PMIN		(BIT(3) | BIT(2)) /* INT2FE | INT2ME */51 52static const struct i2c_device_id s35390a_id[] = {53	{ "s35390a" },54	{ }55};56MODULE_DEVICE_TABLE(i2c, s35390a_id);57 58static const __maybe_unused struct of_device_id s35390a_of_match[] = {59	{ .compatible = "sii,s35390a" },60	{ }61};62MODULE_DEVICE_TABLE(of, s35390a_of_match);63 64struct s35390a {65	struct i2c_client *client[8];66	struct rtc_device *rtc;67	int twentyfourhour;68};69 70static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)71{72	struct i2c_client *client = s35390a->client[reg];73	struct i2c_msg msg[] = {74		{75			.addr = client->addr,76			.len = len,77			.buf = buf78		},79	};80 81	if ((i2c_transfer(client->adapter, msg, 1)) != 1)82		return -EIO;83 84	return 0;85}86 87static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)88{89	struct i2c_client *client = s35390a->client[reg];90	struct i2c_msg msg[] = {91		{92			.addr = client->addr,93			.flags = I2C_M_RD,94			.len = len,95			.buf = buf96		},97	};98 99	if ((i2c_transfer(client->adapter, msg, 1)) != 1)100		return -EIO;101 102	return 0;103}104 105static int s35390a_init(struct s35390a *s35390a)106{107	u8 buf;108	int ret;109	unsigned initcount = 0;110 111	/*112	 * At least one of POC and BLD are set, so reinitialise chip. Keeping113	 * this information in the hardware to know later that the time isn't114	 * valid is unfortunately not possible because POC and BLD are cleared115	 * on read. So the reset is best done now.116	 *117	 * The 24H bit is kept over reset, so set it already here.118	 */119initialize:120	buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;121	ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);122 123	if (ret < 0)124		return ret;125 126	ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);127	if (ret < 0)128		return ret;129 130	if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {131		/* Try up to five times to reset the chip */132		if (initcount < 5) {133			++initcount;134			goto initialize;135		} else136			return -EIO;137	}138 139	return 1;140}141 142/*143 * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.144 * To keep the information if an irq is pending, pass the value read from145 * STATUS1 to the caller.146 */147static int s35390a_read_status(struct s35390a *s35390a, char *status1)148{149	int ret;150 151	ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);152	if (ret < 0)153		return ret;154 155	if (*status1 & S35390A_FLAG_POC) {156		/*157		 * Do not communicate for 0.5 seconds since the power-on158		 * detection circuit is in operation.159		 */160		msleep(500);161		return 1;162	} else if (*status1 & S35390A_FLAG_BLD)163		return 1;164	/*165	 * If both POC and BLD are unset everything is fine.166	 */167	return 0;168}169 170static int s35390a_disable_test_mode(struct s35390a *s35390a)171{172	char buf[1];173 174	if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)) < 0)175		return -EIO;176 177	if (!(buf[0] & S35390A_FLAG_TEST))178		return 0;179 180	buf[0] &= ~S35390A_FLAG_TEST;181	return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf));182}183 184static char s35390a_hr2reg(struct s35390a *s35390a, int hour)185{186	if (s35390a->twentyfourhour)187		return bin2bcd(hour);188 189	if (hour < 12)190		return bin2bcd(hour);191 192	return 0x40 | bin2bcd(hour - 12);193}194 195static int s35390a_reg2hr(struct s35390a *s35390a, char reg)196{197	unsigned hour;198 199	if (s35390a->twentyfourhour)200		return bcd2bin(reg & 0x3f);201 202	hour = bcd2bin(reg & 0x3f);203	if (reg & 0x40)204		hour += 12;205 206	return hour;207}208 209static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)210{211	struct i2c_client *client = to_i2c_client(dev);212	struct s35390a	*s35390a = i2c_get_clientdata(client);213	int i;214	char buf[7], status;215 216	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, "217		"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,218		tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,219		tm->tm_wday);220 221	if (s35390a_read_status(s35390a, &status) == 1)222		s35390a_init(s35390a);223 224	buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100);225	buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1);226	buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday);227	buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday);228	buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour);229	buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min);230	buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec);231 232	/* This chip expects the bits of each byte to be in reverse order */233	for (i = 0; i < 7; ++i)234		buf[i] = bitrev8(buf[i]);235 236	return s35390a_set_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf));237}238 239static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)240{241	struct i2c_client *client = to_i2c_client(dev);242	struct s35390a *s35390a = i2c_get_clientdata(client);243	char buf[7], status;244	int i, err;245 246	if (s35390a_read_status(s35390a, &status) == 1)247		return -EINVAL;248 249	err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf));250	if (err < 0)251		return err;252 253	/* This chip returns the bits of each byte in reverse order */254	for (i = 0; i < 7; ++i)255		buf[i] = bitrev8(buf[i]);256 257	tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]);258	tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]);259	tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]);260	tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]);261	tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]);262	tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1;263	tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100;264 265	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "266		"mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,267		tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,268		tm->tm_wday);269 270	return 0;271}272 273static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)274{275	struct i2c_client *client = to_i2c_client(dev);276	struct s35390a *s35390a = i2c_get_clientdata(client);277	char buf[3], sts = 0;278	int err, i;279 280	dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\281		"mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec,282		alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,283		alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);284 285	/* disable interrupt (which deasserts the irq line) */286	err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));287	if (err < 0)288		return err;289 290	/* clear pending interrupt (in STATUS1 only), if any */291	err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));292	if (err < 0)293		return err;294 295	if (alm->enabled)296		sts = S35390A_INT2_MODE_ALARM;297	else298		sts = S35390A_INT2_MODE_NOINTR;299 300	/* set interupt mode*/301	err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));302	if (err < 0)303		return err;304 305	if (alm->time.tm_wday != -1)306		buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;307	else308		buf[S35390A_ALRM_BYTE_WDAY] = 0;309 310	buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,311			alm->time.tm_hour) | 0x80;312	buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80;313 314	if (alm->time.tm_hour >= 12)315		buf[S35390A_ALRM_BYTE_HOURS] |= 0x40;316 317	for (i = 0; i < 3; ++i)318		buf[i] = bitrev8(buf[i]);319 320	err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf,321								sizeof(buf));322 323	return err;324}325 326static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)327{328	struct i2c_client *client = to_i2c_client(dev);329	struct s35390a *s35390a = i2c_get_clientdata(client);330	char buf[3], sts;331	int i, err;332 333	err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));334	if (err < 0)335		return err;336 337	if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {338		/*339		 * When the alarm isn't enabled, the register to configure340		 * the alarm time isn't accessible.341		 */342		alm->enabled = 0;343		return 0;344	} else {345		alm->enabled = 1;346	}347 348	err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));349	if (err < 0)350		return err;351 352	/* This chip returns the bits of each byte in reverse order */353	for (i = 0; i < 3; ++i)354		buf[i] = bitrev8(buf[i]);355 356	/*357	 * B0 of the three matching registers is an enable flag. Iff it is set358	 * the configured value is used for matching.359	 */360	if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)361		alm->time.tm_wday =362			bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);363 364	if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)365		alm->time.tm_hour =366			s35390a_reg2hr(s35390a,367				       buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);368 369	if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)370		alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);371 372	/* alarm triggers always at s=0 */373	alm->time.tm_sec = 0;374 375	dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",376			__func__, alm->time.tm_min, alm->time.tm_hour,377			alm->time.tm_wday);378 379	return 0;380}381 382static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd,383			     unsigned long arg)384{385	struct i2c_client *client = to_i2c_client(dev);386	struct s35390a *s35390a = i2c_get_clientdata(client);387	char sts;388	int err;389 390	switch (cmd) {391	case RTC_VL_READ:392		/* s35390a_reset set lowvoltage flag and init RTC if needed */393		err = s35390a_read_status(s35390a, &sts);394		if (err < 0)395			return err;396		if (copy_to_user((void __user *)arg, &err, sizeof(int)))397			return -EFAULT;398		break;399	case RTC_VL_CLR:400		/* update flag and clear register */401		err = s35390a_init(s35390a);402		if (err < 0)403			return err;404		break;405	default:406		return -ENOIOCTLCMD;407	}408 409	return 0;410}411 412static const struct rtc_class_ops s35390a_rtc_ops = {413	.read_time	= s35390a_rtc_read_time,414	.set_time	= s35390a_rtc_set_time,415	.set_alarm	= s35390a_rtc_set_alarm,416	.read_alarm	= s35390a_rtc_read_alarm,417	.ioctl          = s35390a_rtc_ioctl,418};419 420static int s35390a_probe(struct i2c_client *client)421{422	int err, err_read;423	unsigned int i;424	struct s35390a *s35390a;425	char buf, status1;426	struct device *dev = &client->dev;427 428	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))429		return -ENODEV;430 431	s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL);432	if (!s35390a)433		return -ENOMEM;434 435	s35390a->client[0] = client;436	i2c_set_clientdata(client, s35390a);437 438	/* This chip uses multiple addresses, use dummy devices for them */439	for (i = 1; i < 8; ++i) {440		s35390a->client[i] = devm_i2c_new_dummy_device(dev,441							       client->adapter,442							       client->addr + i);443		if (IS_ERR(s35390a->client[i])) {444			dev_err(dev, "Address %02x unavailable\n",445				client->addr + i);446			return PTR_ERR(s35390a->client[i]);447		}448	}449 450	s35390a->rtc = devm_rtc_allocate_device(dev);451	if (IS_ERR(s35390a->rtc))452		return PTR_ERR(s35390a->rtc);453 454	err_read = s35390a_read_status(s35390a, &status1);455	if (err_read < 0) {456		dev_err(dev, "error resetting chip\n");457		return err_read;458	}459 460	if (status1 & S35390A_FLAG_24H)461		s35390a->twentyfourhour = 1;462	else463		s35390a->twentyfourhour = 0;464 465	if (status1 & S35390A_FLAG_INT2) {466		/* disable alarm (and maybe test mode) */467		buf = 0;468		err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);469		if (err < 0) {470			dev_err(dev, "error disabling alarm");471			return err;472		}473	} else {474		err = s35390a_disable_test_mode(s35390a);475		if (err < 0) {476			dev_err(dev, "error disabling test mode\n");477			return err;478		}479	}480 481	device_set_wakeup_capable(dev, 1);482 483	s35390a->rtc->ops = &s35390a_rtc_ops;484	s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;485	s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099;486 487	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features);488	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features );489 490	if (status1 & S35390A_FLAG_INT2)491		rtc_update_irq(s35390a->rtc, 1, RTC_AF);492 493	return devm_rtc_register_device(s35390a->rtc);494}495 496static struct i2c_driver s35390a_driver = {497	.driver		= {498		.name	= "rtc-s35390a",499		.of_match_table = of_match_ptr(s35390a_of_match),500	},501	.probe		= s35390a_probe,502	.id_table	= s35390a_id,503};504 505module_i2c_driver(s35390a_driver);506 507MODULE_AUTHOR("Byron Bradley <byron.bbradley@gmail.com>");508MODULE_DESCRIPTION("S35390A RTC driver");509MODULE_LICENSE("GPL");510