169468320SAlexandre Belloni // SPDX-License-Identifier: GPL-2.0 2edf1aaa3SAlessandro Zummo /* 3edf1aaa3SAlessandro Zummo * An rtc/i2c driver for the Dallas DS1672 43903586aSAlessandro Zummo * Copyright 2005-06 Tower Technologies 53903586aSAlessandro Zummo * 63903586aSAlessandro Zummo * Author: Alessandro Zummo <a.zummo@towertech.it> 7edf1aaa3SAlessandro Zummo */ 8edf1aaa3SAlessandro Zummo 9edf1aaa3SAlessandro Zummo #include <linux/i2c.h> 10edf1aaa3SAlessandro Zummo #include <linux/rtc.h> 112113852bSPaul Gortmaker #include <linux/module.h> 12edf1aaa3SAlessandro Zummo 13edf1aaa3SAlessandro Zummo /* Registers */ 14edf1aaa3SAlessandro Zummo 15edf1aaa3SAlessandro Zummo #define DS1672_REG_CNT_BASE 0 16edf1aaa3SAlessandro Zummo #define DS1672_REG_CONTROL 4 17edf1aaa3SAlessandro Zummo #define DS1672_REG_TRICKLE 5 18edf1aaa3SAlessandro Zummo 193903586aSAlessandro Zummo #define DS1672_REG_CONTROL_EOSC 0x80 20edf1aaa3SAlessandro Zummo 21edf1aaa3SAlessandro Zummo /* 22edf1aaa3SAlessandro Zummo * In the routines that deal directly with the ds1672 hardware, we use 23edf1aaa3SAlessandro Zummo * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch 24d1fbe695SAlexandre Belloni * Time is set to UTC. 25edf1aaa3SAlessandro Zummo */ 267a5670c7SAlexandre Belloni static int ds1672_read_time(struct device *dev, struct rtc_time *tm) 27edf1aaa3SAlessandro Zummo { 287a5670c7SAlexandre Belloni struct i2c_client *client = to_i2c_client(dev); 29edf1aaa3SAlessandro Zummo unsigned long time; 3010e3efc1SAlexandre Belloni unsigned char addr = DS1672_REG_CONTROL; 31edf1aaa3SAlessandro Zummo unsigned char buf[4]; 32edf1aaa3SAlessandro Zummo 33edf1aaa3SAlessandro Zummo struct i2c_msg msgs[] = { 342bfc37dfSShubhrajyoti D {/* setup read ptr */ 352bfc37dfSShubhrajyoti D .addr = client->addr, 362bfc37dfSShubhrajyoti D .len = 1, 372bfc37dfSShubhrajyoti D .buf = &addr 382bfc37dfSShubhrajyoti D }, 392bfc37dfSShubhrajyoti D {/* read date */ 402bfc37dfSShubhrajyoti D .addr = client->addr, 412bfc37dfSShubhrajyoti D .flags = I2C_M_RD, 4210e3efc1SAlexandre Belloni .len = 1, 432bfc37dfSShubhrajyoti D .buf = buf 442bfc37dfSShubhrajyoti D }, 45edf1aaa3SAlessandro Zummo }; 46edf1aaa3SAlessandro Zummo 4710e3efc1SAlexandre Belloni /* read control register */ 4810e3efc1SAlexandre Belloni if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { 4910e3efc1SAlexandre Belloni dev_warn(&client->dev, "Unable to read the control register\n"); 5010e3efc1SAlexandre Belloni return -EIO; 5110e3efc1SAlexandre Belloni } 5210e3efc1SAlexandre Belloni 5310e3efc1SAlexandre Belloni if (buf[0] & DS1672_REG_CONTROL_EOSC) { 5410e3efc1SAlexandre Belloni dev_warn(&client->dev, "Oscillator not enabled. Set time to enable.\n"); 5510e3efc1SAlexandre Belloni return -EINVAL; 5610e3efc1SAlexandre Belloni } 5710e3efc1SAlexandre Belloni 5810e3efc1SAlexandre Belloni addr = DS1672_REG_CNT_BASE; 5910e3efc1SAlexandre Belloni msgs[1].len = 4; 6010e3efc1SAlexandre Belloni 61edf1aaa3SAlessandro Zummo /* read date registers */ 62edf1aaa3SAlessandro Zummo if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { 632a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: read error\n", __func__); 64edf1aaa3SAlessandro Zummo return -EIO; 65edf1aaa3SAlessandro Zummo } 66edf1aaa3SAlessandro Zummo 67edf1aaa3SAlessandro Zummo dev_dbg(&client->dev, 6811966adcSJeff Garzik "%s: raw read data - counters=%02x,%02x,%02x,%02x\n", 692a4e2b87SHarvey Harrison __func__, buf[0], buf[1], buf[2], buf[3]); 70edf1aaa3SAlessandro Zummo 71f0c04c27SColin Ian King time = ((unsigned long)buf[3] << 24) | (buf[2] << 16) | 72f0c04c27SColin Ian King (buf[1] << 8) | buf[0]; 73edf1aaa3SAlessandro Zummo 74520d6516SAlexandre Belloni rtc_time64_to_tm(time, tm); 75edf1aaa3SAlessandro Zummo 76e3a76913SAlexandre Belloni dev_dbg(&client->dev, "%s: tm is %ptR\n", __func__, tm); 77edf1aaa3SAlessandro Zummo 78edf1aaa3SAlessandro Zummo return 0; 79edf1aaa3SAlessandro Zummo } 80edf1aaa3SAlessandro Zummo 81219219d9SAlexandre Belloni static int ds1672_set_time(struct device *dev, struct rtc_time *tm) 82edf1aaa3SAlessandro Zummo { 837a5670c7SAlexandre Belloni struct i2c_client *client = to_i2c_client(dev); 84edf1aaa3SAlessandro Zummo int xfer; 858a95b252SKumar Gala unsigned char buf[6]; 86219219d9SAlexandre Belloni unsigned long secs = rtc_tm_to_time64(tm); 87edf1aaa3SAlessandro Zummo 88edf1aaa3SAlessandro Zummo buf[0] = DS1672_REG_CNT_BASE; 89edf1aaa3SAlessandro Zummo buf[1] = secs & 0x000000FF; 90edf1aaa3SAlessandro Zummo buf[2] = (secs & 0x0000FF00) >> 8; 91edf1aaa3SAlessandro Zummo buf[3] = (secs & 0x00FF0000) >> 16; 92edf1aaa3SAlessandro Zummo buf[4] = (secs & 0xFF000000) >> 24; 938a95b252SKumar Gala buf[5] = 0; /* set control reg to enable counting */ 94edf1aaa3SAlessandro Zummo 958a95b252SKumar Gala xfer = i2c_master_send(client, buf, 6); 968a95b252SKumar Gala if (xfer != 6) { 972a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: send: %d\n", __func__, xfer); 98edf1aaa3SAlessandro Zummo return -EIO; 99edf1aaa3SAlessandro Zummo } 100edf1aaa3SAlessandro Zummo 101edf1aaa3SAlessandro Zummo return 0; 102edf1aaa3SAlessandro Zummo } 103edf1aaa3SAlessandro Zummo 104ff8371acSDavid Brownell static const struct rtc_class_ops ds1672_rtc_ops = { 1057a5670c7SAlexandre Belloni .read_time = ds1672_read_time, 106219219d9SAlexandre Belloni .set_time = ds1672_set_time, 107edf1aaa3SAlessandro Zummo }; 108edf1aaa3SAlessandro Zummo 1093f4a3322SStephen Kitt static int ds1672_probe(struct i2c_client *client) 110edf1aaa3SAlessandro Zummo { 111edf1aaa3SAlessandro Zummo int err = 0; 112edf1aaa3SAlessandro Zummo struct rtc_device *rtc; 113edf1aaa3SAlessandro Zummo 1141716b0feSAlessandro Zummo dev_dbg(&client->dev, "%s\n", __func__); 115edf1aaa3SAlessandro Zummo 1161716b0feSAlessandro Zummo if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 1171716b0feSAlessandro Zummo return -ENODEV; 118edf1aaa3SAlessandro Zummo 119d1fbe695SAlexandre Belloni rtc = devm_rtc_allocate_device(&client->dev); 120d1fbe695SAlexandre Belloni if (IS_ERR(rtc)) 121d1fbe695SAlexandre Belloni return PTR_ERR(rtc); 122d1fbe695SAlexandre Belloni 123d1fbe695SAlexandre Belloni rtc->ops = &ds1672_rtc_ops; 124d1fbe695SAlexandre Belloni rtc->range_max = U32_MAX; 125d1fbe695SAlexandre Belloni 126fdcfd854SBartosz Golaszewski err = devm_rtc_register_device(rtc); 127d1fbe695SAlexandre Belloni if (err) 128d1fbe695SAlexandre Belloni return err; 129edf1aaa3SAlessandro Zummo 130edf1aaa3SAlessandro Zummo i2c_set_clientdata(client, rtc); 131edf1aaa3SAlessandro Zummo 132edf1aaa3SAlessandro Zummo return 0; 133edf1aaa3SAlessandro Zummo } 134edf1aaa3SAlessandro Zummo 13545a63518SArvind Yadav static const struct i2c_device_id ds1672_id[] = { 136fe102c71SAlessandro Zummo { "ds1672", 0 }, 137fe102c71SAlessandro Zummo { } 138fe102c71SAlessandro Zummo }; 1398ad0f5b6SAxel Lin MODULE_DEVICE_TABLE(i2c, ds1672_id); 140fe102c71SAlessandro Zummo 141fb38b5daSAlexandre Belloni static const __maybe_unused struct of_device_id ds1672_of_match[] = { 14223194ac0SJavier Martinez Canillas { .compatible = "dallas,ds1672" }, 14323194ac0SJavier Martinez Canillas { } 14423194ac0SJavier Martinez Canillas }; 14523194ac0SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, ds1672_of_match); 14623194ac0SJavier Martinez Canillas 1471716b0feSAlessandro Zummo static struct i2c_driver ds1672_driver = { 1481716b0feSAlessandro Zummo .driver = { 1491716b0feSAlessandro Zummo .name = "rtc-ds1672", 15023194ac0SJavier Martinez Canillas .of_match_table = of_match_ptr(ds1672_of_match), 1511716b0feSAlessandro Zummo }, 152*31b0cecbSUwe Kleine-König .probe = ds1672_probe, 153fe102c71SAlessandro Zummo .id_table = ds1672_id, 1541716b0feSAlessandro Zummo }; 1551716b0feSAlessandro Zummo 1560abc9201SAxel Lin module_i2c_driver(ds1672_driver); 157edf1aaa3SAlessandro Zummo 158edf1aaa3SAlessandro Zummo MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 159edf1aaa3SAlessandro Zummo MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); 160edf1aaa3SAlessandro Zummo MODULE_LICENSE("GPL"); 161