243 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * rtc-ds1390.c -- driver for the Dallas/Maxim DS1390/93/94 SPI RTC4 *5 * Copyright (C) 2008 Mercury IMC Ltd6 * Written by Mark Jackson <mpfj@mimc.co.uk>7 *8 * NOTE: Currently this driver only supports the bare minimum for read9 * and write the RTC. The extra features provided by the chip family10 * (alarms, trickle charger, different control registers) are unavailable.11 */12 13#include <linux/init.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/rtc.h>17#include <linux/spi/spi.h>18#include <linux/bcd.h>19#include <linux/slab.h>20#include <linux/of.h>21 22#define DS1390_REG_100THS 0x0023#define DS1390_REG_SECONDS 0x0124#define DS1390_REG_MINUTES 0x0225#define DS1390_REG_HOURS 0x0326#define DS1390_REG_DAY 0x0427#define DS1390_REG_DATE 0x0528#define DS1390_REG_MONTH_CENT 0x0629#define DS1390_REG_YEAR 0x0730 31#define DS1390_REG_ALARM_100THS 0x0832#define DS1390_REG_ALARM_SECONDS 0x0933#define DS1390_REG_ALARM_MINUTES 0x0A34#define DS1390_REG_ALARM_HOURS 0x0B35#define DS1390_REG_ALARM_DAY_DATE 0x0C36 37#define DS1390_REG_CONTROL 0x0D38#define DS1390_REG_STATUS 0x0E39#define DS1390_REG_TRICKLE 0x0F40 41#define DS1390_TRICKLE_CHARGER_ENABLE 0xA042#define DS1390_TRICKLE_CHARGER_250_OHM 0x0143#define DS1390_TRICKLE_CHARGER_2K_OHM 0x0244#define DS1390_TRICKLE_CHARGER_4K_OHM 0x0345#define DS1390_TRICKLE_CHARGER_NO_DIODE 0x0446#define DS1390_TRICKLE_CHARGER_DIODE 0x0847 48struct ds1390 {49 struct rtc_device *rtc;50 u8 txrx_buf[9]; /* cmd + 8 registers */51};52 53static void ds1390_set_reg(struct device *dev, unsigned char address,54 unsigned char data)55{56 struct spi_device *spi = to_spi_device(dev);57 unsigned char buf[2];58 59 /* MSB must be '1' to write */60 buf[0] = address | 0x80;61 buf[1] = data;62 63 spi_write(spi, buf, 2);64}65 66static int ds1390_get_reg(struct device *dev, unsigned char address,67 unsigned char *data)68{69 struct spi_device *spi = to_spi_device(dev);70 struct ds1390 *chip = dev_get_drvdata(dev);71 int status;72 73 if (!data)74 return -EINVAL;75 76 /* Clear MSB to indicate read */77 chip->txrx_buf[0] = address & 0x7f;78 /* do the i/o */79 status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 1);80 if (status != 0)81 return status;82 83 *data = chip->txrx_buf[0];84 85 return 0;86}87 88static void ds1390_trickle_of_init(struct spi_device *spi)89{90 u32 ohms = 0;91 u8 value;92 93 if (of_property_read_u32(spi->dev.of_node, "trickle-resistor-ohms",94 &ohms))95 goto out;96 97 /* Enable charger */98 value = DS1390_TRICKLE_CHARGER_ENABLE;99 if (of_property_read_bool(spi->dev.of_node, "trickle-diode-disable"))100 value |= DS1390_TRICKLE_CHARGER_NO_DIODE;101 else102 value |= DS1390_TRICKLE_CHARGER_DIODE;103 104 /* Resistor select */105 switch (ohms) {106 case 250:107 value |= DS1390_TRICKLE_CHARGER_250_OHM;108 break;109 case 2000:110 value |= DS1390_TRICKLE_CHARGER_2K_OHM;111 break;112 case 4000:113 value |= DS1390_TRICKLE_CHARGER_4K_OHM;114 break;115 default:116 dev_warn(&spi->dev,117 "Unsupported ohm value %02ux in dt\n", ohms);118 return;119 }120 121 ds1390_set_reg(&spi->dev, DS1390_REG_TRICKLE, value);122 123out:124 return;125}126 127static int ds1390_read_time(struct device *dev, struct rtc_time *dt)128{129 struct spi_device *spi = to_spi_device(dev);130 struct ds1390 *chip = dev_get_drvdata(dev);131 int status;132 133 /* build the message */134 chip->txrx_buf[0] = DS1390_REG_SECONDS;135 136 /* do the i/o */137 status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8);138 if (status != 0)139 return status;140 141 /* The chip sends data in this order:142 * Seconds, Minutes, Hours, Day, Date, Month / Century, Year */143 dt->tm_sec = bcd2bin(chip->txrx_buf[0]);144 dt->tm_min = bcd2bin(chip->txrx_buf[1]);145 dt->tm_hour = bcd2bin(chip->txrx_buf[2]);146 dt->tm_wday = bcd2bin(chip->txrx_buf[3]);147 dt->tm_mday = bcd2bin(chip->txrx_buf[4]);148 /* mask off century bit */149 dt->tm_mon = bcd2bin(chip->txrx_buf[5] & 0x7f) - 1;150 /* adjust for century bit */151 dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0);152 153 return 0;154}155 156static int ds1390_set_time(struct device *dev, struct rtc_time *dt)157{158 struct spi_device *spi = to_spi_device(dev);159 struct ds1390 *chip = dev_get_drvdata(dev);160 161 /* build the message */162 chip->txrx_buf[0] = DS1390_REG_SECONDS | 0x80;163 chip->txrx_buf[1] = bin2bcd(dt->tm_sec);164 chip->txrx_buf[2] = bin2bcd(dt->tm_min);165 chip->txrx_buf[3] = bin2bcd(dt->tm_hour);166 chip->txrx_buf[4] = bin2bcd(dt->tm_wday);167 chip->txrx_buf[5] = bin2bcd(dt->tm_mday);168 chip->txrx_buf[6] = bin2bcd(dt->tm_mon + 1) |169 ((dt->tm_year > 99) ? 0x80 : 0x00);170 chip->txrx_buf[7] = bin2bcd(dt->tm_year % 100);171 172 /* do the i/o */173 return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0);174}175 176static const struct rtc_class_ops ds1390_rtc_ops = {177 .read_time = ds1390_read_time,178 .set_time = ds1390_set_time,179};180 181static int ds1390_probe(struct spi_device *spi)182{183 unsigned char tmp;184 struct ds1390 *chip;185 int res;186 187 spi->mode = SPI_MODE_3;188 spi->bits_per_word = 8;189 spi_setup(spi);190 191 chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);192 if (!chip)193 return -ENOMEM;194 195 spi_set_drvdata(spi, chip);196 197 res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp);198 if (res != 0) {199 dev_err(&spi->dev, "unable to read device\n");200 return res;201 }202 203 if (spi->dev.of_node)204 ds1390_trickle_of_init(spi);205 206 chip->rtc = devm_rtc_device_register(&spi->dev, "ds1390",207 &ds1390_rtc_ops, THIS_MODULE);208 if (IS_ERR(chip->rtc)) {209 dev_err(&spi->dev, "unable to register device\n");210 res = PTR_ERR(chip->rtc);211 }212 213 return res;214}215 216static const struct of_device_id ds1390_of_match[] __maybe_unused = {217 { .compatible = "dallas,ds1390" },218 {}219};220MODULE_DEVICE_TABLE(of, ds1390_of_match);221 222static const struct spi_device_id ds1390_spi_ids[] = {223 { .name = "ds1390" },224 {}225};226MODULE_DEVICE_TABLE(spi, ds1390_spi_ids);227 228static struct spi_driver ds1390_driver = {229 .driver = {230 .name = "rtc-ds1390",231 .of_match_table = of_match_ptr(ds1390_of_match),232 },233 .probe = ds1390_probe,234 .id_table = ds1390_spi_ids,235};236 237module_spi_driver(ds1390_driver);238 239MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver");240MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>");241MODULE_LICENSE("GPL");242MODULE_ALIAS("spi:rtc-ds1390");243