Uwe Kleine-König (The Capable Hub)rtc: Use named initializers for arrays of i2c_device_data3eebec15 months agoHistory
776 lines · 20.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * RTC driver for the MAX31335 * * Copyright (C) 2023 Analog Devices * * Antoniu Miclaus <antoniu.miclaus@analog.com> * */ #include <linux/unaligned.h>#include <linux/bcd.h>#include <linux/bitfield.h>#include <linux/bitops.h>#include <linux/clk.h>#include <linux/clk-provider.h>#include <linux/hwmon.h>#include <linux/i2c.h>#include <linux/interrupt.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/of_device.h>#include <linux/regmap.h>#include <linux/rtc.h>#include <linux/util_macros.h> /* MAX31335 Register Map */#define MAX31335_STATUS1			0x00#define MAX31335_INT_EN1			0x01#define MAX31335_STATUS2			0x02#define MAX31335_INT_EN2			0x03#define MAX31335_RTC_RESET			0x04#define MAX31335_RTC_CONFIG			0x05#define MAX31335_RTC_CONFIG2			0x06#define MAX31335_TIMESTAMP_CONFIG		0x07#define MAX31335_TIMER_CONFIG			0x08#define MAX31335_SECONDS_1_128			0x09#define MAX31335_SECONDS			0x0A#define MAX31335_MINUTES			0x0B#define MAX31335_HOURS				0x0C#define MAX31335_DAY				0x0D#define MAX31335_DATE				0x0E#define MAX31335_MONTH				0x0F#define MAX31335_YEAR				0x0F#define MAX31335_ALM1_SEC			0x11#define MAX31335_ALM1_MIN			0x12#define MAX31335_ALM1_HRS			0x13#define MAX31335_ALM1_DAY_DATE			0x14#define MAX31335_ALM1_MON			0x15#define MAX31335_ALM1_YEAR			0x16#define MAX31335_ALM2_MIN			0x17#define MAX31335_ALM2_HRS			0x18#define MAX31335_ALM2_DAY_DATE			0x19#define MAX31335_TIMER_COUNT			0x1A#define MAX31335_TIMER_INIT			0x1B#define MAX31335_PWR_MGMT			0x1C#define MAX31335_TRICKLE_REG			0x1D#define MAX31335_AGING_OFFSET			0x1E#define MAX31335_TS_CONFIG			0x30#define MAX31335_TEMP_ALARM_HIGH_MSB		0x31#define MAX31335_TEMP_ALARM_HIGH_LSB		0x32#define MAX31335_TEMP_ALARM_LOW_MSB		0x33#define MAX31335_TEMP_ALARM_LOW_LSB		0x34#define MAX31335_TEMP_DATA_MSB			0x35#define MAX31335_TEMP_DATA_LSB			0x36#define MAX31335_TS0_SEC_1_128			0x40#define MAX31335_TS0_SEC			0x41#define MAX31335_TS0_MIN			0x42#define MAX31335_TS0_HOUR			0x43#define MAX31335_TS0_DATE			0x44#define MAX31335_TS0_MONTH			0x45#define MAX31335_TS0_YEAR			0x46#define MAX31335_TS0_FLAGS			0x47#define MAX31335_TS1_SEC_1_128			0x48#define MAX31335_TS1_SEC			0x49#define MAX31335_TS1_MIN			0x4A#define MAX31335_TS1_HOUR			0x4B#define MAX31335_TS1_DATE			0x4C#define MAX31335_TS1_MONTH			0x4D#define MAX31335_TS1_YEAR			0x4E#define MAX31335_TS1_FLAGS			0x4F#define MAX31335_TS2_SEC_1_128			0x50#define MAX31335_TS2_SEC			0x51#define MAX31335_TS2_MIN			0x52#define MAX31335_TS2_HOUR			0x53#define MAX31335_TS2_DATE			0x54#define MAX31335_TS2_MONTH			0x55#define MAX31335_TS2_YEAR			0x56#define MAX31335_TS2_FLAGS			0x57#define MAX31335_TS3_SEC_1_128			0x58#define MAX31335_TS3_SEC			0x59#define MAX31335_TS3_MIN			0x5A#define MAX31335_TS3_HOUR			0x5B#define MAX31335_TS3_DATE			0x5C#define MAX31335_TS3_MONTH			0x5D#define MAX31335_TS3_YEAR			0x5E#define MAX31335_TS3_FLAGS			0x5F /* MAX31335_STATUS1 Bit Definitions */#define MAX31335_STATUS1_PSDECT			BIT(7)#define MAX31335_STATUS1_OSF			BIT(6)#define MAX31335_STATUS1_PFAIL			BIT(5)#define MAX31335_STATUS1_VBATLOW		BIT(4)#define MAX31335_STATUS1_DIF			BIT(3)#define MAX31335_STATUS1_TIF			BIT(2)#define MAX31335_STATUS1_A2F			BIT(1)#define MAX31335_STATUS1_A1F			BIT(0) /* MAX31335_INT_EN1 Bit Definitions */#define MAX31335_INT_EN1_DOSF			BIT(6)#define MAX31335_INT_EN1_PFAILE			BIT(5)#define MAX31335_INT_EN1_VBATLOWE		BIT(4)#define MAX31335_INT_EN1_DIE			BIT(3)#define MAX31335_INT_EN1_TIE			BIT(2)#define MAX31335_INT_EN1_A2IE			BIT(1)#define MAX31335_INT_EN1_A1IE			BIT(0) /* MAX31335_STATUS2 Bit Definitions */#define MAX31335_STATUS2_TEMP_RDY		BIT(2)#define MAX31335_STATUS2_OTF			BIT(1)#define MAX31335_STATUS2_UTF			BIT(0) /* MAX31335_INT_EN2 Bit Definitions */#define MAX31335_INT_EN2_TEMP_RDY_EN		BIT(2)#define MAX31335_INT_EN2_OTIE			BIT(1)#define MAX31335_INT_EN2_UTIE			BIT(0) /* MAX31335_RTC_RESET Bit Definitions */#define MAX31335_RTC_RESET_SWRST		BIT(0) /* MAX31335_RTC_CONFIG1 Bit Definitions */#define MAX31335_RTC_CONFIG1_EN_IO		BIT(6)#define MAX31335_RTC_CONFIG1_A1AC		GENMASK(5, 4)#define MAX31335_RTC_CONFIG1_DIP		BIT(3)#define MAX31335_RTC_CONFIG1_I2C_TIMEOUT	BIT(1)#define MAX31335_RTC_CONFIG1_EN_OSC		BIT(0) /* MAX31335_RTC_CONFIG2 Bit Definitions */#define MAX31335_RTC_CONFIG2_ENCLKO		BIT(2)#define MAX31335_RTC_CONFIG2_CLKO_HZ		GENMASK(1, 0) /* MAX31335_TIMESTAMP_CONFIG Bit Definitions */#define MAX31335_TIMESTAMP_CONFIG_TSVLOW	BIT(5)#define MAX31335_TIMESTAMP_CONFIG_TSPWM		BIT(4)#define MAX31335_TIMESTAMP_CONFIG_TSDIN		BIT(3)#define MAX31335_TIMESTAMP_CONFIG_TSOW		BIT(2)#define MAX31335_TIMESTAMP_CONFIG_TSR		BIT(1)#define MAX31335_TIMESTAMP_CONFIG_TSE		BIT(0) /* MAX31335_TIMER_CONFIG Bit Definitions */#define MAX31335_TIMER_CONFIG_TE		BIT(4)#define MAX31335_TIMER_CONFIG_TPAUSE		BIT(3)#define MAX31335_TIMER_CONFIG_TRPT		BIT(2)#define MAX31335_TIMER_CONFIG_TFS		GENMASK(1, 0) /* MAX31335_HOURS Bit Definitions */#define MAX31335_HOURS_F_24_12			BIT(6)#define MAX31335_HOURS_HR_20_AM_PM		BIT(5) /* MAX31335_MONTH Bit Definitions */#define MAX31335_MONTH_CENTURY			BIT(7) /* MAX31335_PWR_MGMT Bit Definitions */#define MAX31335_PWR_MGMT_PFVT			BIT(0) /* MAX31335_TRICKLE_REG Bit Definitions */#define MAX31335_TRICKLE_REG_TRICKLE		GENMASK(3, 1)#define MAX31335_TRICKLE_REG_EN_TRICKLE		BIT(0) /* MAX31335_TS_CONFIG Bit Definitions */#define MAX31335_TS_CONFIG_AUTO			BIT(4)#define MAX31335_TS_CONFIG_CONVERT_T		BIT(3)#define MAX31335_TS_CONFIG_TSINT		GENMASK(2, 0) /* MAX31335_TS_FLAGS Bit Definitions */#define MAX31335_TS_FLAGS_VLOWF			BIT(3)#define MAX31335_TS_FLAGS_VBATF			BIT(2)#define MAX31335_TS_FLAGS_VCCF			BIT(1)#define MAX31335_TS_FLAGS_DINF			BIT(0) /* MAX31335 Miscellaneous Definitions */#define MAX31335_TRICKLE_SCHOTTKY_DIODE		1#define MAX31335_TRICKLE_STANDARD_DIODE		4#define MAX31335_RAM_SIZE			32#define MAX31335_TIME_SIZE			0x07 /* MAX31331 Register Map */#define MAX31331_RTC_CONFIG2			0x04 #define clk_hw_to_max31335(_hw) container_of(_hw, struct max31335_data, clkout) /* Supported Maxim RTC */enum max_rtc_ids {	ID_MAX31331,	ID_MAX31335,	MAX_RTC_ID_NR}; struct chip_desc {	u8 sec_reg;	u8 alarm1_sec_reg; 	u8 int_en_reg;	u8 int_status_reg; 	u8 ram_reg;	u8 ram_size; 	u8 temp_reg; 	u8 trickle_reg; 	u8 clkout_reg; 	enum max_rtc_ids id;}; struct max31335_data {	struct regmap *regmap;	struct rtc_device *rtc;	struct clk_hw clkout;	struct clk *clkin;	const struct chip_desc *chip;	int irq;}; static const int max31335_clkout_freq[] = { 1, 64, 1024, 32768 }; static const struct chip_desc chip[MAX_RTC_ID_NR] = {	[ID_MAX31331] = {		.id = ID_MAX31331,		.int_en_reg = 0x01,		.int_status_reg = 0x00,		.sec_reg = 0x08,		.alarm1_sec_reg = 0x0F,		.ram_reg = 0x20,		.ram_size = 32,		.trickle_reg = 0x1B,		.clkout_reg = 0x04,	},	[ID_MAX31335] = {		.id = ID_MAX31335,		.int_en_reg = 0x01,		.int_status_reg = 0x00,		.sec_reg = 0x0A,		.alarm1_sec_reg = 0x11,		.ram_reg = 0x40,		.ram_size = 32,		.temp_reg = 0x35,		.trickle_reg = 0x1D,		.clkout_reg = 0x06,	},}; static const u16 max31335_trickle_resistors[] = {3000, 6000, 11000}; static bool max31335_volatile_reg(struct device *dev, unsigned int reg){	struct max31335_data *max31335 = dev_get_drvdata(dev);	const struct chip_desc *chip = max31335->chip; 	/* time keeping registers */	if (reg >= chip->sec_reg && reg < chip->sec_reg + MAX31335_TIME_SIZE)		return true; 	/* interrupt status register */	if (reg == chip->int_status_reg)		return true; 	/* temperature registers if valid */	if (chip->temp_reg && (reg == chip->temp_reg || reg == chip->temp_reg + 1))		return true; 	return false;} static const struct regmap_config regmap_config = {	.reg_bits = 8,	.val_bits = 8,	.max_register = 0x5F,	.volatile_reg = max31335_volatile_reg,}; static int max31335_read_time(struct device *dev, struct rtc_time *tm){	struct max31335_data *max31335 = dev_get_drvdata(dev);	u8 date[7];	int ret; 	ret = regmap_bulk_read(max31335->regmap, max31335->chip->sec_reg, date,			       sizeof(date));	if (ret)		return ret; 	tm->tm_sec  = bcd2bin(date[0] & 0x7f);	tm->tm_min  = bcd2bin(date[1] & 0x7f);	tm->tm_hour = bcd2bin(date[2] & 0x3f);	tm->tm_wday = bcd2bin(date[3] & 0x7) - 1;	tm->tm_mday = bcd2bin(date[4] & 0x3f);	tm->tm_mon  = bcd2bin(date[5] & 0x1f) - 1;	tm->tm_year = bcd2bin(date[6]) + 100; 	if (FIELD_GET(MAX31335_MONTH_CENTURY, date[5]))		tm->tm_year += 100; 	return 0;} static int max31335_set_time(struct device *dev, struct rtc_time *tm){	struct max31335_data *max31335 = dev_get_drvdata(dev);	u8 date[7]; 	date[0] = bin2bcd(tm->tm_sec);	date[1] = bin2bcd(tm->tm_min);	date[2] = bin2bcd(tm->tm_hour);	date[3] = bin2bcd(tm->tm_wday + 1);	date[4] = bin2bcd(tm->tm_mday);	date[5] = bin2bcd(tm->tm_mon + 1);	date[6] = bin2bcd(tm->tm_year % 100); 	if (tm->tm_year >= 200)		date[5] |= FIELD_PREP(MAX31335_MONTH_CENTURY, 1); 	return regmap_bulk_write(max31335->regmap, max31335->chip->sec_reg, date,				 sizeof(date));} static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm){	struct max31335_data *max31335 = dev_get_drvdata(dev);	int ret, ctrl, status;	struct rtc_time time;	u8 regs[6]; 	ret = regmap_bulk_read(max31335->regmap, max31335->chip->alarm1_sec_reg, regs,			       sizeof(regs));	if (ret)		return ret; 	alrm->time.tm_sec  = bcd2bin(regs[0] & 0x7f);	alrm->time.tm_min  = bcd2bin(regs[1] & 0x7f);	alrm->time.tm_hour = bcd2bin(regs[2] & 0x3f);	alrm->time.tm_mday = bcd2bin(regs[3] & 0x3f);	alrm->time.tm_mon  = bcd2bin(regs[4] & 0x1f) - 1;	alrm->time.tm_year = bcd2bin(regs[5]) + 100; 	ret = max31335_read_time(dev, &time);	if (ret)		return ret; 	if (time.tm_year >= 200)		alrm->time.tm_year += 100; 	ret = regmap_read(max31335->regmap, max31335->chip->int_en_reg, &ctrl);	if (ret)		return ret; 	ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status);	if (ret)		return ret; 	alrm->enabled = FIELD_GET(MAX31335_INT_EN1_A1IE, ctrl);	alrm->pending = FIELD_GET(MAX31335_STATUS1_A1F, status); 	return 0;} static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm){	struct max31335_data *max31335 = dev_get_drvdata(dev);	unsigned int reg;	u8 regs[6];	int ret; 	regs[0] = bin2bcd(alrm->time.tm_sec);	regs[1] = bin2bcd(alrm->time.tm_min);	regs[2] = bin2bcd(alrm->time.tm_hour);	regs[3] = bin2bcd(alrm->time.tm_mday);	regs[4] = bin2bcd(alrm->time.tm_mon + 1);	regs[5] = bin2bcd(alrm->time.tm_year % 100); 	ret = regmap_bulk_write(max31335->regmap, max31335->chip->alarm1_sec_reg,				regs, sizeof(regs));	if (ret)		return ret; 	reg = FIELD_PREP(MAX31335_INT_EN1_A1IE, alrm->enabled);	ret = regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg,				 MAX31335_INT_EN1_A1IE, reg);	if (ret)		return ret; 	return regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,				  MAX31335_STATUS1_A1F, 0);} static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled){	struct max31335_data *max31335 = dev_get_drvdata(dev); 	return regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg,				  MAX31335_INT_EN1_A1IE, enabled);} static irqreturn_t max31335_handle_irq(int irq, void *dev_id){	struct max31335_data *max31335 = dev_id;	struct mutex *lock = &max31335->rtc->ops_lock;	int ret, status; 	mutex_lock(lock); 	ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status);	if (ret)		goto exit; 	if (FIELD_GET(MAX31335_STATUS1_A1F, status)) {		ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,					 MAX31335_STATUS1_A1F, 0);		if (ret)			goto exit; 		rtc_update_irq(max31335->rtc, 1, RTC_AF | RTC_IRQF);	} exit:	mutex_unlock(lock); 	return IRQ_HANDLED;} static const struct rtc_class_ops max31335_rtc_ops = {	.read_time = max31335_read_time,	.set_time = max31335_set_time,	.read_alarm = max31335_read_alarm,	.set_alarm = max31335_set_alarm,	.alarm_irq_enable = max31335_alarm_irq_enable,}; static int max31335_trickle_charger_setup(struct device *dev,					  struct max31335_data *max31335){	u32 ohms, chargeable;	int i, trickle_cfg;	const char *diode; 	if (device_property_read_u32(dev, "aux-voltage-chargeable",				     &chargeable))		return 0; 	if (device_property_read_u32(dev, "trickle-resistor-ohms", &ohms))		return 0; 	if (device_property_read_string(dev, "adi,tc-diode", &diode))		return 0; 	if (!strcmp(diode, "schottky"))		trickle_cfg = MAX31335_TRICKLE_SCHOTTKY_DIODE;	else if (!strcmp(diode, "standard+schottky"))		trickle_cfg = MAX31335_TRICKLE_STANDARD_DIODE;	else		return dev_err_probe(dev, -EINVAL,				     "Invalid tc-diode value: %s\n", diode); 	for (i = 0; i < ARRAY_SIZE(max31335_trickle_resistors); i++)		if (ohms == max31335_trickle_resistors[i])			break; 	if (i >= ARRAY_SIZE(max31335_trickle_resistors))		return 0; 	i = i + trickle_cfg; 	return regmap_write(max31335->regmap, max31335->chip->trickle_reg,			    FIELD_PREP(MAX31335_TRICKLE_REG_TRICKLE, i) |			    FIELD_PREP(MAX31335_TRICKLE_REG_EN_TRICKLE,				       chargeable));} static unsigned long max31335_clkout_recalc_rate(struct clk_hw *hw,						 unsigned long parent_rate){	struct max31335_data *max31335 = clk_hw_to_max31335(hw);	unsigned int freq_mask;	unsigned int reg;	int ret; 	ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, &reg);	if (ret)		return 0; 	freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1; 	return max31335_clkout_freq[reg & freq_mask];} static int max31335_clkout_determine_rate(struct clk_hw *hw,					  struct clk_rate_request *req){

Lines 1–500 of 776.