1e6e7376cSAlexandre Belloni // SPDX-License-Identifier: GPL-2.0 2e6e7376cSAlexandre Belloni /* 3e6e7376cSAlexandre Belloni * RTC driver for the Micro Crystal RV3028 4e6e7376cSAlexandre Belloni * 5e6e7376cSAlexandre Belloni * Copyright (C) 2019 Micro Crystal SA 6e6e7376cSAlexandre Belloni * 7e6e7376cSAlexandre Belloni * Alexandre Belloni <alexandre.belloni@bootlin.com> 8e6e7376cSAlexandre Belloni * 9e6e7376cSAlexandre Belloni */ 10e6e7376cSAlexandre Belloni 11f583c341SParthiban Nallathambi #include <linux/clk-provider.h> 12e6e7376cSAlexandre Belloni #include <linux/bcd.h> 13e6e7376cSAlexandre Belloni #include <linux/bitops.h> 14e6e7376cSAlexandre Belloni #include <linux/i2c.h> 15e6e7376cSAlexandre Belloni #include <linux/interrupt.h> 16e6e7376cSAlexandre Belloni #include <linux/kernel.h> 17e6e7376cSAlexandre Belloni #include <linux/log2.h> 18e6e7376cSAlexandre Belloni #include <linux/module.h> 19e6e7376cSAlexandre Belloni #include <linux/of_device.h> 20e6e7376cSAlexandre Belloni #include <linux/regmap.h> 21e6e7376cSAlexandre Belloni #include <linux/rtc.h> 22e6e7376cSAlexandre Belloni 23e6e7376cSAlexandre Belloni #define RV3028_SEC 0x00 24e6e7376cSAlexandre Belloni #define RV3028_MIN 0x01 25e6e7376cSAlexandre Belloni #define RV3028_HOUR 0x02 26e6e7376cSAlexandre Belloni #define RV3028_WDAY 0x03 27e6e7376cSAlexandre Belloni #define RV3028_DAY 0x04 28e6e7376cSAlexandre Belloni #define RV3028_MONTH 0x05 29e6e7376cSAlexandre Belloni #define RV3028_YEAR 0x06 30e6e7376cSAlexandre Belloni #define RV3028_ALARM_MIN 0x07 31e6e7376cSAlexandre Belloni #define RV3028_ALARM_HOUR 0x08 32e6e7376cSAlexandre Belloni #define RV3028_ALARM_DAY 0x09 33e6e7376cSAlexandre Belloni #define RV3028_STATUS 0x0E 34e6e7376cSAlexandre Belloni #define RV3028_CTRL1 0x0F 35e6e7376cSAlexandre Belloni #define RV3028_CTRL2 0x10 36e6e7376cSAlexandre Belloni #define RV3028_EVT_CTRL 0x13 37e6e7376cSAlexandre Belloni #define RV3028_TS_COUNT 0x14 38e6e7376cSAlexandre Belloni #define RV3028_TS_SEC 0x15 39e6e7376cSAlexandre Belloni #define RV3028_RAM1 0x1F 40e6e7376cSAlexandre Belloni #define RV3028_EEPROM_ADDR 0x25 41e6e7376cSAlexandre Belloni #define RV3028_EEPROM_DATA 0x26 42e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD 0x27 43e6e7376cSAlexandre Belloni #define RV3028_CLKOUT 0x35 44e6e7376cSAlexandre Belloni #define RV3028_OFFSET 0x36 45e6e7376cSAlexandre Belloni #define RV3028_BACKUP 0x37 46e6e7376cSAlexandre Belloni 47e6e7376cSAlexandre Belloni #define RV3028_STATUS_PORF BIT(0) 48e6e7376cSAlexandre Belloni #define RV3028_STATUS_EVF BIT(1) 49e6e7376cSAlexandre Belloni #define RV3028_STATUS_AF BIT(2) 50e6e7376cSAlexandre Belloni #define RV3028_STATUS_TF BIT(3) 51e6e7376cSAlexandre Belloni #define RV3028_STATUS_UF BIT(4) 52e6e7376cSAlexandre Belloni #define RV3028_STATUS_BSF BIT(5) 53e6e7376cSAlexandre Belloni #define RV3028_STATUS_CLKF BIT(6) 54e6e7376cSAlexandre Belloni #define RV3028_STATUS_EEBUSY BIT(7) 55e6e7376cSAlexandre Belloni 56f583c341SParthiban Nallathambi #define RV3028_CLKOUT_FD_MASK GENMASK(2, 0) 57f583c341SParthiban Nallathambi #define RV3028_CLKOUT_PORIE BIT(3) 58f583c341SParthiban Nallathambi #define RV3028_CLKOUT_CLKSY BIT(6) 59f583c341SParthiban Nallathambi #define RV3028_CLKOUT_CLKOE BIT(7) 60f583c341SParthiban Nallathambi 61e6e7376cSAlexandre Belloni #define RV3028_CTRL1_EERD BIT(3) 62e6e7376cSAlexandre Belloni #define RV3028_CTRL1_WADA BIT(5) 63e6e7376cSAlexandre Belloni 64e6e7376cSAlexandre Belloni #define RV3028_CTRL2_RESET BIT(0) 65e6e7376cSAlexandre Belloni #define RV3028_CTRL2_12_24 BIT(1) 66e6e7376cSAlexandre Belloni #define RV3028_CTRL2_EIE BIT(2) 67e6e7376cSAlexandre Belloni #define RV3028_CTRL2_AIE BIT(3) 68e6e7376cSAlexandre Belloni #define RV3028_CTRL2_TIE BIT(4) 69e6e7376cSAlexandre Belloni #define RV3028_CTRL2_UIE BIT(5) 70e6e7376cSAlexandre Belloni #define RV3028_CTRL2_TSE BIT(7) 71e6e7376cSAlexandre Belloni 72e6e7376cSAlexandre Belloni #define RV3028_EVT_CTRL_TSR BIT(2) 73e6e7376cSAlexandre Belloni 74024e6f3dSAlexandre Belloni #define RV3028_EEPROM_CMD_UPDATE 0x11 75e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD_WRITE 0x21 76e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD_READ 0x22 77e6e7376cSAlexandre Belloni 78e6e7376cSAlexandre Belloni #define RV3028_EEBUSY_POLL 10000 79e6e7376cSAlexandre Belloni #define RV3028_EEBUSY_TIMEOUT 100000 80e6e7376cSAlexandre Belloni 81e6e7376cSAlexandre Belloni #define RV3028_BACKUP_TCE BIT(5) 82e6e7376cSAlexandre Belloni #define RV3028_BACKUP_TCR_MASK GENMASK(1,0) 83e6e7376cSAlexandre Belloni 84e6e7376cSAlexandre Belloni #define OFFSET_STEP_PPT 953674 85e6e7376cSAlexandre Belloni 86e6e7376cSAlexandre Belloni enum rv3028_type { 87e6e7376cSAlexandre Belloni rv_3028, 88e6e7376cSAlexandre Belloni }; 89e6e7376cSAlexandre Belloni 90e6e7376cSAlexandre Belloni struct rv3028_data { 91e6e7376cSAlexandre Belloni struct regmap *regmap; 92e6e7376cSAlexandre Belloni struct rtc_device *rtc; 93e6e7376cSAlexandre Belloni enum rv3028_type type; 94f583c341SParthiban Nallathambi #ifdef CONFIG_COMMON_CLK 95f583c341SParthiban Nallathambi struct clk_hw clkout_hw; 96f583c341SParthiban Nallathambi #endif 97e6e7376cSAlexandre Belloni }; 98e6e7376cSAlexandre Belloni 99c1efae14SAlexandre Belloni static u16 rv3028_trickle_resistors[] = {3000, 5000, 9000, 15000}; 100e6e7376cSAlexandre Belloni 101e6e7376cSAlexandre Belloni static ssize_t timestamp0_store(struct device *dev, 102e6e7376cSAlexandre Belloni struct device_attribute *attr, 103e6e7376cSAlexandre Belloni const char *buf, size_t count) 104e6e7376cSAlexandre Belloni { 105e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent); 106e6e7376cSAlexandre Belloni 107e6e7376cSAlexandre Belloni regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR, 108e6e7376cSAlexandre Belloni RV3028_EVT_CTRL_TSR); 109e6e7376cSAlexandre Belloni 110e6e7376cSAlexandre Belloni return count; 111e6e7376cSAlexandre Belloni }; 112e6e7376cSAlexandre Belloni 113e6e7376cSAlexandre Belloni static ssize_t timestamp0_show(struct device *dev, 114e6e7376cSAlexandre Belloni struct device_attribute *attr, char *buf) 115e6e7376cSAlexandre Belloni { 116e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent); 117e6e7376cSAlexandre Belloni struct rtc_time tm; 118e6e7376cSAlexandre Belloni int ret, count; 119e6e7376cSAlexandre Belloni u8 date[6]; 120e6e7376cSAlexandre Belloni 121e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count); 122e6e7376cSAlexandre Belloni if (ret) 123e6e7376cSAlexandre Belloni return ret; 124e6e7376cSAlexandre Belloni 125e6e7376cSAlexandre Belloni if (!count) 126e6e7376cSAlexandre Belloni return 0; 127e6e7376cSAlexandre Belloni 128e6e7376cSAlexandre Belloni ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date, 129e6e7376cSAlexandre Belloni sizeof(date)); 130e6e7376cSAlexandre Belloni if (ret) 131e6e7376cSAlexandre Belloni return ret; 132e6e7376cSAlexandre Belloni 133e6e7376cSAlexandre Belloni tm.tm_sec = bcd2bin(date[0]); 134e6e7376cSAlexandre Belloni tm.tm_min = bcd2bin(date[1]); 135e6e7376cSAlexandre Belloni tm.tm_hour = bcd2bin(date[2]); 136e6e7376cSAlexandre Belloni tm.tm_mday = bcd2bin(date[3]); 137e6e7376cSAlexandre Belloni tm.tm_mon = bcd2bin(date[4]) - 1; 138e6e7376cSAlexandre Belloni tm.tm_year = bcd2bin(date[5]) + 100; 139e6e7376cSAlexandre Belloni 140e6e7376cSAlexandre Belloni ret = rtc_valid_tm(&tm); 141e6e7376cSAlexandre Belloni if (ret) 142e6e7376cSAlexandre Belloni return ret; 143e6e7376cSAlexandre Belloni 144e6e7376cSAlexandre Belloni return sprintf(buf, "%llu\n", 145e6e7376cSAlexandre Belloni (unsigned long long)rtc_tm_to_time64(&tm)); 146e6e7376cSAlexandre Belloni }; 147e6e7376cSAlexandre Belloni 148e6e7376cSAlexandre Belloni static DEVICE_ATTR_RW(timestamp0); 149e6e7376cSAlexandre Belloni 150e6e7376cSAlexandre Belloni static ssize_t timestamp0_count_show(struct device *dev, 151e6e7376cSAlexandre Belloni struct device_attribute *attr, char *buf) 152e6e7376cSAlexandre Belloni { 153e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent); 154e6e7376cSAlexandre Belloni int ret, count; 155e6e7376cSAlexandre Belloni 156e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count); 157e6e7376cSAlexandre Belloni if (ret) 158e6e7376cSAlexandre Belloni return ret; 159e6e7376cSAlexandre Belloni 160e6e7376cSAlexandre Belloni return sprintf(buf, "%u\n", count); 161e6e7376cSAlexandre Belloni }; 162e6e7376cSAlexandre Belloni 163e6e7376cSAlexandre Belloni static DEVICE_ATTR_RO(timestamp0_count); 164e6e7376cSAlexandre Belloni 165e6e7376cSAlexandre Belloni static struct attribute *rv3028_attrs[] = { 166e6e7376cSAlexandre Belloni &dev_attr_timestamp0.attr, 167e6e7376cSAlexandre Belloni &dev_attr_timestamp0_count.attr, 168e6e7376cSAlexandre Belloni NULL 169e6e7376cSAlexandre Belloni }; 170e6e7376cSAlexandre Belloni 171e6e7376cSAlexandre Belloni static const struct attribute_group rv3028_attr_group = { 172e6e7376cSAlexandre Belloni .attrs = rv3028_attrs, 173e6e7376cSAlexandre Belloni }; 174e6e7376cSAlexandre Belloni 175de0ad60eSAlexandre Belloni static int rv3028_exit_eerd(struct rv3028_data *rv3028, u32 eerd) 176de0ad60eSAlexandre Belloni { 177de0ad60eSAlexandre Belloni if (eerd) 178de0ad60eSAlexandre Belloni return 0; 179de0ad60eSAlexandre Belloni 180de0ad60eSAlexandre Belloni return regmap_update_bits(rv3028->regmap, RV3028_CTRL1, RV3028_CTRL1_EERD, 0); 181de0ad60eSAlexandre Belloni } 182de0ad60eSAlexandre Belloni 183de0ad60eSAlexandre Belloni static int rv3028_enter_eerd(struct rv3028_data *rv3028, u32 *eerd) 184de0ad60eSAlexandre Belloni { 185de0ad60eSAlexandre Belloni u32 ctrl1, status; 186de0ad60eSAlexandre Belloni int ret; 187de0ad60eSAlexandre Belloni 188de0ad60eSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_CTRL1, &ctrl1); 189de0ad60eSAlexandre Belloni if (ret) 190de0ad60eSAlexandre Belloni return ret; 191de0ad60eSAlexandre Belloni 192de0ad60eSAlexandre Belloni *eerd = ctrl1 & RV3028_CTRL1_EERD; 193de0ad60eSAlexandre Belloni if (*eerd) 194de0ad60eSAlexandre Belloni return 0; 195de0ad60eSAlexandre Belloni 196de0ad60eSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1, 197de0ad60eSAlexandre Belloni RV3028_CTRL1_EERD, RV3028_CTRL1_EERD); 198de0ad60eSAlexandre Belloni if (ret) 199de0ad60eSAlexandre Belloni return ret; 200de0ad60eSAlexandre Belloni 201de0ad60eSAlexandre Belloni ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status, 202de0ad60eSAlexandre Belloni !(status & RV3028_STATUS_EEBUSY), 203de0ad60eSAlexandre Belloni RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT); 204de0ad60eSAlexandre Belloni if (ret) { 205de0ad60eSAlexandre Belloni rv3028_exit_eerd(rv3028, *eerd); 206de0ad60eSAlexandre Belloni 207de0ad60eSAlexandre Belloni return ret; 208de0ad60eSAlexandre Belloni } 209de0ad60eSAlexandre Belloni 210de0ad60eSAlexandre Belloni return 0; 211de0ad60eSAlexandre Belloni } 212de0ad60eSAlexandre Belloni 213024e6f3dSAlexandre Belloni static int rv3028_update_eeprom(struct rv3028_data *rv3028, u32 eerd) 214024e6f3dSAlexandre Belloni { 215024e6f3dSAlexandre Belloni u32 status; 216024e6f3dSAlexandre Belloni int ret; 217024e6f3dSAlexandre Belloni 218024e6f3dSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0); 219024e6f3dSAlexandre Belloni if (ret) 220024e6f3dSAlexandre Belloni goto exit_eerd; 221024e6f3dSAlexandre Belloni 222024e6f3dSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, RV3028_EEPROM_CMD_UPDATE); 223024e6f3dSAlexandre Belloni if (ret) 224024e6f3dSAlexandre Belloni goto exit_eerd; 225024e6f3dSAlexandre Belloni 226024e6f3dSAlexandre Belloni usleep_range(63000, RV3028_EEBUSY_TIMEOUT); 227024e6f3dSAlexandre Belloni 228024e6f3dSAlexandre Belloni ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status, 229024e6f3dSAlexandre Belloni !(status & RV3028_STATUS_EEBUSY), 230024e6f3dSAlexandre Belloni RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT); 231024e6f3dSAlexandre Belloni 232024e6f3dSAlexandre Belloni exit_eerd: 233024e6f3dSAlexandre Belloni rv3028_exit_eerd(rv3028, eerd); 234024e6f3dSAlexandre Belloni 235024e6f3dSAlexandre Belloni return ret; 236024e6f3dSAlexandre Belloni } 237024e6f3dSAlexandre Belloni 238024e6f3dSAlexandre Belloni static int rv3028_update_cfg(struct rv3028_data *rv3028, unsigned int reg, 239024e6f3dSAlexandre Belloni unsigned int mask, unsigned int val) 240024e6f3dSAlexandre Belloni { 241024e6f3dSAlexandre Belloni u32 eerd; 242024e6f3dSAlexandre Belloni int ret; 243024e6f3dSAlexandre Belloni 244024e6f3dSAlexandre Belloni ret = rv3028_enter_eerd(rv3028, &eerd); 245024e6f3dSAlexandre Belloni if (ret) 246024e6f3dSAlexandre Belloni return ret; 247024e6f3dSAlexandre Belloni 248024e6f3dSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, reg, mask, val); 249024e6f3dSAlexandre Belloni if (ret) { 250024e6f3dSAlexandre Belloni rv3028_exit_eerd(rv3028, eerd); 251024e6f3dSAlexandre Belloni return ret; 252024e6f3dSAlexandre Belloni } 253024e6f3dSAlexandre Belloni 254024e6f3dSAlexandre Belloni return rv3028_update_eeprom(rv3028, eerd); 255024e6f3dSAlexandre Belloni } 256024e6f3dSAlexandre Belloni 257e6e7376cSAlexandre Belloni static irqreturn_t rv3028_handle_irq(int irq, void *dev_id) 258e6e7376cSAlexandre Belloni { 259e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_id; 260e6e7376cSAlexandre Belloni unsigned long events = 0; 261e6e7376cSAlexandre Belloni u32 status = 0, ctrl = 0; 262e6e7376cSAlexandre Belloni 263e6e7376cSAlexandre Belloni if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 || 264e6e7376cSAlexandre Belloni status == 0) { 265e6e7376cSAlexandre Belloni return IRQ_NONE; 266e6e7376cSAlexandre Belloni } 267e6e7376cSAlexandre Belloni 268e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_PORF) 269e6e7376cSAlexandre Belloni dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n"); 270e6e7376cSAlexandre Belloni 271*f007c479SAlexandre Belloni status &= ~RV3028_STATUS_PORF; 272*f007c479SAlexandre Belloni 273e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_TF) { 274e6e7376cSAlexandre Belloni status |= RV3028_STATUS_TF; 275e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_TIE; 276e6e7376cSAlexandre Belloni events |= RTC_PF; 277e6e7376cSAlexandre Belloni } 278e6e7376cSAlexandre Belloni 279e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_AF) { 280e6e7376cSAlexandre Belloni status |= RV3028_STATUS_AF; 281e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_AIE; 282e6e7376cSAlexandre Belloni events |= RTC_AF; 283e6e7376cSAlexandre Belloni } 284e6e7376cSAlexandre Belloni 285e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_UF) { 286e6e7376cSAlexandre Belloni status |= RV3028_STATUS_UF; 287e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_UIE; 288e6e7376cSAlexandre Belloni events |= RTC_UF; 289e6e7376cSAlexandre Belloni } 290e6e7376cSAlexandre Belloni 291e6e7376cSAlexandre Belloni if (events) { 292e6e7376cSAlexandre Belloni rtc_update_irq(rv3028->rtc, 1, events); 293e6e7376cSAlexandre Belloni regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0); 294e6e7376cSAlexandre Belloni regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0); 295e6e7376cSAlexandre Belloni } 296e6e7376cSAlexandre Belloni 297e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_EVF) { 298e6e7376cSAlexandre Belloni sysfs_notify(&rv3028->rtc->dev.kobj, NULL, 299e6e7376cSAlexandre Belloni dev_attr_timestamp0.attr.name); 300e6e7376cSAlexandre Belloni dev_warn(&rv3028->rtc->dev, "event detected"); 301e6e7376cSAlexandre Belloni } 302e6e7376cSAlexandre Belloni 303e6e7376cSAlexandre Belloni return IRQ_HANDLED; 304e6e7376cSAlexandre Belloni } 305e6e7376cSAlexandre Belloni 306e6e7376cSAlexandre Belloni static int rv3028_get_time(struct device *dev, struct rtc_time *tm) 307e6e7376cSAlexandre Belloni { 308e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 309e6e7376cSAlexandre Belloni u8 date[7]; 310e6e7376cSAlexandre Belloni int ret, status; 311e6e7376cSAlexandre Belloni 312e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status); 313e6e7376cSAlexandre Belloni if (ret < 0) 314e6e7376cSAlexandre Belloni return ret; 315e6e7376cSAlexandre Belloni 316e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_PORF) { 317e6e7376cSAlexandre Belloni dev_warn(dev, "Voltage low, data is invalid.\n"); 318e6e7376cSAlexandre Belloni return -EINVAL; 319e6e7376cSAlexandre Belloni } 320e6e7376cSAlexandre Belloni 321e6e7376cSAlexandre Belloni ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date)); 322e6e7376cSAlexandre Belloni if (ret) 323e6e7376cSAlexandre Belloni return ret; 324e6e7376cSAlexandre Belloni 325e6e7376cSAlexandre Belloni tm->tm_sec = bcd2bin(date[RV3028_SEC] & 0x7f); 326e6e7376cSAlexandre Belloni tm->tm_min = bcd2bin(date[RV3028_MIN] & 0x7f); 327e6e7376cSAlexandre Belloni tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f); 328e6e7376cSAlexandre Belloni tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f); 329e6e7376cSAlexandre Belloni tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f); 330e6e7376cSAlexandre Belloni tm->tm_mon = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1; 331e6e7376cSAlexandre Belloni tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100; 332e6e7376cSAlexandre Belloni 333e6e7376cSAlexandre Belloni return 0; 334e6e7376cSAlexandre Belloni } 335e6e7376cSAlexandre Belloni 336e6e7376cSAlexandre Belloni static int rv3028_set_time(struct device *dev, struct rtc_time *tm) 337e6e7376cSAlexandre Belloni { 338e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 339e6e7376cSAlexandre Belloni u8 date[7]; 340e6e7376cSAlexandre Belloni int ret; 341e6e7376cSAlexandre Belloni 342e6e7376cSAlexandre Belloni date[RV3028_SEC] = bin2bcd(tm->tm_sec); 343e6e7376cSAlexandre Belloni date[RV3028_MIN] = bin2bcd(tm->tm_min); 344e6e7376cSAlexandre Belloni date[RV3028_HOUR] = bin2bcd(tm->tm_hour); 345e6e7376cSAlexandre Belloni date[RV3028_WDAY] = 1 << (tm->tm_wday); 346e6e7376cSAlexandre Belloni date[RV3028_DAY] = bin2bcd(tm->tm_mday); 347e6e7376cSAlexandre Belloni date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1); 348e6e7376cSAlexandre Belloni date[RV3028_YEAR] = bin2bcd(tm->tm_year - 100); 349e6e7376cSAlexandre Belloni 350e6e7376cSAlexandre Belloni /* 351e6e7376cSAlexandre Belloni * Writing to the Seconds register has the same effect as setting RESET 352e6e7376cSAlexandre Belloni * bit to 1 353e6e7376cSAlexandre Belloni */ 354e6e7376cSAlexandre Belloni ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date, 355e6e7376cSAlexandre Belloni sizeof(date)); 356e6e7376cSAlexandre Belloni if (ret) 357e6e7376cSAlexandre Belloni return ret; 358e6e7376cSAlexandre Belloni 359e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS, 360e6e7376cSAlexandre Belloni RV3028_STATUS_PORF, 0); 361e6e7376cSAlexandre Belloni 362e6e7376cSAlexandre Belloni return ret; 363e6e7376cSAlexandre Belloni } 364e6e7376cSAlexandre Belloni 365e6e7376cSAlexandre Belloni static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm) 366e6e7376cSAlexandre Belloni { 367e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 368e6e7376cSAlexandre Belloni u8 alarmvals[3]; 369e6e7376cSAlexandre Belloni int status, ctrl, ret; 370e6e7376cSAlexandre Belloni 371e6e7376cSAlexandre Belloni ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals, 372e6e7376cSAlexandre Belloni sizeof(alarmvals)); 373e6e7376cSAlexandre Belloni if (ret) 374e6e7376cSAlexandre Belloni return ret; 375e6e7376cSAlexandre Belloni 376e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status); 377e6e7376cSAlexandre Belloni if (ret < 0) 378e6e7376cSAlexandre Belloni return ret; 379e6e7376cSAlexandre Belloni 380e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl); 381e6e7376cSAlexandre Belloni if (ret < 0) 382e6e7376cSAlexandre Belloni return ret; 383e6e7376cSAlexandre Belloni 384e6e7376cSAlexandre Belloni alrm->time.tm_sec = 0; 385e6e7376cSAlexandre Belloni alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); 386e6e7376cSAlexandre Belloni alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); 387e6e7376cSAlexandre Belloni alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f); 388e6e7376cSAlexandre Belloni 389e6e7376cSAlexandre Belloni alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE); 390e6e7376cSAlexandre Belloni alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled; 391e6e7376cSAlexandre Belloni 392e6e7376cSAlexandre Belloni return 0; 393e6e7376cSAlexandre Belloni } 394e6e7376cSAlexandre Belloni 395e6e7376cSAlexandre Belloni static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 396e6e7376cSAlexandre Belloni { 397e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 398e6e7376cSAlexandre Belloni u8 alarmvals[3]; 399e6e7376cSAlexandre Belloni u8 ctrl = 0; 400e6e7376cSAlexandre Belloni int ret; 401e6e7376cSAlexandre Belloni 402e6e7376cSAlexandre Belloni /* The alarm has no seconds, round up to nearest minute */ 403e6e7376cSAlexandre Belloni if (alrm->time.tm_sec) { 404e6e7376cSAlexandre Belloni time64_t alarm_time = rtc_tm_to_time64(&alrm->time); 405e6e7376cSAlexandre Belloni 406e6e7376cSAlexandre Belloni alarm_time += 60 - alrm->time.tm_sec; 407e6e7376cSAlexandre Belloni rtc_time64_to_tm(alarm_time, &alrm->time); 408e6e7376cSAlexandre Belloni } 409e6e7376cSAlexandre Belloni 410e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2, 411e6e7376cSAlexandre Belloni RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0); 412e6e7376cSAlexandre Belloni if (ret) 413e6e7376cSAlexandre Belloni return ret; 414e6e7376cSAlexandre Belloni 415e6e7376cSAlexandre Belloni alarmvals[0] = bin2bcd(alrm->time.tm_min); 416e6e7376cSAlexandre Belloni alarmvals[1] = bin2bcd(alrm->time.tm_hour); 417e6e7376cSAlexandre Belloni alarmvals[2] = bin2bcd(alrm->time.tm_mday); 418e6e7376cSAlexandre Belloni 419e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS, 420e6e7376cSAlexandre Belloni RV3028_STATUS_AF, 0); 421e6e7376cSAlexandre Belloni if (ret) 422e6e7376cSAlexandre Belloni return ret; 423e6e7376cSAlexandre Belloni 424e6e7376cSAlexandre Belloni ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals, 425e6e7376cSAlexandre Belloni sizeof(alarmvals)); 426e6e7376cSAlexandre Belloni if (ret) 427e6e7376cSAlexandre Belloni return ret; 428e6e7376cSAlexandre Belloni 429e6e7376cSAlexandre Belloni if (alrm->enabled) { 430e6e7376cSAlexandre Belloni if (rv3028->rtc->uie_rtctimer.enabled) 431e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_UIE; 432e6e7376cSAlexandre Belloni if (rv3028->rtc->aie_timer.enabled) 433e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_AIE; 434e6e7376cSAlexandre Belloni } 435e6e7376cSAlexandre Belloni 436e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2, 437e6e7376cSAlexandre Belloni RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl); 438e6e7376cSAlexandre Belloni 439e6e7376cSAlexandre Belloni return ret; 440e6e7376cSAlexandre Belloni } 441e6e7376cSAlexandre Belloni 442e6e7376cSAlexandre Belloni static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled) 443e6e7376cSAlexandre Belloni { 444e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 445e6e7376cSAlexandre Belloni int ctrl = 0, ret; 446e6e7376cSAlexandre Belloni 447e6e7376cSAlexandre Belloni if (enabled) { 448e6e7376cSAlexandre Belloni if (rv3028->rtc->uie_rtctimer.enabled) 449e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_UIE; 450e6e7376cSAlexandre Belloni if (rv3028->rtc->aie_timer.enabled) 451e6e7376cSAlexandre Belloni ctrl |= RV3028_CTRL2_AIE; 452e6e7376cSAlexandre Belloni } 453e6e7376cSAlexandre Belloni 454e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS, 455e6e7376cSAlexandre Belloni RV3028_STATUS_AF | RV3028_STATUS_UF, 0); 456e6e7376cSAlexandre Belloni if (ret) 457e6e7376cSAlexandre Belloni return ret; 458e6e7376cSAlexandre Belloni 459e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2, 460e6e7376cSAlexandre Belloni RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl); 461e6e7376cSAlexandre Belloni if (ret) 462e6e7376cSAlexandre Belloni return ret; 463e6e7376cSAlexandre Belloni 464e6e7376cSAlexandre Belloni return 0; 465e6e7376cSAlexandre Belloni } 466e6e7376cSAlexandre Belloni 467e6e7376cSAlexandre Belloni static int rv3028_read_offset(struct device *dev, long *offset) 468e6e7376cSAlexandre Belloni { 469e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 470e6e7376cSAlexandre Belloni int ret, value, steps; 471e6e7376cSAlexandre Belloni 472e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value); 473e6e7376cSAlexandre Belloni if (ret < 0) 474e6e7376cSAlexandre Belloni return ret; 475e6e7376cSAlexandre Belloni 476e6e7376cSAlexandre Belloni steps = sign_extend32(value << 1, 8); 477e6e7376cSAlexandre Belloni 478e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value); 479e6e7376cSAlexandre Belloni if (ret < 0) 480e6e7376cSAlexandre Belloni return ret; 481e6e7376cSAlexandre Belloni 482e6e7376cSAlexandre Belloni steps += value >> 7; 483e6e7376cSAlexandre Belloni 484e6e7376cSAlexandre Belloni *offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000); 485e6e7376cSAlexandre Belloni 486e6e7376cSAlexandre Belloni return 0; 487e6e7376cSAlexandre Belloni } 488e6e7376cSAlexandre Belloni 489e6e7376cSAlexandre Belloni static int rv3028_set_offset(struct device *dev, long offset) 490e6e7376cSAlexandre Belloni { 491e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 492024e6f3dSAlexandre Belloni u32 eerd; 493e6e7376cSAlexandre Belloni int ret; 494e6e7376cSAlexandre Belloni 495e6e7376cSAlexandre Belloni offset = clamp(offset, -244141L, 243187L) * 1000; 496e6e7376cSAlexandre Belloni offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT); 497e6e7376cSAlexandre Belloni 498024e6f3dSAlexandre Belloni ret = rv3028_enter_eerd(rv3028, &eerd); 499024e6f3dSAlexandre Belloni if (ret) 500e6e7376cSAlexandre Belloni return ret; 501e6e7376cSAlexandre Belloni 502024e6f3dSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1); 503024e6f3dSAlexandre Belloni if (ret < 0) 504024e6f3dSAlexandre Belloni goto exit_eerd; 505024e6f3dSAlexandre Belloni 506024e6f3dSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7), 507e6e7376cSAlexandre Belloni offset << 7); 508024e6f3dSAlexandre Belloni if (ret < 0) 509024e6f3dSAlexandre Belloni goto exit_eerd; 510024e6f3dSAlexandre Belloni 511024e6f3dSAlexandre Belloni return rv3028_update_eeprom(rv3028, eerd); 512024e6f3dSAlexandre Belloni 513024e6f3dSAlexandre Belloni exit_eerd: 514024e6f3dSAlexandre Belloni rv3028_exit_eerd(rv3028, eerd); 515024e6f3dSAlexandre Belloni 516024e6f3dSAlexandre Belloni return ret; 517024e6f3dSAlexandre Belloni 518e6e7376cSAlexandre Belloni } 519e6e7376cSAlexandre Belloni 520e6e7376cSAlexandre Belloni static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 521e6e7376cSAlexandre Belloni { 522e6e7376cSAlexandre Belloni struct rv3028_data *rv3028 = dev_get_drvdata(dev); 523e6e7376cSAlexandre Belloni int status, ret = 0; 524e6e7376cSAlexandre Belloni 525e6e7376cSAlexandre Belloni switch (cmd) { 526e6e7376cSAlexandre Belloni case RTC_VL_READ: 527e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status); 528e6e7376cSAlexandre Belloni if (ret < 0) 529e6e7376cSAlexandre Belloni return ret; 530e6e7376cSAlexandre Belloni 53186e655f9SAlexandre Belloni status = status & RV3028_STATUS_PORF ? RTC_VL_DATA_INVALID : 0; 53286e655f9SAlexandre Belloni return put_user(status, (unsigned int __user *)arg); 533e6e7376cSAlexandre Belloni 534e6e7376cSAlexandre Belloni default: 535e6e7376cSAlexandre Belloni return -ENOIOCTLCMD; 536e6e7376cSAlexandre Belloni } 537e6e7376cSAlexandre Belloni } 538e6e7376cSAlexandre Belloni 539e6e7376cSAlexandre Belloni static int rv3028_nvram_write(void *priv, unsigned int offset, void *val, 540e6e7376cSAlexandre Belloni size_t bytes) 541e6e7376cSAlexandre Belloni { 542e6e7376cSAlexandre Belloni return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes); 543e6e7376cSAlexandre Belloni } 544e6e7376cSAlexandre Belloni 545e6e7376cSAlexandre Belloni static int rv3028_nvram_read(void *priv, unsigned int offset, void *val, 546e6e7376cSAlexandre Belloni size_t bytes) 547e6e7376cSAlexandre Belloni { 548e6e7376cSAlexandre Belloni return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes); 549e6e7376cSAlexandre Belloni } 550e6e7376cSAlexandre Belloni 551e6e7376cSAlexandre Belloni static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val, 552e6e7376cSAlexandre Belloni size_t bytes) 553e6e7376cSAlexandre Belloni { 554de0ad60eSAlexandre Belloni struct rv3028_data *rv3028 = priv; 555de0ad60eSAlexandre Belloni u32 status, eerd; 556de0ad60eSAlexandre Belloni int i, ret; 557e6e7376cSAlexandre Belloni u8 *buf = val; 558e6e7376cSAlexandre Belloni 559de0ad60eSAlexandre Belloni ret = rv3028_enter_eerd(rv3028, &eerd); 560e6e7376cSAlexandre Belloni if (ret) 561e6e7376cSAlexandre Belloni return ret; 562e6e7376cSAlexandre Belloni 563e6e7376cSAlexandre Belloni for (i = 0; i < bytes; i++) { 564de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i); 565e6e7376cSAlexandre Belloni if (ret) 566e6e7376cSAlexandre Belloni goto restore_eerd; 567e6e7376cSAlexandre Belloni 568de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_DATA, buf[i]); 569e6e7376cSAlexandre Belloni if (ret) 570e6e7376cSAlexandre Belloni goto restore_eerd; 571e6e7376cSAlexandre Belloni 572de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0); 573e6e7376cSAlexandre Belloni if (ret) 574e6e7376cSAlexandre Belloni goto restore_eerd; 575e6e7376cSAlexandre Belloni 576de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 577e6e7376cSAlexandre Belloni RV3028_EEPROM_CMD_WRITE); 578e6e7376cSAlexandre Belloni if (ret) 579e6e7376cSAlexandre Belloni goto restore_eerd; 580e6e7376cSAlexandre Belloni 581e6e7376cSAlexandre Belloni usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT); 582e6e7376cSAlexandre Belloni 583de0ad60eSAlexandre Belloni ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status, 584e6e7376cSAlexandre Belloni !(status & RV3028_STATUS_EEBUSY), 585e6e7376cSAlexandre Belloni RV3028_EEBUSY_POLL, 586e6e7376cSAlexandre Belloni RV3028_EEBUSY_TIMEOUT); 587e6e7376cSAlexandre Belloni if (ret) 588e6e7376cSAlexandre Belloni goto restore_eerd; 589e6e7376cSAlexandre Belloni } 590e6e7376cSAlexandre Belloni 591e6e7376cSAlexandre Belloni restore_eerd: 592de0ad60eSAlexandre Belloni rv3028_exit_eerd(rv3028, eerd); 593e6e7376cSAlexandre Belloni 594e6e7376cSAlexandre Belloni return ret; 595e6e7376cSAlexandre Belloni } 596e6e7376cSAlexandre Belloni 597e6e7376cSAlexandre Belloni static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val, 598e6e7376cSAlexandre Belloni size_t bytes) 599e6e7376cSAlexandre Belloni { 600de0ad60eSAlexandre Belloni struct rv3028_data *rv3028 = priv; 601de0ad60eSAlexandre Belloni u32 status, eerd, data; 602de0ad60eSAlexandre Belloni int i, ret; 603e6e7376cSAlexandre Belloni u8 *buf = val; 604e6e7376cSAlexandre Belloni 605de0ad60eSAlexandre Belloni ret = rv3028_enter_eerd(rv3028, &eerd); 606e6e7376cSAlexandre Belloni if (ret) 607e6e7376cSAlexandre Belloni return ret; 608e6e7376cSAlexandre Belloni 609e6e7376cSAlexandre Belloni for (i = 0; i < bytes; i++) { 610de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i); 611e6e7376cSAlexandre Belloni if (ret) 612e6e7376cSAlexandre Belloni goto restore_eerd; 613e6e7376cSAlexandre Belloni 614de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0); 615e6e7376cSAlexandre Belloni if (ret) 616e6e7376cSAlexandre Belloni goto restore_eerd; 617e6e7376cSAlexandre Belloni 618de0ad60eSAlexandre Belloni ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 619e6e7376cSAlexandre Belloni RV3028_EEPROM_CMD_READ); 620e6e7376cSAlexandre Belloni if (ret) 621e6e7376cSAlexandre Belloni goto restore_eerd; 622e6e7376cSAlexandre Belloni 623de0ad60eSAlexandre Belloni ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status, 624e6e7376cSAlexandre Belloni !(status & RV3028_STATUS_EEBUSY), 625e6e7376cSAlexandre Belloni RV3028_EEBUSY_POLL, 626e6e7376cSAlexandre Belloni RV3028_EEBUSY_TIMEOUT); 627e6e7376cSAlexandre Belloni if (ret) 628e6e7376cSAlexandre Belloni goto restore_eerd; 629e6e7376cSAlexandre Belloni 630de0ad60eSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_EEPROM_DATA, &data); 631e6e7376cSAlexandre Belloni if (ret) 632e6e7376cSAlexandre Belloni goto restore_eerd; 633e6e7376cSAlexandre Belloni buf[i] = data; 634e6e7376cSAlexandre Belloni } 635e6e7376cSAlexandre Belloni 636e6e7376cSAlexandre Belloni restore_eerd: 637de0ad60eSAlexandre Belloni rv3028_exit_eerd(rv3028, eerd); 638e6e7376cSAlexandre Belloni 639e6e7376cSAlexandre Belloni return ret; 640e6e7376cSAlexandre Belloni } 641e6e7376cSAlexandre Belloni 642f583c341SParthiban Nallathambi #ifdef CONFIG_COMMON_CLK 643f583c341SParthiban Nallathambi #define clkout_hw_to_rv3028(hw) container_of(hw, struct rv3028_data, clkout_hw) 644f583c341SParthiban Nallathambi 645f583c341SParthiban Nallathambi static int clkout_rates[] = { 646f583c341SParthiban Nallathambi 32768, 647f583c341SParthiban Nallathambi 8192, 648f583c341SParthiban Nallathambi 1024, 649f583c341SParthiban Nallathambi 64, 650f583c341SParthiban Nallathambi 32, 651f583c341SParthiban Nallathambi 1, 652f583c341SParthiban Nallathambi }; 653f583c341SParthiban Nallathambi 654f583c341SParthiban Nallathambi static unsigned long rv3028_clkout_recalc_rate(struct clk_hw *hw, 655f583c341SParthiban Nallathambi unsigned long parent_rate) 656f583c341SParthiban Nallathambi { 657f583c341SParthiban Nallathambi int clkout, ret; 658f583c341SParthiban Nallathambi struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); 659f583c341SParthiban Nallathambi 660f583c341SParthiban Nallathambi ret = regmap_read(rv3028->regmap, RV3028_CLKOUT, &clkout); 661f583c341SParthiban Nallathambi if (ret < 0) 662f583c341SParthiban Nallathambi return 0; 663f583c341SParthiban Nallathambi 664f583c341SParthiban Nallathambi clkout &= RV3028_CLKOUT_FD_MASK; 665f583c341SParthiban Nallathambi return clkout_rates[clkout]; 666f583c341SParthiban Nallathambi } 667f583c341SParthiban Nallathambi 668f583c341SParthiban Nallathambi static long rv3028_clkout_round_rate(struct clk_hw *hw, unsigned long rate, 669f583c341SParthiban Nallathambi unsigned long *prate) 670f583c341SParthiban Nallathambi { 671f583c341SParthiban Nallathambi int i; 672f583c341SParthiban Nallathambi 673f583c341SParthiban Nallathambi for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) 674f583c341SParthiban Nallathambi if (clkout_rates[i] <= rate) 675f583c341SParthiban Nallathambi return clkout_rates[i]; 676f583c341SParthiban Nallathambi 677f583c341SParthiban Nallathambi return 0; 678f583c341SParthiban Nallathambi } 679f583c341SParthiban Nallathambi 680f583c341SParthiban Nallathambi static int rv3028_clkout_set_rate(struct clk_hw *hw, unsigned long rate, 681f583c341SParthiban Nallathambi unsigned long parent_rate) 682f583c341SParthiban Nallathambi { 683f583c341SParthiban Nallathambi int i, ret; 68400e8e87fSAlexandre Belloni u32 enabled; 685f583c341SParthiban Nallathambi struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); 686f583c341SParthiban Nallathambi 68700e8e87fSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_CLKOUT, &enabled); 68800e8e87fSAlexandre Belloni if (ret < 0) 68900e8e87fSAlexandre Belloni return ret; 69000e8e87fSAlexandre Belloni 691f583c341SParthiban Nallathambi ret = regmap_write(rv3028->regmap, RV3028_CLKOUT, 0x0); 692f583c341SParthiban Nallathambi if (ret < 0) 693f583c341SParthiban Nallathambi return ret; 694f583c341SParthiban Nallathambi 69500e8e87fSAlexandre Belloni enabled &= RV3028_CLKOUT_CLKOE; 696f583c341SParthiban Nallathambi 69700e8e87fSAlexandre Belloni for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) 69800e8e87fSAlexandre Belloni if (clkout_rates[i] == rate) 699024e6f3dSAlexandre Belloni return rv3028_update_cfg(rv3028, RV3028_CLKOUT, 0xff, 70000e8e87fSAlexandre Belloni RV3028_CLKOUT_CLKSY | enabled | i); 701f583c341SParthiban Nallathambi 702f583c341SParthiban Nallathambi return -EINVAL; 703f583c341SParthiban Nallathambi } 704f583c341SParthiban Nallathambi 705f583c341SParthiban Nallathambi static int rv3028_clkout_prepare(struct clk_hw *hw) 706f583c341SParthiban Nallathambi { 707f583c341SParthiban Nallathambi struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); 708f583c341SParthiban Nallathambi 709f583c341SParthiban Nallathambi return regmap_write(rv3028->regmap, RV3028_CLKOUT, 710f583c341SParthiban Nallathambi RV3028_CLKOUT_CLKSY | RV3028_CLKOUT_CLKOE); 711f583c341SParthiban Nallathambi } 712f583c341SParthiban Nallathambi 713f583c341SParthiban Nallathambi static void rv3028_clkout_unprepare(struct clk_hw *hw) 714f583c341SParthiban Nallathambi { 715f583c341SParthiban Nallathambi struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); 716f583c341SParthiban Nallathambi 717f583c341SParthiban Nallathambi regmap_write(rv3028->regmap, RV3028_CLKOUT, 0x0); 718f583c341SParthiban Nallathambi regmap_update_bits(rv3028->regmap, RV3028_STATUS, 719f583c341SParthiban Nallathambi RV3028_STATUS_CLKF, 0); 720f583c341SParthiban Nallathambi } 721f583c341SParthiban Nallathambi 722f583c341SParthiban Nallathambi static int rv3028_clkout_is_prepared(struct clk_hw *hw) 723f583c341SParthiban Nallathambi { 724f583c341SParthiban Nallathambi int clkout, ret; 725f583c341SParthiban Nallathambi struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); 726f583c341SParthiban Nallathambi 727f583c341SParthiban Nallathambi ret = regmap_read(rv3028->regmap, RV3028_CLKOUT, &clkout); 728f583c341SParthiban Nallathambi if (ret < 0) 729f583c341SParthiban Nallathambi return ret; 730f583c341SParthiban Nallathambi 731f583c341SParthiban Nallathambi return !!(clkout & RV3028_CLKOUT_CLKOE); 732f583c341SParthiban Nallathambi } 733f583c341SParthiban Nallathambi 734f583c341SParthiban Nallathambi static const struct clk_ops rv3028_clkout_ops = { 735f583c341SParthiban Nallathambi .prepare = rv3028_clkout_prepare, 736f583c341SParthiban Nallathambi .unprepare = rv3028_clkout_unprepare, 737f583c341SParthiban Nallathambi .is_prepared = rv3028_clkout_is_prepared, 738f583c341SParthiban Nallathambi .recalc_rate = rv3028_clkout_recalc_rate, 739f583c341SParthiban Nallathambi .round_rate = rv3028_clkout_round_rate, 740f583c341SParthiban Nallathambi .set_rate = rv3028_clkout_set_rate, 741f583c341SParthiban Nallathambi }; 742f583c341SParthiban Nallathambi 743f583c341SParthiban Nallathambi static int rv3028_clkout_register_clk(struct rv3028_data *rv3028, 744f583c341SParthiban Nallathambi struct i2c_client *client) 745f583c341SParthiban Nallathambi { 746f583c341SParthiban Nallathambi int ret; 747f583c341SParthiban Nallathambi struct clk *clk; 748f583c341SParthiban Nallathambi struct clk_init_data init; 749f583c341SParthiban Nallathambi struct device_node *node = client->dev.of_node; 750f583c341SParthiban Nallathambi 751f583c341SParthiban Nallathambi ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS, 752f583c341SParthiban Nallathambi RV3028_STATUS_CLKF, 0); 753f583c341SParthiban Nallathambi if (ret < 0) 754f583c341SParthiban Nallathambi return ret; 755f583c341SParthiban Nallathambi 756f583c341SParthiban Nallathambi init.name = "rv3028-clkout"; 757f583c341SParthiban Nallathambi init.ops = &rv3028_clkout_ops; 758f583c341SParthiban Nallathambi init.flags = 0; 759f583c341SParthiban Nallathambi init.parent_names = NULL; 760f583c341SParthiban Nallathambi init.num_parents = 0; 761f583c341SParthiban Nallathambi rv3028->clkout_hw.init = &init; 762f583c341SParthiban Nallathambi 763f583c341SParthiban Nallathambi /* optional override of the clockname */ 764f583c341SParthiban Nallathambi of_property_read_string(node, "clock-output-names", &init.name); 765f583c341SParthiban Nallathambi 766f583c341SParthiban Nallathambi /* register the clock */ 767f583c341SParthiban Nallathambi clk = devm_clk_register(&client->dev, &rv3028->clkout_hw); 768f583c341SParthiban Nallathambi if (!IS_ERR(clk)) 769f583c341SParthiban Nallathambi of_clk_add_provider(node, of_clk_src_simple_get, clk); 770f583c341SParthiban Nallathambi 771f583c341SParthiban Nallathambi return 0; 772f583c341SParthiban Nallathambi } 773f583c341SParthiban Nallathambi #endif 774f583c341SParthiban Nallathambi 7750f769569SAlexandre Belloni static const struct rtc_class_ops rv3028_rtc_ops = { 776e6e7376cSAlexandre Belloni .read_time = rv3028_get_time, 777e6e7376cSAlexandre Belloni .set_time = rv3028_set_time, 7780f769569SAlexandre Belloni .read_alarm = rv3028_get_alarm, 7790f769569SAlexandre Belloni .set_alarm = rv3028_set_alarm, 7800f769569SAlexandre Belloni .alarm_irq_enable = rv3028_alarm_irq_enable, 781e6e7376cSAlexandre Belloni .read_offset = rv3028_read_offset, 782e6e7376cSAlexandre Belloni .set_offset = rv3028_set_offset, 783e6e7376cSAlexandre Belloni .ioctl = rv3028_ioctl, 784e6e7376cSAlexandre Belloni }; 785e6e7376cSAlexandre Belloni 786e6e7376cSAlexandre Belloni static const struct regmap_config regmap_config = { 787e6e7376cSAlexandre Belloni .reg_bits = 8, 788e6e7376cSAlexandre Belloni .val_bits = 8, 789e6e7376cSAlexandre Belloni .max_register = 0x37, 790e6e7376cSAlexandre Belloni }; 791e6e7376cSAlexandre Belloni 792e6e7376cSAlexandre Belloni static int rv3028_probe(struct i2c_client *client) 793e6e7376cSAlexandre Belloni { 794e6e7376cSAlexandre Belloni struct rv3028_data *rv3028; 795e6e7376cSAlexandre Belloni int ret, status; 796e6e7376cSAlexandre Belloni u32 ohms; 797e6e7376cSAlexandre Belloni struct nvmem_config nvmem_cfg = { 798e6e7376cSAlexandre Belloni .name = "rv3028_nvram", 799e6e7376cSAlexandre Belloni .word_size = 1, 800e6e7376cSAlexandre Belloni .stride = 1, 801e6e7376cSAlexandre Belloni .size = 2, 802e6e7376cSAlexandre Belloni .type = NVMEM_TYPE_BATTERY_BACKED, 803e6e7376cSAlexandre Belloni .reg_read = rv3028_nvram_read, 804e6e7376cSAlexandre Belloni .reg_write = rv3028_nvram_write, 805e6e7376cSAlexandre Belloni }; 806e6e7376cSAlexandre Belloni struct nvmem_config eeprom_cfg = { 807e6e7376cSAlexandre Belloni .name = "rv3028_eeprom", 808e6e7376cSAlexandre Belloni .word_size = 1, 809e6e7376cSAlexandre Belloni .stride = 1, 810e6e7376cSAlexandre Belloni .size = 43, 811e6e7376cSAlexandre Belloni .type = NVMEM_TYPE_EEPROM, 812e6e7376cSAlexandre Belloni .reg_read = rv3028_eeprom_read, 813e6e7376cSAlexandre Belloni .reg_write = rv3028_eeprom_write, 814e6e7376cSAlexandre Belloni }; 815e6e7376cSAlexandre Belloni 816e6e7376cSAlexandre Belloni rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data), 817e6e7376cSAlexandre Belloni GFP_KERNEL); 818e6e7376cSAlexandre Belloni if (!rv3028) 819e6e7376cSAlexandre Belloni return -ENOMEM; 820e6e7376cSAlexandre Belloni 821e6e7376cSAlexandre Belloni rv3028->regmap = devm_regmap_init_i2c(client, ®map_config); 822c3b29bf6SChuhong Yuan if (IS_ERR(rv3028->regmap)) 823c3b29bf6SChuhong Yuan return PTR_ERR(rv3028->regmap); 824e6e7376cSAlexandre Belloni 825e6e7376cSAlexandre Belloni i2c_set_clientdata(client, rv3028); 826e6e7376cSAlexandre Belloni 827e6e7376cSAlexandre Belloni ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status); 828e6e7376cSAlexandre Belloni if (ret < 0) 829e6e7376cSAlexandre Belloni return ret; 830e6e7376cSAlexandre Belloni 831e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_PORF) 832e6e7376cSAlexandre Belloni dev_warn(&client->dev, "Voltage low, data loss detected.\n"); 833e6e7376cSAlexandre Belloni 834e6e7376cSAlexandre Belloni if (status & RV3028_STATUS_AF) 835e6e7376cSAlexandre Belloni dev_warn(&client->dev, "An alarm may have been missed.\n"); 836e6e7376cSAlexandre Belloni 837e6e7376cSAlexandre Belloni rv3028->rtc = devm_rtc_allocate_device(&client->dev); 83844c638ceSAlexandre Belloni if (IS_ERR(rv3028->rtc)) 839e6e7376cSAlexandre Belloni return PTR_ERR(rv3028->rtc); 840e6e7376cSAlexandre Belloni 841e6e7376cSAlexandre Belloni if (client->irq > 0) { 842e6e7376cSAlexandre Belloni ret = devm_request_threaded_irq(&client->dev, client->irq, 843e6e7376cSAlexandre Belloni NULL, rv3028_handle_irq, 844e6e7376cSAlexandre Belloni IRQF_TRIGGER_LOW | IRQF_ONESHOT, 845e6e7376cSAlexandre Belloni "rv3028", rv3028); 846e6e7376cSAlexandre Belloni if (ret) { 847e6e7376cSAlexandre Belloni dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n"); 848e6e7376cSAlexandre Belloni client->irq = 0; 849e6e7376cSAlexandre Belloni } 850e6e7376cSAlexandre Belloni } 8510f769569SAlexandre Belloni if (!client->irq) 8520f769569SAlexandre Belloni clear_bit(RTC_FEATURE_ALARM, rv3028->rtc->features); 853e6e7376cSAlexandre Belloni 854e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1, 855e6e7376cSAlexandre Belloni RV3028_CTRL1_WADA, RV3028_CTRL1_WADA); 856e6e7376cSAlexandre Belloni if (ret) 857e6e7376cSAlexandre Belloni return ret; 858e6e7376cSAlexandre Belloni 859e6e7376cSAlexandre Belloni /* setup timestamping */ 860e6e7376cSAlexandre Belloni ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2, 861e6e7376cSAlexandre Belloni RV3028_CTRL2_EIE | RV3028_CTRL2_TSE, 862e6e7376cSAlexandre Belloni RV3028_CTRL2_EIE | RV3028_CTRL2_TSE); 863e6e7376cSAlexandre Belloni if (ret) 864e6e7376cSAlexandre Belloni return ret; 865e6e7376cSAlexandre Belloni 866e6e7376cSAlexandre Belloni /* setup trickle charger */ 867e6e7376cSAlexandre Belloni if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms", 868e6e7376cSAlexandre Belloni &ohms)) { 869e6e7376cSAlexandre Belloni int i; 870e6e7376cSAlexandre Belloni 871e6e7376cSAlexandre Belloni for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++) 872e6e7376cSAlexandre Belloni if (ohms == rv3028_trickle_resistors[i]) 873e6e7376cSAlexandre Belloni break; 874e6e7376cSAlexandre Belloni 875e6e7376cSAlexandre Belloni if (i < ARRAY_SIZE(rv3028_trickle_resistors)) { 876024e6f3dSAlexandre Belloni ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE | 877024e6f3dSAlexandre Belloni RV3028_BACKUP_TCR_MASK, RV3028_BACKUP_TCE | i); 878e6e7376cSAlexandre Belloni if (ret) 879e6e7376cSAlexandre Belloni return ret; 880e6e7376cSAlexandre Belloni } else { 881e6e7376cSAlexandre Belloni dev_warn(&client->dev, "invalid trickle resistor value\n"); 882e6e7376cSAlexandre Belloni } 883e6e7376cSAlexandre Belloni } 884e6e7376cSAlexandre Belloni 885e6e7376cSAlexandre Belloni ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group); 886e6e7376cSAlexandre Belloni if (ret) 887e6e7376cSAlexandre Belloni return ret; 888e6e7376cSAlexandre Belloni 889e6e7376cSAlexandre Belloni rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 890e6e7376cSAlexandre Belloni rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099; 891e6e7376cSAlexandre Belloni rv3028->rtc->ops = &rv3028_rtc_ops; 892fdcfd854SBartosz Golaszewski ret = devm_rtc_register_device(rv3028->rtc); 893e6e7376cSAlexandre Belloni if (ret) 894e6e7376cSAlexandre Belloni return ret; 895e6e7376cSAlexandre Belloni 896e6e7376cSAlexandre Belloni nvmem_cfg.priv = rv3028->regmap; 8973a905c2dSBartosz Golaszewski devm_rtc_nvmem_register(rv3028->rtc, &nvmem_cfg); 898de0ad60eSAlexandre Belloni eeprom_cfg.priv = rv3028; 8993a905c2dSBartosz Golaszewski devm_rtc_nvmem_register(rv3028->rtc, &eeprom_cfg); 900e6e7376cSAlexandre Belloni 901e6e7376cSAlexandre Belloni rv3028->rtc->max_user_freq = 1; 902e6e7376cSAlexandre Belloni 903f583c341SParthiban Nallathambi #ifdef CONFIG_COMMON_CLK 904f583c341SParthiban Nallathambi rv3028_clkout_register_clk(rv3028, client); 905f583c341SParthiban Nallathambi #endif 906e6e7376cSAlexandre Belloni return 0; 907e6e7376cSAlexandre Belloni } 908e6e7376cSAlexandre Belloni 909e6e7376cSAlexandre Belloni static const struct of_device_id rv3028_of_match[] = { 910e6e7376cSAlexandre Belloni { .compatible = "microcrystal,rv3028", }, 911e6e7376cSAlexandre Belloni { } 912e6e7376cSAlexandre Belloni }; 913e6e7376cSAlexandre Belloni MODULE_DEVICE_TABLE(of, rv3028_of_match); 914e6e7376cSAlexandre Belloni 915e6e7376cSAlexandre Belloni static struct i2c_driver rv3028_driver = { 916e6e7376cSAlexandre Belloni .driver = { 917e6e7376cSAlexandre Belloni .name = "rtc-rv3028", 918e6e7376cSAlexandre Belloni .of_match_table = of_match_ptr(rv3028_of_match), 919e6e7376cSAlexandre Belloni }, 920e6e7376cSAlexandre Belloni .probe_new = rv3028_probe, 921e6e7376cSAlexandre Belloni }; 922e6e7376cSAlexandre Belloni module_i2c_driver(rv3028_driver); 923e6e7376cSAlexandre Belloni 924e6e7376cSAlexandre Belloni MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>"); 925e6e7376cSAlexandre Belloni MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver"); 926e6e7376cSAlexandre Belloni MODULE_LICENSE("GPL v2"); 927