1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2f30c2269SUwe Zeisberger /* drivers/rtc/rtc-max6902.c 38e12ecc2SRaphael Assenat * 48e12ecc2SRaphael Assenat * Copyright (C) 2006 8D Technologies inc. 58e12ecc2SRaphael Assenat * Copyright (C) 2004 Compulab Ltd. 68e12ecc2SRaphael Assenat * 78e12ecc2SRaphael Assenat * Driver for MAX6902 spi RTC 88e12ecc2SRaphael Assenat */ 98e12ecc2SRaphael Assenat 108e12ecc2SRaphael Assenat #include <linux/module.h> 118e12ecc2SRaphael Assenat #include <linux/kernel.h> 128e12ecc2SRaphael Assenat #include <linux/platform_device.h> 138e12ecc2SRaphael Assenat #include <linux/init.h> 148e12ecc2SRaphael Assenat #include <linux/rtc.h> 158e12ecc2SRaphael Assenat #include <linux/spi/spi.h> 168e12ecc2SRaphael Assenat #include <linux/bcd.h> 178e12ecc2SRaphael Assenat 188e12ecc2SRaphael Assenat #define MAX6902_REG_SECONDS 0x01 198e12ecc2SRaphael Assenat #define MAX6902_REG_MINUTES 0x03 208e12ecc2SRaphael Assenat #define MAX6902_REG_HOURS 0x05 218e12ecc2SRaphael Assenat #define MAX6902_REG_DATE 0x07 228e12ecc2SRaphael Assenat #define MAX6902_REG_MONTH 0x09 238e12ecc2SRaphael Assenat #define MAX6902_REG_DAY 0x0B 248e12ecc2SRaphael Assenat #define MAX6902_REG_YEAR 0x0D 258e12ecc2SRaphael Assenat #define MAX6902_REG_CONTROL 0x0F 268e12ecc2SRaphael Assenat #define MAX6902_REG_CENTURY 0x13 278e12ecc2SRaphael Assenat 28a5771c6cSAlessandro Zummo static int max6902_set_reg(struct device *dev, unsigned char address, 298e12ecc2SRaphael Assenat unsigned char data) 308e12ecc2SRaphael Assenat { 318e12ecc2SRaphael Assenat struct spi_device *spi = to_spi_device(dev); 328e12ecc2SRaphael Assenat unsigned char buf[2]; 338e12ecc2SRaphael Assenat 348e12ecc2SRaphael Assenat /* MSB must be '0' to write */ 358e12ecc2SRaphael Assenat buf[0] = address & 0x7f; 368e12ecc2SRaphael Assenat buf[1] = data; 378e12ecc2SRaphael Assenat 38a5771c6cSAlessandro Zummo return spi_write_then_read(spi, buf, 2, NULL, 0); 398e12ecc2SRaphael Assenat } 408e12ecc2SRaphael Assenat 418e12ecc2SRaphael Assenat static int max6902_get_reg(struct device *dev, unsigned char address, 428e12ecc2SRaphael Assenat unsigned char *data) 438e12ecc2SRaphael Assenat { 448e12ecc2SRaphael Assenat struct spi_device *spi = to_spi_device(dev); 458e12ecc2SRaphael Assenat 468e12ecc2SRaphael Assenat /* Set MSB to indicate read */ 47a5771c6cSAlessandro Zummo *data = address | 0x80; 488e12ecc2SRaphael Assenat 49a5771c6cSAlessandro Zummo return spi_write_then_read(spi, data, 1, data, 1); 508e12ecc2SRaphael Assenat } 518e12ecc2SRaphael Assenat 52a5771c6cSAlessandro Zummo static int max6902_read_time(struct device *dev, struct rtc_time *dt) 538e12ecc2SRaphael Assenat { 54a5771c6cSAlessandro Zummo int err, century; 558e12ecc2SRaphael Assenat struct spi_device *spi = to_spi_device(dev); 56a5771c6cSAlessandro Zummo unsigned char buf[8]; 578e12ecc2SRaphael Assenat 58a5771c6cSAlessandro Zummo buf[0] = 0xbf; /* Burst read */ 59a5771c6cSAlessandro Zummo 60a5771c6cSAlessandro Zummo err = spi_write_then_read(spi, buf, 1, buf, 8); 61a5771c6cSAlessandro Zummo if (err != 0) 628e12ecc2SRaphael Assenat return err; 638e12ecc2SRaphael Assenat 648e12ecc2SRaphael Assenat /* The chip sends data in this order: 658e12ecc2SRaphael Assenat * Seconds, Minutes, Hours, Date, Month, Day, Year */ 66a5771c6cSAlessandro Zummo dt->tm_sec = bcd2bin(buf[0]); 67a5771c6cSAlessandro Zummo dt->tm_min = bcd2bin(buf[1]); 68a5771c6cSAlessandro Zummo dt->tm_hour = bcd2bin(buf[2]); 69a5771c6cSAlessandro Zummo dt->tm_mday = bcd2bin(buf[3]); 70a5771c6cSAlessandro Zummo dt->tm_mon = bcd2bin(buf[4]) - 1; 71a5771c6cSAlessandro Zummo dt->tm_wday = bcd2bin(buf[5]); 72a5771c6cSAlessandro Zummo dt->tm_year = bcd2bin(buf[6]); 738e12ecc2SRaphael Assenat 74a5771c6cSAlessandro Zummo /* Read century */ 75a5771c6cSAlessandro Zummo err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &buf[0]); 76a5771c6cSAlessandro Zummo if (err != 0) 77a5771c6cSAlessandro Zummo return err; 78a5771c6cSAlessandro Zummo 79a5771c6cSAlessandro Zummo century = bcd2bin(buf[0]) * 100; 808e12ecc2SRaphael Assenat 818e12ecc2SRaphael Assenat dt->tm_year += century; 828e12ecc2SRaphael Assenat dt->tm_year -= 1900; 838e12ecc2SRaphael Assenat 8422652ba7SAlexandre Belloni return 0; 858e12ecc2SRaphael Assenat } 868e12ecc2SRaphael Assenat 87a5771c6cSAlessandro Zummo static int max6902_set_time(struct device *dev, struct rtc_time *dt) 888e12ecc2SRaphael Assenat { 898e12ecc2SRaphael Assenat dt->tm_year = dt->tm_year + 1900; 908e12ecc2SRaphael Assenat 918e12ecc2SRaphael Assenat /* Remove write protection */ 9208348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_CONTROL, 0); 938e12ecc2SRaphael Assenat 9408348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_SECONDS, bin2bcd(dt->tm_sec)); 9508348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_MINUTES, bin2bcd(dt->tm_min)); 9608348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_HOURS, bin2bcd(dt->tm_hour)); 978e12ecc2SRaphael Assenat 9808348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_DATE, bin2bcd(dt->tm_mday)); 9908348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_MONTH, bin2bcd(dt->tm_mon + 1)); 10008348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_DAY, bin2bcd(dt->tm_wday)); 10108348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_YEAR, bin2bcd(dt->tm_year % 100)); 10208348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_CENTURY, bin2bcd(dt->tm_year / 100)); 1038e12ecc2SRaphael Assenat 1048e12ecc2SRaphael Assenat /* Compulab used a delay here. However, the datasheet 1058e12ecc2SRaphael Assenat * does not mention a delay being required anywhere... */ 1068e12ecc2SRaphael Assenat /* delay(2000); */ 1078e12ecc2SRaphael Assenat 1088e12ecc2SRaphael Assenat /* Write protect */ 10908348d2fSAxel Lin max6902_set_reg(dev, MAX6902_REG_CONTROL, 0x80); 1108e12ecc2SRaphael Assenat 1118e12ecc2SRaphael Assenat return 0; 1128e12ecc2SRaphael Assenat } 1138e12ecc2SRaphael Assenat 114ff8371acSDavid Brownell static const struct rtc_class_ops max6902_rtc_ops = { 1158e12ecc2SRaphael Assenat .read_time = max6902_read_time, 1168e12ecc2SRaphael Assenat .set_time = max6902_set_time, 1178e12ecc2SRaphael Assenat }; 1188e12ecc2SRaphael Assenat 1195a167f45SGreg Kroah-Hartman static int max6902_probe(struct spi_device *spi) 1208e12ecc2SRaphael Assenat { 1218e12ecc2SRaphael Assenat struct rtc_device *rtc; 1228e12ecc2SRaphael Assenat unsigned char tmp; 1238e12ecc2SRaphael Assenat int res; 1248e12ecc2SRaphael Assenat 125a5771c6cSAlessandro Zummo spi->mode = SPI_MODE_3; 126a5771c6cSAlessandro Zummo spi->bits_per_word = 8; 127a5771c6cSAlessandro Zummo spi_setup(spi); 128a5771c6cSAlessandro Zummo 129a5771c6cSAlessandro Zummo res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp); 130a5771c6cSAlessandro Zummo if (res != 0) 131a5771c6cSAlessandro Zummo return res; 132a5771c6cSAlessandro Zummo 13304353a73SJingoo Han rtc = devm_rtc_device_register(&spi->dev, "max6902", 13404353a73SJingoo Han &max6902_rtc_ops, THIS_MODULE); 1358e12ecc2SRaphael Assenat if (IS_ERR(rtc)) 1368e12ecc2SRaphael Assenat return PTR_ERR(rtc); 1378e12ecc2SRaphael Assenat 138a5ef73f0SJingoo Han spi_set_drvdata(spi, rtc); 1398e12ecc2SRaphael Assenat return 0; 1408e12ecc2SRaphael Assenat } 1418e12ecc2SRaphael Assenat 1428e12ecc2SRaphael Assenat static struct spi_driver max6902_driver = { 1438e12ecc2SRaphael Assenat .driver = { 1445c076fceSDavid Brownell .name = "rtc-max6902", 1458e12ecc2SRaphael Assenat }, 1468e12ecc2SRaphael Assenat .probe = max6902_probe, 1478e12ecc2SRaphael Assenat }; 1488e12ecc2SRaphael Assenat 149109e9418SAxel Lin module_spi_driver(max6902_driver); 1508e12ecc2SRaphael Assenat 1518e12ecc2SRaphael Assenat MODULE_DESCRIPTION("max6902 spi RTC driver"); 1528e12ecc2SRaphael Assenat MODULE_AUTHOR("Raphael Assenat"); 1538e12ecc2SRaphael Assenat MODULE_LICENSE("GPL"); 154e0626e38SAnton Vorontsov MODULE_ALIAS("spi:rtc-max6902"); 155