brintos

brintos / linux-shallow public Read only

0
0
Text · 15.1 KiB · f82728e Raw
530 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip.4 *5 *  Copyright (C) 2008 Sergey Lapin6 *  Based on ds1307 driver by James Chapman and David Brownell7 */8 9#include <linux/module.h>10#include <linux/i2c.h>11#include <linux/rtc.h>12#include <linux/bcd.h>13#include <linux/slab.h>14 15#define FM3130_RTC_CONTROL	(0x0)16#define FM3130_CAL_CONTROL	(0x1)17#define FM3130_RTC_SECONDS	(0x2)18#define FM3130_RTC_MINUTES	(0x3)19#define FM3130_RTC_HOURS	(0x4)20#define FM3130_RTC_DAY		(0x5)21#define FM3130_RTC_DATE		(0x6)22#define FM3130_RTC_MONTHS	(0x7)23#define FM3130_RTC_YEARS	(0x8)24 25#define FM3130_ALARM_SECONDS	(0x9)26#define FM3130_ALARM_MINUTES	(0xa)27#define FM3130_ALARM_HOURS	(0xb)28#define FM3130_ALARM_DATE	(0xc)29#define FM3130_ALARM_MONTHS	(0xd)30#define FM3130_ALARM_WP_CONTROL	(0xe)31 32#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */33#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */34#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */35#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */36#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */37#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */38#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */39#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */40#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */41 42#define FM3130_CLOCK_REGS 743#define FM3130_ALARM_REGS 544 45struct fm3130 {46	u8			reg_addr_time;47	u8			reg_addr_alarm;48	u8			regs[15];49	struct i2c_msg		msg[4];50	struct i2c_client	*client;51	struct rtc_device	*rtc;52	int			alarm_valid;53	int			data_valid;54};55static const struct i2c_device_id fm3130_id[] = {56	{ "fm3130" },57	{ }58};59MODULE_DEVICE_TABLE(i2c, fm3130_id);60 61#define FM3130_MODE_NORMAL		062#define FM3130_MODE_WRITE		163#define FM3130_MODE_READ		264 65static void fm3130_rtc_mode(struct device *dev, int mode)66{67	struct fm3130 *fm3130 = dev_get_drvdata(dev);68 69	fm3130->regs[FM3130_RTC_CONTROL] =70		i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);71	switch (mode) {72	case FM3130_MODE_NORMAL:73		fm3130->regs[FM3130_RTC_CONTROL] &=74			~(FM3130_RTC_CONTROL_BIT_WRITE |75			FM3130_RTC_CONTROL_BIT_READ);76		break;77	case FM3130_MODE_WRITE:78		fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE;79		break;80	case FM3130_MODE_READ:81		fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ;82		break;83	default:84		dev_dbg(dev, "invalid mode %d\n", mode);85		break;86	}87 88	i2c_smbus_write_byte_data(fm3130->client,89		 FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]);90}91 92static int fm3130_get_time(struct device *dev, struct rtc_time *t)93{94	struct fm3130 *fm3130 = dev_get_drvdata(dev);95	int		tmp;96 97	if (!fm3130->data_valid) {98		/* We have invalid data in RTC, probably due99		to battery faults or other problems. Return EIO100		for now, it will allow us to set data later instead101		of error during probing which disables device */102		return -EIO;103	}104	fm3130_rtc_mode(dev, FM3130_MODE_READ);105 106	/* read the RTC date and time registers all at once */107	tmp = i2c_transfer(fm3130->client->adapter, fm3130->msg, 2);108	if (tmp != 2) {109		dev_err(dev, "%s error %d\n", "read", tmp);110		return -EIO;111	}112 113	fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);114 115	dev_dbg(dev, "%s: %15ph\n", "read", fm3130->regs);116 117	t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);118	t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);119	tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;120	t->tm_hour = bcd2bin(tmp);121	t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;122	t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);123	tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;124	t->tm_mon = bcd2bin(tmp) - 1;125 126	/* assume 20YY not 19YY, and ignore CF bit */127	t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;128 129	dev_dbg(dev, "%s secs=%d, mins=%d, "130		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",131		"read", t->tm_sec, t->tm_min,132		t->tm_hour, t->tm_mday,133		t->tm_mon, t->tm_year, t->tm_wday);134 135	return 0;136}137 138 139static int fm3130_set_time(struct device *dev, struct rtc_time *t)140{141	struct fm3130 *fm3130 = dev_get_drvdata(dev);142	int		tmp, i;143	u8		*buf = fm3130->regs;144 145	dev_dbg(dev, "%s secs=%d, mins=%d, "146		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",147		"write", t->tm_sec, t->tm_min,148		t->tm_hour, t->tm_mday,149		t->tm_mon, t->tm_year, t->tm_wday);150 151	/* first register addr */152	buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);153	buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);154	buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);155	buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);156	buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);157	buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);158 159	/* assume 20YY not 19YY */160	tmp = t->tm_year - 100;161	buf[FM3130_RTC_YEARS] = bin2bcd(tmp);162 163	dev_dbg(dev, "%s: %15ph\n", "write", buf);164 165	fm3130_rtc_mode(dev, FM3130_MODE_WRITE);166 167	/* Writing time registers, we don't support multibyte transfers */168	for (i = 0; i < FM3130_CLOCK_REGS; i++) {169		i2c_smbus_write_byte_data(fm3130->client,170					FM3130_RTC_SECONDS + i,171					fm3130->regs[FM3130_RTC_SECONDS + i]);172	}173 174	fm3130_rtc_mode(dev, FM3130_MODE_NORMAL);175 176	/* We assume here that data are valid once written */177	if (!fm3130->data_valid)178		fm3130->data_valid = 1;179	return 0;180}181 182static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)183{184	struct fm3130 *fm3130 = dev_get_drvdata(dev);185	int tmp;186	struct rtc_time *tm = &alrm->time;187 188	if (!fm3130->alarm_valid) {189		/*190		 * We have invalid alarm in RTC, probably due to battery faults191		 * or other problems. Return EIO for now, it will allow us to192		 * set alarm value later instead of error during probing which193		 * disables device194		 */195		return -EIO;196	}197 198	/* read the RTC alarm registers all at once */199	tmp = i2c_transfer(fm3130->client->adapter, &fm3130->msg[2], 2);200	if (tmp != 2) {201		dev_err(dev, "%s error %d\n", "read", tmp);202		return -EIO;203	}204	dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n",205			fm3130->regs[FM3130_ALARM_SECONDS],206			fm3130->regs[FM3130_ALARM_MINUTES],207			fm3130->regs[FM3130_ALARM_HOURS],208			fm3130->regs[FM3130_ALARM_DATE],209			fm3130->regs[FM3130_ALARM_MONTHS]);210 211	tm->tm_sec	= bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);212	tm->tm_min	= bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);213	tm->tm_hour	= bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);214	tm->tm_mday	= bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);215	tm->tm_mon	= bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);216 217	if (tm->tm_mon > 0)218		tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */219 220	dev_dbg(dev, "%s secs=%d, mins=%d, "221		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",222		"read alarm", tm->tm_sec, tm->tm_min,223		tm->tm_hour, tm->tm_mday,224		tm->tm_mon, tm->tm_year, tm->tm_wday);225 226	/* check if alarm enabled */227	fm3130->regs[FM3130_RTC_CONTROL] =228		i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);229 230	if ((fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AEN) &&231		(~fm3130->regs[FM3130_RTC_CONTROL] &232			FM3130_RTC_CONTROL_BIT_CAL)) {233		alrm->enabled = 1;234	}235 236	return 0;237}238 239static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)240{241	struct fm3130 *fm3130 = dev_get_drvdata(dev);242	struct rtc_time *tm = &alrm->time;243	int i;244 245	dev_dbg(dev, "%s secs=%d, mins=%d, "246		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",247		"write alarm", tm->tm_sec, tm->tm_min,248		tm->tm_hour, tm->tm_mday,249		tm->tm_mon, tm->tm_year, tm->tm_wday);250 251	fm3130->regs[FM3130_ALARM_SECONDS] =252		(tm->tm_sec != -1) ? bin2bcd(tm->tm_sec) : 0x80;253 254	fm3130->regs[FM3130_ALARM_MINUTES] =255		(tm->tm_min != -1) ? bin2bcd(tm->tm_min) : 0x80;256 257	fm3130->regs[FM3130_ALARM_HOURS] =258		(tm->tm_hour != -1) ? bin2bcd(tm->tm_hour) : 0x80;259 260	fm3130->regs[FM3130_ALARM_DATE] =261		(tm->tm_mday != -1) ? bin2bcd(tm->tm_mday) : 0x80;262 263	fm3130->regs[FM3130_ALARM_MONTHS] =264		(tm->tm_mon != -1) ? bin2bcd(tm->tm_mon + 1) : 0x80;265 266	dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",267			fm3130->regs[FM3130_ALARM_SECONDS],268			fm3130->regs[FM3130_ALARM_MINUTES],269			fm3130->regs[FM3130_ALARM_HOURS],270			fm3130->regs[FM3130_ALARM_DATE],271			fm3130->regs[FM3130_ALARM_MONTHS]);272	/* Writing time registers, we don't support multibyte transfers */273	for (i = 0; i < FM3130_ALARM_REGS; i++) {274		i2c_smbus_write_byte_data(fm3130->client,275					FM3130_ALARM_SECONDS + i,276					fm3130->regs[FM3130_ALARM_SECONDS + i]);277	}278	fm3130->regs[FM3130_RTC_CONTROL] =279		i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);280 281	/* enable or disable alarm */282	if (alrm->enabled) {283		i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,284			(fm3130->regs[FM3130_RTC_CONTROL] &285				~(FM3130_RTC_CONTROL_BIT_CAL)) |286					FM3130_RTC_CONTROL_BIT_AEN);287	} else {288		i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL,289			fm3130->regs[FM3130_RTC_CONTROL] &290				~(FM3130_RTC_CONTROL_BIT_CAL) &291					~(FM3130_RTC_CONTROL_BIT_AEN));292	}293 294	/* We assume here that data is valid once written */295	if (!fm3130->alarm_valid)296		fm3130->alarm_valid = 1;297 298	return 0;299}300 301static int fm3130_alarm_irq_enable(struct device *dev, unsigned int enabled)302{303	struct fm3130 *fm3130 = dev_get_drvdata(dev);304	int ret = 0;305 306	fm3130->regs[FM3130_RTC_CONTROL] =307		i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL);308 309	dev_dbg(dev, "alarm_irq_enable: enable=%d, FM3130_RTC_CONTROL=%02x\n",310		enabled, fm3130->regs[FM3130_RTC_CONTROL]);311 312	switch (enabled) {313	case 0:		/* alarm off */314		ret = i2c_smbus_write_byte_data(fm3130->client,315			FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL] &316				~(FM3130_RTC_CONTROL_BIT_CAL) &317					~(FM3130_RTC_CONTROL_BIT_AEN));318		break;319	case 1:		/* alarm on */320		ret = i2c_smbus_write_byte_data(fm3130->client,321			FM3130_RTC_CONTROL, (fm3130->regs[FM3130_RTC_CONTROL] &322				~(FM3130_RTC_CONTROL_BIT_CAL)) |323					FM3130_RTC_CONTROL_BIT_AEN);324		break;325	default:326		ret = -EINVAL;327		break;328	}329 330	return ret;331}332 333static const struct rtc_class_ops fm3130_rtc_ops = {334	.read_time	= fm3130_get_time,335	.set_time	= fm3130_set_time,336	.read_alarm	= fm3130_read_alarm,337	.set_alarm	= fm3130_set_alarm,338	.alarm_irq_enable = fm3130_alarm_irq_enable,339};340 341static struct i2c_driver fm3130_driver;342 343static int fm3130_probe(struct i2c_client *client)344{345	struct fm3130		*fm3130;346	int			err = -ENODEV;347	int			tmp;348	struct i2c_adapter	*adapter = client->adapter;349 350	if (!i2c_check_functionality(adapter,351			I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))352		return -EIO;353 354	fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);355 356	if (!fm3130)357		return -ENOMEM;358 359	fm3130->client = client;360	i2c_set_clientdata(client, fm3130);361	fm3130->reg_addr_time = FM3130_RTC_SECONDS;362	fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;363 364	/* Messages to read time */365	fm3130->msg[0].addr = client->addr;366	fm3130->msg[0].flags = 0;367	fm3130->msg[0].len = 1;368	fm3130->msg[0].buf = &fm3130->reg_addr_time;369 370	fm3130->msg[1].addr = client->addr;371	fm3130->msg[1].flags = I2C_M_RD;372	fm3130->msg[1].len = FM3130_CLOCK_REGS;373	fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];374 375	/* Messages to read alarm */376	fm3130->msg[2].addr = client->addr;377	fm3130->msg[2].flags = 0;378	fm3130->msg[2].len = 1;379	fm3130->msg[2].buf = &fm3130->reg_addr_alarm;380 381	fm3130->msg[3].addr = client->addr;382	fm3130->msg[3].flags = I2C_M_RD;383	fm3130->msg[3].len = FM3130_ALARM_REGS;384	fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];385 386	fm3130->alarm_valid = 0;387	fm3130->data_valid = 0;388 389	tmp = i2c_transfer(adapter, fm3130->msg, 4);390	if (tmp != 4) {391		dev_dbg(&client->dev, "read error %d\n", tmp);392		err = -EIO;393		goto exit_free;394	}395 396	fm3130->regs[FM3130_RTC_CONTROL] =397		i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);398	fm3130->regs[FM3130_CAL_CONTROL] =399		i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);400 401	/* Disabling calibration mode */402	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {403		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,404			fm3130->regs[FM3130_RTC_CONTROL] &405				~(FM3130_RTC_CONTROL_BIT_CAL));406		dev_warn(&client->dev, "Disabling calibration mode!\n");407	}408 409	/* Disabling read and write modes */410	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||411	    fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {412		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,413			fm3130->regs[FM3130_RTC_CONTROL] &414				~(FM3130_RTC_CONTROL_BIT_READ |415					FM3130_RTC_CONTROL_BIT_WRITE));416		dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");417	}418 419	/* oscillator off?  turn it on, so clock can tick. */420	if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)421		i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,422			fm3130->regs[FM3130_CAL_CONTROL] &423				~(FM3130_CAL_CONTROL_BIT_nOSCEN));424 425	/* low battery?  clear flag, and warn */426	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {427		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,428			fm3130->regs[FM3130_RTC_CONTROL] &429				~(FM3130_RTC_CONTROL_BIT_LB));430		dev_warn(&client->dev, "Low battery!\n");431	}432 433	/* check if Power On Reset bit is set */434	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {435		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,436			fm3130->regs[FM3130_RTC_CONTROL] &437				~FM3130_RTC_CONTROL_BIT_POR);438		dev_dbg(&client->dev, "POR bit is set\n");439	}440	/* ACS is controlled by alarm */441	i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);442 443	/* alarm registers sanity check */444	tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);445	if (tmp > 59)446		goto bad_alarm;447 448	tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);449	if (tmp > 59)450		goto bad_alarm;451 452	tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);453	if (tmp > 23)454		goto bad_alarm;455 456	tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);457	if (tmp == 0 || tmp > 31)458		goto bad_alarm;459 460	tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);461	if (tmp == 0 || tmp > 12)462		goto bad_alarm;463 464	fm3130->alarm_valid = 1;465 466bad_alarm:467 468	/* clock registers sanity chek */469	tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);470	if (tmp > 59)471		goto bad_clock;472 473	tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);474	if (tmp > 59)475		goto bad_clock;476 477	tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);478	if (tmp > 23)479		goto bad_clock;480 481	tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);482	if (tmp == 0 || tmp > 7)483		goto bad_clock;484 485	tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);486	if (tmp == 0 || tmp > 31)487		goto bad_clock;488 489	tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);490	if (tmp == 0 || tmp > 12)491		goto bad_clock;492 493	fm3130->data_valid = 1;494 495bad_clock:496 497	if (!fm3130->data_valid || !fm3130->alarm_valid)498		dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",499			fm3130->regs);500 501	/* We won't bail out here because we just got invalid data.502	   Time setting from u-boot doesn't work anyway */503	fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,504				&fm3130_rtc_ops, THIS_MODULE);505	if (IS_ERR(fm3130->rtc)) {506		err = PTR_ERR(fm3130->rtc);507		dev_err(&client->dev,508			"unable to register the class device\n");509		goto exit_free;510	}511	return 0;512exit_free:513	return err;514}515 516static struct i2c_driver fm3130_driver = {517	.driver = {518		.name	= "rtc-fm3130",519	},520	.probe		= fm3130_probe,521	.id_table	= fm3130_id,522};523 524module_i2c_driver(fm3130_driver);525 526MODULE_DESCRIPTION("RTC driver for FM3130");527MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>");528MODULE_LICENSE("GPL");529 530