brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 6e53142 Raw
161 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * An rtc/i2c driver for the Dallas DS16724 * Copyright 2005-06 Tower Technologies5 *6 * Author: Alessandro Zummo <a.zummo@towertech.it>7 */8 9#include <linux/i2c.h>10#include <linux/rtc.h>11#include <linux/module.h>12 13/* Registers */14 15#define DS1672_REG_CNT_BASE	016#define DS1672_REG_CONTROL	417#define DS1672_REG_TRICKLE	518 19#define DS1672_REG_CONTROL_EOSC	0x8020 21/*22 * In the routines that deal directly with the ds1672 hardware, we use23 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch24 * Time is set to UTC.25 */26static int ds1672_read_time(struct device *dev, struct rtc_time *tm)27{28	struct i2c_client *client = to_i2c_client(dev);29	unsigned long time;30	unsigned char addr = DS1672_REG_CONTROL;31	unsigned char buf[4];32 33	struct i2c_msg msgs[] = {34		{/* setup read ptr */35			.addr = client->addr,36			.len = 1,37			.buf = &addr38		},39		{/* read date */40			.addr = client->addr,41			.flags = I2C_M_RD,42			.len = 1,43			.buf = buf44		},45	};46 47	/* read control register */48	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {49		dev_warn(&client->dev, "Unable to read the control register\n");50		return -EIO;51	}52 53	if (buf[0] & DS1672_REG_CONTROL_EOSC) {54		dev_warn(&client->dev, "Oscillator not enabled. Set time to enable.\n");55		return -EINVAL;56	}57 58	addr = DS1672_REG_CNT_BASE;59	msgs[1].len = 4;60 61	/* read date registers */62	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {63		dev_err(&client->dev, "%s: read error\n", __func__);64		return -EIO;65	}66 67	dev_dbg(&client->dev,68		"%s: raw read data - counters=%02x,%02x,%02x,%02x\n",69		__func__, buf[0], buf[1], buf[2], buf[3]);70 71	time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) |72	       (buf[1] << 8) | buf[0];73 74	rtc_time64_to_tm(time, tm);75 76	dev_dbg(&client->dev, "%s: tm is %ptR\n", __func__, tm);77 78	return 0;79}80 81static int ds1672_set_time(struct device *dev, struct rtc_time *tm)82{83	struct i2c_client *client = to_i2c_client(dev);84	int xfer;85	unsigned char buf[6];86	unsigned long secs = rtc_tm_to_time64(tm);87 88	buf[0] = DS1672_REG_CNT_BASE;89	buf[1] = secs & 0x000000FF;90	buf[2] = (secs & 0x0000FF00) >> 8;91	buf[3] = (secs & 0x00FF0000) >> 16;92	buf[4] = (secs & 0xFF000000) >> 24;93	buf[5] = 0;		/* set control reg to enable counting */94 95	xfer = i2c_master_send(client, buf, 6);96	if (xfer != 6) {97		dev_err(&client->dev, "%s: send: %d\n", __func__, xfer);98		return -EIO;99	}100 101	return 0;102}103 104static const struct rtc_class_ops ds1672_rtc_ops = {105	.read_time = ds1672_read_time,106	.set_time = ds1672_set_time,107};108 109static int ds1672_probe(struct i2c_client *client)110{111	int err = 0;112	struct rtc_device *rtc;113 114	dev_dbg(&client->dev, "%s\n", __func__);115 116	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))117		return -ENODEV;118 119	rtc = devm_rtc_allocate_device(&client->dev);120	if (IS_ERR(rtc))121		return PTR_ERR(rtc);122 123	rtc->ops = &ds1672_rtc_ops;124	rtc->range_max = U32_MAX;125 126	err = devm_rtc_register_device(rtc);127	if (err)128		return err;129 130	i2c_set_clientdata(client, rtc);131 132	return 0;133}134 135static const struct i2c_device_id ds1672_id[] = {136	{ "ds1672" },137	{ }138};139MODULE_DEVICE_TABLE(i2c, ds1672_id);140 141static const __maybe_unused struct of_device_id ds1672_of_match[] = {142	{ .compatible = "dallas,ds1672" },143	{ }144};145MODULE_DEVICE_TABLE(of, ds1672_of_match);146 147static struct i2c_driver ds1672_driver = {148	.driver = {149		   .name = "rtc-ds1672",150		   .of_match_table = of_match_ptr(ds1672_of_match),151	},152	.probe = ds1672_probe,153	.id_table = ds1672_id,154};155 156module_i2c_driver(ds1672_driver);157 158MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");159MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver");160MODULE_LICENSE("GPL");161