[v7,1/2] drivers: rtc: add max313xx series rtc driver

Message ID 20240219221827.3821415-2-chris.packham@alliedtelesis.co.nz
State New
Headers
Series drivers: rtc: add max313xx series rtc driver |

Commit Message

Chris Packham Feb. 19, 2024, 10:18 p.m. UTC
  From: Ibrahim Tilki <Ibrahim.Tilki@analog.com>

Adding support for Analog Devices MAX313XX series RTCs.

Signed-off-by: Ibrahim Tilki <Ibrahim.Tilki@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 drivers/rtc/Kconfig        |    2 +-
 drivers/rtc/rtc-max31335.c | 1152 ++++++++++++++++++++++++------------
 2 files changed, 790 insertions(+), 364 deletions(-)
  

Comments

Guenter Roeck Feb. 20, 2024, 7:42 p.m. UTC | #1
On 2/19/24 14:18, Chris Packham wrote:
> From: Ibrahim Tilki <Ibrahim.Tilki@analog.com>
> 
> Adding support for Analog Devices MAX313XX series RTCs.
> 

Adding -> Add

The subject should really be something like "rtc: max31335: Add support
for additional chips", with details in the patch description.

All those (in my opinion unnecessary) function, data structure,
and variable renames makes it really difficult to review the code.
I don't see the point of that, so please don't expect any further
feedback about the hwmon changes from me.

Thanks,
Guenter
  
Chris Packham Feb. 20, 2024, 8:07 p.m. UTC | #2
On 21/02/24 08:42, Guenter Roeck wrote:
> On 2/19/24 14:18, Chris Packham wrote:
>> From: Ibrahim Tilki <Ibrahim.Tilki@analog.com>
>>
>> Adding support for Analog Devices MAX313XX series RTCs.
>>
>
> Adding -> Add
>
> The subject should really be something like "rtc: max31335: Add support
> for additional chips", with details in the patch description.

Ack.

> All those (in my opinion unnecessary) function, data structure,
> and variable renames makes it really difficult to review the code.
> I don't see the point of that, so please don't expect any further
> feedback about the hwmon changes from me. 

Sorry about that. In reality what happened is that someone started 
trying to add support for the range then they left Analog Devices with 
the patch still in flight. In the mean time someone else from AD landed 
a driver for a single variant (with no public datasheet). I'm left 
trying to pick up the pieces.

This is effectively the original max313xx series patch with the max31335 
changes incorporated as best I can. I can probably rename more things so 
there is less delta against the max31335 driver.

> Thanks,
> Guenter
>
  
kernel test robot Feb. 20, 2024, 10:56 p.m. UTC | #3
Hi Chris,

kernel test robot noticed the following build warnings:

[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on linus/master v6.8-rc5 next-20240220]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chris-Packham/drivers-rtc-add-max313xx-series-rtc-driver/20240220-062057
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20240219221827.3821415-2-chris.packham%40alliedtelesis.co.nz
patch subject: [PATCH v7 1/2] drivers: rtc: add max313xx series rtc driver
config: x86_64-randconfig-123-20240220 (https://download.01.org/0day-ci/archive/20240221/202402210633.wquhPF22-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240221/202402210633.wquhPF22-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202402210633.wquhPF22-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/rtc/rtc-max31335.c:727:22: sparse: sparse: symbol 'max313xx_clk_init' was not declared. Should it be static?
>> drivers/rtc/rtc-max31335.c:750:21: sparse: sparse: symbol 'max313xx_nvmem_cfg' was not declared. Should it be static?

vim +/max313xx_clk_init +727 drivers/rtc/rtc-max31335.c

   726	
 > 727	struct clk_init_data max313xx_clk_init = {
   728		.name = "max313xx-clkout",
   729		.ops = &max313xx_clkout_ops,
   730	};
   731	
   732	static int max313xx_nvmem_reg_read(void *priv, unsigned int offset,
   733					   void *val, size_t bytes)
   734	{
   735		struct max313xx *rtc = priv;
   736		unsigned int reg = rtc->chip->ram_reg + offset;
   737	
   738		return regmap_bulk_read(rtc->regmap, reg, val, bytes);
   739	}
   740	
   741	static int max313xx_nvmem_reg_write(void *priv, unsigned int offset,
   742					    void *val, size_t bytes)
   743	{
   744		struct max313xx *rtc = priv;
   745		unsigned int reg = rtc->chip->ram_reg + offset;
   746	
   747		return regmap_bulk_write(rtc->regmap, reg, val, bytes);
   748	}
   749	
 > 750	struct nvmem_config max313xx_nvmem_cfg = {
   751		.reg_read = max313xx_nvmem_reg_read,
   752		.reg_write = max313xx_nvmem_reg_write,
   753		.word_size = 8,
   754	};
   755
  
kernel test robot Feb. 21, 2024, 6:04 p.m. UTC | #4
Hi Chris,

kernel test robot noticed the following build warnings:

[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on linus/master v6.8-rc5 next-20240221]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Chris-Packham/drivers-rtc-add-max313xx-series-rtc-driver/20240220-062057
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20240219221827.3821415-2-chris.packham%40alliedtelesis.co.nz
patch subject: [PATCH v7 1/2] drivers: rtc: add max313xx series rtc driver
config: x86_64-randconfig-123-20240220 (https://download.01.org/0day-ci/archive/20240222/202402220139.EmXyZO4Q-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240222/202402220139.EmXyZO4Q-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202402220139.EmXyZO4Q-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/rtc/rtc-max31335.c:727:22: sparse: sparse: symbol 'max313xx_clk_init' was not declared. Should it be static?
>> drivers/rtc/rtc-max31335.c:750:21: sparse: sparse: symbol 'max313xx_nvmem_cfg' was not declared. Should it be static?

vim +/max313xx_clk_init +727 drivers/rtc/rtc-max31335.c

   726	
 > 727	struct clk_init_data max313xx_clk_init = {
   728		.name = "max313xx-clkout",
   729		.ops = &max313xx_clkout_ops,
   730	};
   731	
   732	static int max313xx_nvmem_reg_read(void *priv, unsigned int offset,
   733					   void *val, size_t bytes)
   734	{
   735		struct max313xx *rtc = priv;
   736		unsigned int reg = rtc->chip->ram_reg + offset;
   737	
   738		return regmap_bulk_read(rtc->regmap, reg, val, bytes);
   739	}
   740	
   741	static int max313xx_nvmem_reg_write(void *priv, unsigned int offset,
   742					    void *val, size_t bytes)
   743	{
   744		struct max313xx *rtc = priv;
   745		unsigned int reg = rtc->chip->ram_reg + offset;
   746	
   747		return regmap_bulk_write(rtc->regmap, reg, val, bytes);
   748	}
   749	
 > 750	struct nvmem_config max313xx_nvmem_cfg = {
   751		.reg_read = max313xx_nvmem_reg_read,
   752		.reg_write = max313xx_nvmem_reg_write,
   753		.word_size = 8,
   754	};
   755
  

Patch

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e37a4341f442..b30e384d0d3c 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -381,7 +381,7 @@  config RTC_DRV_MAX31335
 	select REGMAP_I2C
 	help
 	  If you say yes here you get support for the Analog Devices
-	  MAX31335.
+	  MAX31335/31328/31329/31331/31334/31341/31342/31343.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-max31335.
diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c
index 402fda8fd548..36a5bb37e0b0 100644
--- a/drivers/rtc/rtc-max31335.c
+++ b/drivers/rtc/rtc-max31335.c
@@ -1,13 +1,12 @@ 
 // SPDX-License-Identifier: GPL-2.0
 /*
- * RTC driver for the MAX31335
+ * RTC driver for the MAX313XX series
  *
  * Copyright (C) 2023 Analog Devices
  *
  * Antoniu Miclaus <antoniu.miclaus@analog.com>
  *
  */
-
 #include <asm-generic/unaligned.h>
 #include <linux/bcd.h>
 #include <linux/bitfield.h>
@@ -24,232 +23,398 @@ 
 #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
+/* common registers */
+#define MAX313XX_INT_ALARM1		BIT(0)
+#define MAX313XX_HRS_F_AM_PM		BIT(5)
+#define MAX313XX_HRS_F_12_24		BIT(6)
+#define MAX313XX_MONTH_CENTURY		BIT(7)
 
-/* 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)
+#define MAX313XX_TIME_SIZE		0x07
 
-/* 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)
+/* device specific registers */
+#define MAX3134X_CFG2_REG		0x01
+#define MAX3134X_CFG2_SET_RTC		BIT(1)
 
-/* MAX31335_STATUS2 Bit Definitions */
-#define MAX31335_STATUS2_TEMP_RDY		BIT(2)
-#define MAX31335_STATUS2_OTF			BIT(1)
-#define MAX31335_STATUS2_UTF			BIT(0)
+#define MAX31341_TRICKLE_RES_MASK	GENMASK(1, 0)
+#define MAX31341_TRICKLE_DIODE_EN	BIT(2)
+#define MAX31341_TRICKLE_ENABLE_BIT	BIT(3)
+#define MAX31341_POWER_MGMT_REG		0x56
+#define MAX31341_POWER_MGMT_TRICKLE_BIT	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)
+#define MAX3133X_TRICKLE_RES_MASK	GENMASK(2, 1)
+#define MAX3133X_TRICKLE_DIODE_EN	BIT(3)
+#define MAX3133X_TRICKLE_ENABLE_BIT	BIT(0)
 
-/* MAX31335_RTC_RESET Bit Definitions */
-#define MAX31335_RTC_RESET_SWRST		BIT(0)
+#define MAX31329_TRICKLE_ENABLE_BIT	BIT(7)
+#define MAX31343_TRICKLE_ENABLE_MASK	GENMASK(7, 4)
+#define MAX31343_TRICKLE_ENABLE_CODE	5
+#define MAX31329_43_TRICKLE_RES_MASK	GENMASK(1, 0)
+#define MAX31329_43_TRICKLE_DIODE_EN	BIT(2)
 
-/* 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)
+#define MAX31329_CONFIG2_REG		0x04
+#define MAX31329_CONFIG2_CLKIN_EN	BIT(2)
+#define MAX31329_CONFIG2_CLKIN_FREQ	GENMASK(1, 0)
 
-/* MAX31335_RTC_CONFIG2 Bit Definitions */
-#define MAX31335_RTC_CONFIG2_ENCLKO		BIT(2)
-#define MAX31335_RTC_CONFIG2_CLKO_HZ		GENMASK(1, 0)
+#define MAX31341_42_CONFIG1_REG		0x00
+#define MAX31341_42_CONFIG1_CLKIN_EN	BIT(7)
+#define MAX31341_42_CONFIG1_CLKIN_FREQ	GENMASK(5, 4)
+#define MAX31341_42_CONFIG1_OSC_DISABLE	BIT(3)
+#define MAX31341_42_CONFIG1_SWRST	BIT(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)
+enum max313xx_ids {
+	ID_MAX31328,
+	ID_MAX31329,
+	ID_MAX31331,
+	ID_MAX31334,
+	ID_MAX31335,
+	ID_MAX31341,
+	ID_MAX31342,
+	ID_MAX31343,
+	MAX313XX_ID_NR
+};
 
-/* 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)
+struct clkout_cfg {
+	const int *freq_avail;
+	u8 freq_size;
+	u8 freq_pos;
+	u8 reg;
+	u8 en_bit;
+	bool en_invert;
+};
 
-/* MAX31335_HOURS Bit Definitions */
-#define MAX31335_HOURS_F_24_12			BIT(6)
-#define MAX31335_HOURS_HR_20_AM_PM		BIT(5)
+struct chip_desc {
+	struct clkout_cfg *clkout;
+	const char *clkout_name;
+	u8 sec_reg;
+	u8 alarm1_sec_reg;
 
-/* MAX31335_MONTH Bit Definitions */
-#define MAX31335_MONTH_CENTURY			BIT(7)
+	u8 int_en_reg;
+	u8 int_status_reg;
+	u8 osf_bit;
 
-/* MAX31335_PWR_MGMT Bit Definitions */
-#define MAX31335_PWR_MGMT_PFVT			BIT(0)
+	u8 ram_reg;
+	u8 ram_size;
 
-/* MAX31335_TRICKLE_REG Bit Definitions */
-#define MAX31335_TRICKLE_REG_TRICKLE		GENMASK(3, 1)
-#define MAX31335_TRICKLE_REG_EN_TRICKLE		BIT(0)
+	u8 temp_reg;
 
-/* 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)
+	u8 trickle_reg;
 
-/* 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)
+	u8 rst_reg;
+	u8 rst_bit;
+};
 
-/* 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
+#define clk_hw_to_max313xx(_hw) container_of(_hw, struct max313xx, clkout)
 
-#define clk_hw_to_max31335(_hw) container_of(_hw, struct max31335_data, clkout)
-
-struct max31335_data {
+struct max313xx {
+	enum max313xx_ids id;
 	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 int max313xx_clkin_freq[] = { 1, 50, 60, 32768 };
 
-static const u16 max31335_trickle_resistors[] = {3000, 6000, 11000};
+static const int max31328_clkout_freq[] = { 1, 1024, 4096, 8192 };
+static const int max31329_clkout_freq[] = { 1, 4096, 8192, 32768 };
+static const int max3133x_clkout_freq[] = { 1, 64, 1024, 32768 };
+static const int max31341_42_clkout_freq[] = { 1, 50, 60, 32768 };
+static const int max31343_clkout_freq[] = { 1, 2, 4, 8, 16, 32, 64, 128, 32875 };
 
-static bool max31335_volatile_reg(struct device *dev, unsigned int reg)
+static struct clkout_cfg max31328_clkout = {
+	.freq_avail = max31328_clkout_freq,
+	.freq_size = ARRAY_SIZE(max31328_clkout_freq),
+	.freq_pos = 3,
+	.reg = 0x0E,
+	.en_bit = BIT(3),
+	.en_invert = true,
+};
+
+static struct clkout_cfg max31329_clkout = {
+	.freq_avail = max31329_clkout_freq,
+	.freq_size = ARRAY_SIZE(max31329_clkout_freq),
+	.freq_pos = 5,
+	.reg = 0x04,
+	.en_bit = BIT(7),
+};
+
+static struct clkout_cfg max3133x_clkout = {
+	.freq_avail = max3133x_clkout_freq,
+	.freq_size = ARRAY_SIZE(max3133x_clkout_freq),
+	.freq_pos = 0,
+	.reg = 0x04,
+	.en_bit = BIT(2),
+};
+
+static struct clkout_cfg max31335_clkout = {
+	.freq_avail = max3133x_clkout_freq,
+	.freq_size = ARRAY_SIZE(max3133x_clkout_freq),
+	.freq_pos = 0,
+	.reg = 0x06,
+	.en_bit = BIT(2),
+};
+
+static struct clkout_cfg max31341_42_clkout = {
+	.freq_avail = max31341_42_clkout_freq,
+	.freq_size = ARRAY_SIZE(max31341_42_clkout_freq),
+	.freq_pos = 1,
+	.reg = 0x00,
+	.en_bit = BIT(6),
+	.en_invert = true,
+};
+
+static struct clkout_cfg max31343_clkout = {
+	.freq_avail = max31343_clkout_freq,
+	.freq_size = ARRAY_SIZE(max31343_clkout_freq),
+	.freq_pos = 3,
+	.reg = 0x04,
+	.en_bit = BIT(7),
+};
+
+static const struct chip_desc chip[MAX313XX_ID_NR] = {
+	[ID_MAX31328] = {
+		.int_en_reg = 0x0E,
+		.int_status_reg = 0x0F,
+		.osf_bit = BIT(7),
+		.sec_reg = 0x00,
+		.alarm1_sec_reg = 0x07,
+		.temp_reg = 0x11,
+		.clkout = &max31328_clkout,
+		.clkout_name = "max31328-sqw",
+	},
+	[ID_MAX31329] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x22,
+		.ram_size = 64,
+		.trickle_reg = 0x19,
+		.clkout = &max31329_clkout,
+		.clkout_name = "max31329-clkout",
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31331] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x08,
+		.alarm1_sec_reg = 0x0F,
+		.ram_reg = 0x20,
+		.ram_size = 32,
+		.trickle_reg = 0x1B,
+		.clkout = &max3133x_clkout,
+		.clkout_name = "max31331-clkout",
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31334] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x09,
+		.alarm1_sec_reg = 0x10,
+		.ram_reg = 0x30,
+		.ram_size = 32,
+		.trickle_reg = 0x1E,
+		.clkout = &max3133x_clkout,
+		.clkout_name = "max31334-clkout",
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31335] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x0a,
+		.alarm1_sec_reg = 0x11,
+		.ram_reg = 0x40,
+		.ram_size = 32,
+		.temp_reg = 0x35,
+		.trickle_reg = 0x1d,
+		.clkout = &max31335_clkout,
+		.clkout_name = "max31335-clkout",
+		.rst_reg = 0x04,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31341] = {
+		.int_en_reg = 0x04,
+		.int_status_reg = 0x05,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x16,
+		.ram_size = 64,
+		.trickle_reg = 0x57,
+		.clkout = &max31341_42_clkout,
+		.clkout_name = "max31341-clkout",
+		.rst_reg = 0x00,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31342] = {
+		.int_en_reg = 0x04,
+		.int_status_reg = 0x05,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.clkout = &max31341_42_clkout,
+		.clkout_name = "max31342-clkout",
+		.rst_reg = 0x00,
+		.rst_bit = BIT(0),
+	},
+	[ID_MAX31343] = {
+		.int_en_reg = 0x01,
+		.int_status_reg = 0x00,
+		.osf_bit = BIT(6),
+		.sec_reg = 0x06,
+		.alarm1_sec_reg = 0x0D,
+		.ram_reg = 0x22,
+		.ram_size = 64,
+		.temp_reg = 0x1A,
+		.trickle_reg = 0x19,
+		.clkout = &max31343_clkout,
+		.clkout_name = "max31343-clko",
+		.rst_reg = 0x02,
+		.rst_bit = BIT(0),
+	},
+};
+
+static const u32 max313xx_trickle_ohms[] = { 3000, 6000, 11000 };
+
+static bool max313xx_volatile_reg(struct device *dev, unsigned int reg)
 {
+	struct max313xx *rtc = dev_get_drvdata(dev);
+	const struct chip_desc *chip = rtc->chip;
+
 	/* time keeping registers */
-	if (reg >= MAX31335_SECONDS &&
-	    reg < MAX31335_SECONDS + MAX31335_TIME_SIZE)
+	if (reg >= chip->sec_reg && reg < chip->sec_reg + MAX313XX_TIME_SIZE)
 		return true;
 
 	/* interrupt status register */
-	if (reg == MAX31335_INT_EN1_A1IE)
+	if (reg == chip->int_status_reg)
 		return true;
 
 	/* temperature registers */
-	if (reg == MAX31335_TEMP_DATA_MSB || reg == MAX31335_TEMP_DATA_LSB)
-		return true;
-
-	return false;
+	return chip->temp_reg &&
+		(reg == chip->temp_reg || reg == chip->temp_reg + 1);
 }
 
 static const struct regmap_config regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
-	.max_register = 0x5F,
-	.volatile_reg = max31335_volatile_reg,
+	.cache_type = REGCACHE_RBTREE,
+	.volatile_reg = max313xx_volatile_reg,
 };
 
-static int max31335_read_time(struct device *dev, struct rtc_time *tm)
+static int max313xx_get_hour(u8 hour_reg)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	int hour;
+
+	/* 24Hr mode */
+	if (!FIELD_GET(MAX313XX_HRS_F_12_24, hour_reg))
+		return bcd2bin(hour_reg & 0x3f);
+
+	/* 12Hr mode */
+	hour = bcd2bin(hour_reg & 0x1f);
+	if (hour == 12)
+		hour = 0;
+
+	if (FIELD_GET(MAX313XX_HRS_F_AM_PM, hour_reg))
+		hour += 12;
+
+	return hour;
+}
+
+static int max313xx_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct max313xx *rtc = dev_get_drvdata(dev);
 	u8 date[7];
 	int ret;
+	unsigned int status;
 
-	ret = regmap_bulk_read(max31335->regmap, MAX31335_SECONDS, date,
-			       sizeof(date));
+	ret = regmap_read(rtc->regmap, rtc->chip->int_status_reg, &status);
+	if (ret)
+		return ret;
+
+	if (status & rtc->chip->osf_bit)
+		return -EINVAL;
+
+	ret = regmap_bulk_read(rtc->regmap, rtc->chip->sec_reg, date, 7);
 	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_hour = max313xx_get_hour(date[2]);
 	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]))
+	if (FIELD_GET(MAX313XX_MONTH_CENTURY, date[5]))
 		tm->tm_year += 100;
 
 	return 0;
 }
 
-static int max31335_set_time(struct device *dev, struct rtc_time *tm)
+static int max313xx_pre_set_time(struct max313xx *rtc)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	if (!rtc->clkin)
+		return 0;
+
+	/* Clkin needs to be disabled before setting time. */
+	switch (rtc->id) {
+	case ID_MAX31341:
+	case ID_MAX31342:
+		return regmap_clear_bits(rtc->regmap,
+					 MAX31341_42_CONFIG1_REG,
+					 MAX31341_42_CONFIG1_CLKIN_EN);
+	default:
+		return 0;
+	}
+}
+
+static int max313xx_post_set_time(struct max313xx *rtc)
+{
+	int ret;
+
+	switch (rtc->id) {
+	case ID_MAX31341:
+	case ID_MAX31342:
+		ret = regmap_set_bits(rtc->regmap, MAX3134X_CFG2_REG,
+				      MAX3134X_CFG2_SET_RTC);
+		if (ret)
+			return ret;
+
+		fsleep(10000);
+
+		ret = regmap_clear_bits(rtc->regmap, MAX3134X_CFG2_REG,
+					MAX3134X_CFG2_SET_RTC);
+		if (ret)
+			return ret;
+
+		if (rtc->clkin)
+			ret = regmap_set_bits(rtc->regmap,
+					      MAX31341_42_CONFIG1_REG,
+					      MAX31341_42_CONFIG1_CLKIN_EN);
+
+		break;
+	default:
+		return 0;
+	}
+
+	return ret;
+}
+
+static int max313xx_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct max313xx *rtc = dev_get_drvdata(dev);
 	u8 date[7];
+	int ret;
 
 	date[0] = bin2bcd(tm->tm_sec);
 	date[1] = bin2bcd(tm->tm_min);
@@ -260,20 +425,34 @@  static int max31335_set_time(struct device *dev, struct rtc_time *tm)
 	date[6] = bin2bcd(tm->tm_year % 100);
 
 	if (tm->tm_year >= 200)
-		date[5] |= FIELD_PREP(MAX31335_MONTH_CENTURY, 1);
+		date[5] |= FIELD_PREP(MAX313XX_MONTH_CENTURY, 1);
 
-	return regmap_bulk_write(max31335->regmap, MAX31335_SECONDS, date,
-				 sizeof(date));
+	ret = max313xx_pre_set_time(rtc);
+	if (ret)
+		return ret;
+
+	if (rtc->chip->rst_bit) {
+		ret = regmap_clear_bits(rtc->regmap, rtc->chip->rst_reg, rtc->chip->rst_bit);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_bulk_write(rtc->regmap, rtc->chip->sec_reg, date, 7);
+	if (ret)
+		return ret;
+
+	return max313xx_post_set_time(rtc);
 }
 
-static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+static int max313xx_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
-	int ret, ctrl, status;
+	struct max313xx *rtc = dev_get_drvdata(dev);
+	unsigned int status, int_en;
 	struct rtc_time time;
 	u8 regs[6];
+	int ret;
 
-	ret = regmap_bulk_read(max31335->regmap, MAX31335_ALM1_SEC, regs,
+	ret = regmap_bulk_read(rtc->regmap, rtc->chip->alarm1_sec_reg, regs,
 			       sizeof(regs));
 	if (ret)
 		return ret;
@@ -285,30 +464,30 @@  static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	alrm->time.tm_mon  = bcd2bin(regs[4] & 0x1f) - 1;
 	alrm->time.tm_year = bcd2bin(regs[5]) + 100;
 
-	ret = max31335_read_time(dev, &time);
+	ret = max313xx_read_time(dev, &time);
 	if (ret)
 		return ret;
 
 	if (time.tm_year >= 200)
 		alrm->time.tm_year += 100;
 
-	ret = regmap_read(max31335->regmap, MAX31335_INT_EN1, &ctrl);
+	ret = regmap_read(rtc->regmap, rtc->chip->int_status_reg, &status);
 	if (ret)
 		return ret;
 
-	ret = regmap_read(max31335->regmap, MAX31335_STATUS1, &status);
+	ret = regmap_read(rtc->regmap, rtc->chip->int_en_reg, &int_en);
 	if (ret)
 		return ret;
 
-	alrm->enabled = FIELD_GET(MAX31335_INT_EN1_A1IE, ctrl);
-	alrm->pending = FIELD_GET(MAX31335_STATUS1_A1F, status);
+	alrm->enabled = FIELD_GET(MAX313XX_INT_ALARM1, int_en);
+	alrm->pending = FIELD_GET(MAX313XX_INT_ALARM1, status);
 
 	return 0;
 }
 
-static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+static int max313xx_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	struct max313xx *rtc = dev_get_drvdata(dev);
 	unsigned int reg;
 	u8 regs[6];
 	int ret;
@@ -320,61 +499,62 @@  static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	regs[4] = bin2bcd(alrm->time.tm_mon + 1);
 	regs[5] = bin2bcd(alrm->time.tm_year % 100);
 
-	ret = regmap_bulk_write(max31335->regmap, MAX31335_ALM1_SEC,
-				regs, sizeof(regs));
+	ret = regmap_bulk_write(rtc->regmap, rtc->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_INT_EN1,
-				 MAX31335_INT_EN1_A1IE, reg);
+	reg = FIELD_PREP(MAX313XX_INT_ALARM1, alrm->enabled);
+	ret = regmap_update_bits(rtc->regmap, rtc->chip->int_en_reg,
+				 MAX313XX_INT_ALARM1, reg);
 	if (ret)
 		return ret;
 
-	ret = regmap_update_bits(max31335->regmap, MAX31335_STATUS1,
-				 MAX31335_STATUS1_A1F, 0);
-
-	return 0;
+	/* Clear status register */
+	return regmap_read(rtc->regmap, rtc->chip->int_status_reg, &reg);
 }
 
-static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
+static int max313xx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	struct max313xx *rtc = dev_get_drvdata(dev);
 
-	return regmap_update_bits(max31335->regmap, MAX31335_INT_EN1,
-				  MAX31335_INT_EN1_A1IE, enabled);
+	return regmap_update_bits(rtc->regmap, rtc->chip->int_en_reg,
+				  MAX313XX_INT_ALARM1,
+				  FIELD_PREP(MAX313XX_INT_ALARM1, enabled));
 }
 
-static irqreturn_t max31335_handle_irq(int irq, void *dev_id)
+static irqreturn_t max313xx_irq(int irq, void *dev_id)
 {
-	struct max31335_data *max31335 = dev_id;
+	struct max313xx	*rtc = dev_id;
 	bool status;
 	int ret;
 
-	ret = regmap_update_bits_check(max31335->regmap, MAX31335_STATUS1,
-				       MAX31335_STATUS1_A1F, 0, &status);
+	ret = regmap_update_bits_check(rtc->regmap, rtc->chip->int_status_reg,
+				       MAX313XX_INT_ALARM1, 0, &status);
 	if (ret)
 		return IRQ_HANDLED;
 
 	if (status)
-		rtc_update_irq(max31335->rtc, 1, RTC_AF | RTC_IRQF);
+		rtc_update_irq(rtc->rtc, 1, RTC_AF | RTC_IRQF);
 
 	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 const struct rtc_class_ops max3133x_rtc_ops = {
+	.read_time	= max313xx_read_time,
+	.set_time	= max313xx_set_time,
+	.read_alarm	= max313xx_read_alarm,
+	.set_alarm	= max313xx_set_alarm,
+	.alarm_irq_enable = max313xx_alarm_irq_enable,
 };
 
-static int max31335_trickle_charger_setup(struct device *dev,
-					  struct max31335_data *max31335)
+static int max313xx_trickle_charger_setup(struct device *dev)
 {
+	struct max313xx *rtc = dev_get_drvdata(dev);
+	bool trickle_diode_en;
+	int index, reg;
 	u32 ohms, chargeable;
-	int i, trickle_cfg;
+	int ret;
 	const char *diode;
 
 	if (device_property_read_u32(dev, "aux-voltage-chargeable",
@@ -388,144 +568,196 @@  static int max31335_trickle_charger_setup(struct device *dev,
 		return 0;
 
 	if (!strcmp(diode, "schottky"))
-		trickle_cfg = MAX31335_TRICKLE_SCHOTTKY_DIODE;
+		trickle_diode_en = 0;
 	else if (!strcmp(diode, "standard+schottky"))
-		trickle_cfg = MAX31335_TRICKLE_STANDARD_DIODE;
+		trickle_diode_en = 1;
 	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))
+	if (!rtc->chip->trickle_reg)
 		return 0;
 
-	i = i + trickle_cfg;
+	index = find_closest(ohms, max313xx_trickle_ohms,
+			     ARRAY_SIZE(max313xx_trickle_ohms)) + 1;
 
-	return regmap_write(max31335->regmap, MAX31335_TRICKLE_REG,
-			    FIELD_PREP(MAX31335_TRICKLE_REG_TRICKLE, i) |
-			    FIELD_PREP(MAX31335_TRICKLE_REG_EN_TRICKLE,
-				       chargeable));
+	switch (rtc->id) {
+	case ID_MAX31329:
+		reg = FIELD_PREP(MAX31329_TRICKLE_ENABLE_BIT, chargeable) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_DIODE_EN, trickle_diode_en);
+		break;
+	case ID_MAX31331:
+	case ID_MAX31334:
+		reg = FIELD_PREP(MAX3133X_TRICKLE_ENABLE_BIT, chargeable) |
+		      FIELD_PREP(MAX3133X_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX3133X_TRICKLE_DIODE_EN, trickle_diode_en);
+		break;
+	case ID_MAX31341:
+		if (index == 1)
+			index = 0;
+
+		reg = FIELD_PREP(MAX31341_TRICKLE_ENABLE_BIT, chargeable) |
+		      FIELD_PREP(MAX31341_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX31341_TRICKLE_DIODE_EN, trickle_diode_en);
+
+		ret = regmap_set_bits(rtc->regmap, MAX31341_POWER_MGMT_REG,
+				      MAX31341_POWER_MGMT_TRICKLE_BIT);
+		if (ret)
+			return ret;
+
+		break;
+	case ID_MAX31343:
+		reg = FIELD_PREP(MAX31329_43_TRICKLE_RES_MASK, index) |
+		      FIELD_PREP(MAX31329_43_TRICKLE_DIODE_EN, trickle_diode_en) |
+		      FIELD_PREP(MAX31343_TRICKLE_ENABLE_MASK,
+				 MAX31343_TRICKLE_ENABLE_CODE);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return regmap_write(rtc->regmap, rtc->chip->trickle_reg, reg);
 }
 
-static unsigned long max31335_clkout_recalc_rate(struct clk_hw *hw,
+static unsigned long max313xx_clkout_recalc_rate(struct clk_hw *hw,
 						 unsigned long parent_rate)
 {
-	struct max31335_data *max31335 = clk_hw_to_max31335(hw);
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	const struct clkout_cfg *clkout = rtc->chip->clkout;
 	unsigned int freq_mask;
 	unsigned int reg;
 	int ret;
 
-	ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, &reg);
+	ret = regmap_read(rtc->regmap, clkout->reg, &reg);
 	if (ret)
 		return 0;
 
-	freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1;
+	freq_mask = __roundup_pow_of_two(clkout->freq_size) - 1;
 
-	return max31335_clkout_freq[reg & freq_mask];
+	return clkout->freq_avail[(reg >> clkout->freq_pos) & freq_mask];
 }
 
-static long max31335_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+static long max313xx_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 				       unsigned long *prate)
 {
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	struct clkout_cfg *clkout = rtc->chip->clkout;
 	int index;
 
-	index = find_closest(rate, max31335_clkout_freq,
-			     ARRAY_SIZE(max31335_clkout_freq));
-
-	return max31335_clkout_freq[index];
+	index = find_closest(rate, clkout->freq_avail, clkout->freq_size);
+	return clkout->freq_avail[index];
 }
 
-static int max31335_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+static int max313xx_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 				    unsigned long parent_rate)
 {
-	struct max31335_data *max31335 = clk_hw_to_max31335(hw);
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	struct clkout_cfg *clkout = rtc->chip->clkout;
 	unsigned int freq_mask;
 	int index;
 
-	index = find_closest(rate, max31335_clkout_freq,
-			     ARRAY_SIZE(max31335_clkout_freq));
-	freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1;
+	index = find_closest(rate, clkout->freq_avail, clkout->freq_size);
+	freq_mask = __roundup_pow_of_two(clkout->freq_size) - 1;
 
-	return regmap_update_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
-				  freq_mask, index);
+	return regmap_update_bits(rtc->regmap, clkout->reg,
+				  freq_mask << clkout->freq_pos,
+				  index << clkout->freq_pos);
 }
 
-static int max31335_clkout_enable(struct clk_hw *hw)
+static int max313xx_clkout_enable(struct clk_hw *hw)
 {
-	struct max31335_data *max31335 = clk_hw_to_max31335(hw);
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	struct clkout_cfg *clkout = rtc->chip->clkout;
 
-	return regmap_set_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
-			       MAX31335_RTC_CONFIG2_ENCLKO);
+	if (clkout->en_invert)
+		return regmap_clear_bits(rtc->regmap, clkout->reg,
+					 clkout->en_bit);
+
+	return regmap_set_bits(rtc->regmap, clkout->reg,  clkout->en_bit);
 }
 
-static void max31335_clkout_disable(struct clk_hw *hw)
+static void max313xx_clkout_disable(struct clk_hw *hw)
 {
-	struct max31335_data *max31335 = clk_hw_to_max31335(hw);
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	struct clkout_cfg *clkout = rtc->chip->clkout;
 
-	regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
-			  MAX31335_RTC_CONFIG2_ENCLKO);
+	switch (rtc->id) {
+	case ID_MAX31331:
+	case ID_MAX31334:
+		if (rtc->irq > 0) {
+			dev_err(rtc->rtc->dev.parent,
+				"clkout cannot be disabled when IRQ is requested");
+			return;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (clkout->en_invert)
+		regmap_set_bits(rtc->regmap, clkout->reg, clkout->en_bit);
+	else
+		regmap_clear_bits(rtc->regmap, clkout->reg,  clkout->en_bit);
 }
 
-static int max31335_clkout_is_enabled(struct clk_hw *hw)
+static int max313xx_clkout_is_enabled(struct clk_hw *hw)
 {
-	struct max31335_data *max31335 = clk_hw_to_max31335(hw);
+	struct max313xx *rtc = clk_hw_to_max313xx(hw);
+	struct clkout_cfg *clkout = rtc->chip->clkout;
 	unsigned int reg;
 	int ret;
 
-	ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, &reg);
+	ret = regmap_read(rtc->regmap, clkout->reg, &reg);
 	if (ret)
 		return ret;
 
-	return !!(reg & MAX31335_RTC_CONFIG2_ENCLKO);
+	return !!(reg & clkout->en_bit) ^ clkout->en_invert;
 }
 
-static const struct clk_ops max31335_clkout_ops = {
-	.recalc_rate = max31335_clkout_recalc_rate,
-	.round_rate = max31335_clkout_round_rate,
-	.set_rate = max31335_clkout_set_rate,
-	.enable = max31335_clkout_enable,
-	.disable = max31335_clkout_disable,
-	.is_enabled = max31335_clkout_is_enabled,
+static const struct clk_ops max313xx_clkout_ops = {
+	.recalc_rate = max313xx_clkout_recalc_rate,
+	.round_rate = max313xx_clkout_round_rate,
+	.set_rate = max313xx_clkout_set_rate,
+	.enable = max313xx_clkout_enable,
+	.disable = max313xx_clkout_disable,
+	.is_enabled = max313xx_clkout_is_enabled,
 };
 
-static struct clk_init_data max31335_clk_init = {
-	.name = "max31335-clkout",
-	.ops = &max31335_clkout_ops,
+struct clk_init_data max313xx_clk_init = {
+	.name = "max313xx-clkout",
+	.ops = &max313xx_clkout_ops,
 };
 
-static int max31335_nvmem_reg_read(void *priv, unsigned int offset,
+static int max313xx_nvmem_reg_read(void *priv, unsigned int offset,
 				   void *val, size_t bytes)
 {
-	struct max31335_data *max31335 = priv;
-	unsigned int reg = MAX31335_TS0_SEC_1_128 + offset;
+	struct max313xx *rtc = priv;
+	unsigned int reg = rtc->chip->ram_reg + offset;
 
-	return regmap_bulk_read(max31335->regmap, reg, val, bytes);
+	return regmap_bulk_read(rtc->regmap, reg, val, bytes);
 }
 
-static int max31335_nvmem_reg_write(void *priv, unsigned int offset,
+static int max313xx_nvmem_reg_write(void *priv, unsigned int offset,
 				    void *val, size_t bytes)
 {
-	struct max31335_data *max31335 = priv;
-	unsigned int reg = MAX31335_TS0_SEC_1_128 + offset;
+	struct max313xx *rtc = priv;
+	unsigned int reg = rtc->chip->ram_reg + offset;
 
-	return regmap_bulk_write(max31335->regmap, reg, val, bytes);
+	return regmap_bulk_write(rtc->regmap, reg, val, bytes);
 }
 
-static struct nvmem_config max31335_nvmem_cfg = {
-	.reg_read = max31335_nvmem_reg_read,
-	.reg_write = max31335_nvmem_reg_write,
+struct nvmem_config max313xx_nvmem_cfg = {
+	.reg_read = max313xx_nvmem_reg_read,
+	.reg_write = max313xx_nvmem_reg_write,
 	.word_size = 8,
-	.size = MAX31335_RAM_SIZE,
 };
 
 #if IS_REACHABLE(HWMON)
-static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type,
+static int max313xx_read_temp(struct device *dev, enum hwmon_sensor_types type,
 			      u32 attr, int channel, long *val)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	struct max313xx *rtc = dev_get_drvdata(dev);
 	u8 reg[2];
 	s16 temp;
 	int ret;
@@ -533,8 +765,7 @@  static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type,
 	if (type != hwmon_temp || attr != hwmon_temp_input)
 		return -EOPNOTSUPP;
 
-	ret = regmap_bulk_read(max31335->regmap, MAX31335_TEMP_DATA_MSB,
-			       reg, 2);
+	ret = regmap_bulk_read(rtc->regmap, rtc->chip->temp_reg, reg, 2);
 	if (ret)
 		return ret;
 
@@ -545,7 +776,7 @@  static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type,
 	return 0;
 }
 
-static umode_t max31335_is_visible(const void *data,
+static umode_t max313xx_is_visible(const void *data,
 				   enum hwmon_sensor_types type,
 				   u32 attr, int channel)
 {
@@ -555,143 +786,338 @@  static umode_t max31335_is_visible(const void *data,
 	return 0;
 }
 
-static const struct hwmon_channel_info *max31335_info[] = {
+static const struct hwmon_channel_info *max313xx_info[] = {
 	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
 	NULL
 };
 
-static const struct hwmon_ops max31335_hwmon_ops = {
-	.is_visible = max31335_is_visible,
-	.read = max31335_read_temp,
+static const struct hwmon_ops max313xx_hwmon_ops = {
+	.is_visible = max313xx_is_visible,
+	.read = max313xx_read_temp,
 };
 
-static const struct hwmon_chip_info max31335_chip_info = {
-	.ops = &max31335_hwmon_ops,
-	.info = max31335_info,
+static const struct hwmon_chip_info max313xx_chip_info = {
+	.ops = &max313xx_hwmon_ops,
+	.info = max313xx_info,
 };
 #endif
 
-static int max31335_clkout_register(struct device *dev)
+static int max313xx_init(struct max313xx *rtc)
 {
-	struct max31335_data *max31335 = dev_get_drvdata(dev);
+	int ret;
+
+	switch (rtc->id) {
+	case ID_MAX31341:
+	case ID_MAX31342:
+		ret = regmap_clear_bits(rtc->regmap, MAX31341_42_CONFIG1_REG,
+					MAX31341_42_CONFIG1_OSC_DISABLE);
+		if (ret)
+			return ret;
+
+		return regmap_set_bits(rtc->regmap, MAX31341_42_CONFIG1_REG,
+				       MAX31341_42_CONFIG1_SWRST);
+	default:
+		return 0;
+	}
+}
+
+static int max313xx_clkout_register(struct device *dev)
+{
+	struct max313xx *rtc = dev_get_drvdata(dev);
 	int ret;
 
 	if (!device_property_present(dev, "#clock-cells"))
-		return regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
-					 MAX31335_RTC_CONFIG2_ENCLKO);
+		return 0;
 
-	max31335->clkout.init = &max31335_clk_init;
+	max313xx_clk_init.name = rtc->chip->clkout_name;
+	device_property_read_string(dev, "clock-output-names",
+				    &max313xx_clk_init.name);
+	rtc->clkout.init = &max313xx_clk_init;
 
-	ret = devm_clk_hw_register(dev, &max31335->clkout);
+	ret = devm_clk_hw_register(dev, &rtc->clkout);
 	if (ret)
 		return dev_err_probe(dev, ret, "cannot register clock\n");
 
-	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
-					  &max31335->clkout);
-	if (ret)
-		return dev_err_probe(dev, ret, "cannot add hw provider\n");
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+					   &rtc->clkout);
+}
 
-	max31335->clkout.clk = devm_clk_get_enabled(dev, NULL);
-	if (IS_ERR(max31335->clkout.clk))
-		return dev_err_probe(dev, PTR_ERR(max31335->clkout.clk),
-				     "cannot enable clkout\n");
+static int max313xx_find_clkin_freq_index(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk);
+	int freq;
+	int i;
+
+	i = find_closest(rate, max313xx_clkin_freq,
+			 ARRAY_SIZE(max313xx_clkin_freq));
+	if (max313xx_clkin_freq[i] == rate)
+		return i;
+
+	for (i = ARRAY_SIZE(max313xx_clkin_freq) - 1; i >= 0; i--) {
+		freq = max313xx_clkin_freq[i];
+		if (freq == clk_round_rate(clk, freq))
+			return i;
+	}
+
+	/* supplied clock cannot produce one of desired frequency rate */
+	return -ENODEV;
+}
+
+static int max313xx_clkin_init(struct device *dev)
+{
+	struct max313xx *rtc = dev_get_drvdata(dev);
+	int rate;
+	int ret;
+
+	rtc->clkin = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(rtc->clkin)) {
+		if (PTR_ERR(rtc->clkin) == -ENOENT)
+			rtc->clkin = NULL;
+		else
+			return dev_err_probe(dev, PTR_ERR(rtc->clkin),
+					     "error while clkin setup\n");
+	}
+
+	if (!rtc->clkin) {
+		switch (rtc->id) {
+		case ID_MAX31329:
+			return regmap_clear_bits(rtc->regmap,
+						 MAX31329_CONFIG2_REG,
+						 MAX31329_CONFIG2_CLKIN_EN);
+		case ID_MAX31341:
+		case ID_MAX31342:
+			return regmap_clear_bits(rtc->regmap,
+						 MAX31341_42_CONFIG1_REG,
+						 MAX31341_42_CONFIG1_CLKIN_EN);
+		default:
+			return 0;
+		}
+	}
+
+	rate = max313xx_find_clkin_freq_index(rtc->clkin);
+	if (rate < 0)
+		return dev_err_probe(dev, rate,
+				     "clkin cannot produce required frequency\n");
+
+	ret = clk_set_rate(rtc->clkin, max313xx_clkin_freq[rate]);
+	if (ret)
+		return ret;
+
+	switch (rtc->id) {
+	case ID_MAX31329:
+		ret = regmap_update_bits(rtc->regmap, MAX31329_CONFIG2_REG,
+					 MAX31329_CONFIG2_CLKIN_FREQ, rate);
+		if (ret)
+			return ret;
+
+		return regmap_set_bits(rtc->regmap, MAX31329_CONFIG2_REG,
+				       MAX31329_CONFIG2_CLKIN_EN);
+	case ID_MAX31341:
+	case ID_MAX31342:
+		ret = regmap_update_bits(rtc->regmap, MAX31341_42_CONFIG1_REG,
+					 MAX31341_42_CONFIG1_CLKIN_FREQ,
+					 FIELD_PREP(MAX31341_42_CONFIG1_CLKIN_FREQ, rate));
+		if (ret)
+			return ret;
+
+		return regmap_set_bits(rtc->regmap, MAX31341_42_CONFIG1_REG,
+				       MAX31341_42_CONFIG1_CLKIN_EN);
+	default:
+		rtc->clkin = NULL;
+		dev_warn(dev, "device does not have clock input\n");
+		return 0;
+	}
+}
+
+static int max313xx_irq_init(struct device *dev, const char *devname)
+{
+	struct max313xx *rtc = dev_get_drvdata(dev);
+	int ret;
+
+	switch (rtc->id) {
+	case ID_MAX31328:
+		break;
+	case ID_MAX31331:
+	case ID_MAX31334:
+		if (rtc->clkout.clk) {
+			/*
+			 * interrupt muxing depends on clkout so enable clkout
+			 * if configured before requesting interrupt
+			 */
+			ret = clk_prepare_enable(rtc->clkout.clk);
+			if (ret)
+				return dev_err_probe(dev, ret,
+						     "cannot enable clkout\n");
+		}
+		break;
+	default:
+		if (rtc->clkin) {
+			if (rtc->clkout.clk && rtc->irq > 0)
+				return dev_err_probe(dev, -EOPNOTSUPP,
+						     "irq not possible when both clkin and clkout are configured\n");
+
+			if (rtc->irq <= 0)
+				break;
+
+			/* clkout needs to be disabled for interrupt */
+			if (rtc->chip->clkout->en_invert)
+				ret = regmap_set_bits(rtc->regmap,
+						      rtc->chip->clkout->reg,
+						      rtc->chip->clkout->en_bit);
+			else
+				ret = regmap_clear_bits(rtc->regmap,
+							rtc->chip->clkout->reg,
+							rtc->chip->clkout->en_bit);
+
+			if (ret)
+				return ret;
+		}
+		break;
+	}
+
+	if (rtc->irq > 0) {
+		return devm_request_threaded_irq(dev, rtc->irq, NULL,
+						 &max313xx_irq, IRQF_ONESHOT,
+						 devname, rtc);
+	} else if (device_property_read_bool(dev, "wakeup-source")) {
+		clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtc->features);
+		return device_init_wakeup(dev, true);
+	}
+
+	clear_bit(RTC_FEATURE_ALARM, rtc->rtc->features);
 
 	return 0;
 }
 
-static int max31335_probe(struct i2c_client *client)
+static int max313xx_probe(struct i2c_client *client)
 {
-	struct max31335_data *max31335;
+	const struct i2c_device_id *id = i2c_client_get_device_id(client);
+	struct device *dev = &client->dev;
+	struct max313xx *max313xx;
 #if IS_REACHABLE(HWMON)
 	struct device *hwmon;
 #endif
+	const void *match;
 	int ret;
 
-	max31335 = devm_kzalloc(&client->dev, sizeof(*max31335), GFP_KERNEL);
-	if (!max31335)
+	max313xx = devm_kzalloc(&client->dev, sizeof(*max313xx), GFP_KERNEL);
+	if (!max313xx)
 		return -ENOMEM;
 
-	max31335->regmap = devm_regmap_init_i2c(client, &regmap_config);
-	if (IS_ERR(max31335->regmap))
-		return PTR_ERR(max31335->regmap);
+	dev_set_drvdata(&client->dev, max313xx);
 
-	i2c_set_clientdata(client, max31335);
-
-	max31335->rtc = devm_rtc_allocate_device(&client->dev);
-	if (IS_ERR(max31335->rtc))
-		return PTR_ERR(max31335->rtc);
-
-	max31335->rtc->ops = &max31335_rtc_ops;
-	max31335->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
-	max31335->rtc->range_max = RTC_TIMESTAMP_END_2199;
-	max31335->rtc->alarm_offset_max = 24 * 60 * 60;
-
-	ret = max31335_clkout_register(&client->dev);
-	if (ret)
-		return ret;
-
-	if (client->irq > 0) {
-		ret = devm_request_threaded_irq(&client->dev, client->irq,
-						NULL, max31335_handle_irq,
-						IRQF_ONESHOT,
-						"max31335", max31335);
-		if (ret) {
-			dev_warn(&client->dev,
-				 "unable to request IRQ, alarm max31335 disabled\n");
-			client->irq = 0;
-		}
+	max313xx->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(max313xx->regmap)) {
+		return dev_err_probe(dev, PTR_ERR(max313xx->regmap),
+				     "regmap init failed\n");
 	}
 
-	if (!client->irq)
-		clear_bit(RTC_FEATURE_ALARM, max31335->rtc->features);
+	i2c_set_clientdata(client, max313xx);
 
-	max31335_nvmem_cfg.priv = max31335;
-	ret = devm_rtc_nvmem_register(max31335->rtc, &max31335_nvmem_cfg);
-	if (ret)
-		return dev_err_probe(&client->dev, ret,
-				     "cannot register rtc nvmem\n");
+	match = device_get_match_data(dev);
+	if (match)
+		max313xx->chip = match;
+	else if (id)
+		max313xx->chip = (struct chip_desc *)id->driver_data;
+	else
+		return -ENODEV;
 
-#if IS_REACHABLE(HWMON)
-	hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name,
-						     max31335,
-						     &max31335_chip_info,
-						     NULL);
-	if (IS_ERR(hwmon))
-		return dev_err_probe(&client->dev, PTR_ERR(hwmon),
-				     "cannot register hwmon device\n");
-#endif
+	max313xx->id = max313xx->chip - chip;
 
-	ret = max31335_trickle_charger_setup(&client->dev, max31335);
+	ret = max313xx_init(max313xx);
 	if (ret)
 		return ret;
 
-	return devm_rtc_register_device(max31335->rtc);
+	max313xx->rtc = devm_rtc_allocate_device(dev);
+	if (IS_ERR(max313xx->rtc))
+		return PTR_ERR(max313xx->rtc);
+
+	max313xx->rtc->ops = &max3133x_rtc_ops;
+	max313xx->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	max313xx->rtc->range_max = RTC_TIMESTAMP_END_2199;
+
+	max313xx->irq = client->irq;
+
+	ret = max313xx_clkout_register(dev);
+	if (ret)
+		return ret;
+
+	ret = max313xx_clkin_init(dev);
+	if (ret)
+		return ret;
+
+	/* IRQ wiring depends on the clock configuration so parse them first */
+	ret = max313xx_irq_init(dev, client->name);
+	if (ret)
+		return ret;
+
+	if (max313xx->chip->ram_size) {
+		max313xx_nvmem_cfg.size = max313xx->chip->ram_size;
+		max313xx_nvmem_cfg.priv = max313xx;
+
+		ret = devm_rtc_nvmem_register(max313xx->rtc, &max313xx_nvmem_cfg);
+		if (ret)
+			dev_warn(dev, "cannot register rtc nvmem\n");
+	}
+
+#if IS_REACHABLE(HWMON)
+	if (max313xx->chip->temp_reg) {
+		hwmon = devm_hwmon_device_register_with_info(dev, client->name,
+							     max313xx,
+							     &max313xx_chip_info,
+							     NULL);
+		if (IS_ERR(hwmon))
+			dev_warn(dev, "cannot register hwmon device: %li\n",
+				 PTR_ERR(hwmon));
+	}
+#endif
+
+	ret = max313xx_trickle_charger_setup(dev);
+	if (ret)
+		return ret;
+
+	return devm_rtc_register_device(max313xx->rtc);
 }
 
-static const struct i2c_device_id max31335_id[] = {
-	{ "max31335", 0 },
+static const struct of_device_id max313xx_of_id[] = {
+	{ .compatible = "adi,max31328", .data = &chip[ID_MAX31328] },
+	{ .compatible = "adi,max31329", .data = &chip[ID_MAX31329] },
+	{ .compatible = "adi,max31331", .data = &chip[ID_MAX31331] },
+	{ .compatible = "adi,max31334", .data = &chip[ID_MAX31334] },
+	{ .compatible = "adi,max31335", .data = &chip[ID_MAX31335] },
+	{ .compatible = "adi,max31341", .data = &chip[ID_MAX31341] },
+	{ .compatible = "adi,max31342", .data = &chip[ID_MAX31342] },
+	{ .compatible = "adi,max31343", .data = &chip[ID_MAX31343] },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, max313xx_of_id);
 
-MODULE_DEVICE_TABLE(i2c, max31335_id);
-
-static const struct of_device_id max31335_of_match[] = {
-	{ .compatible = "adi,max31335" },
+static const struct i2c_device_id max313xx_id[] = {
+	{ "max31328", (kernel_ulong_t)&chip[ID_MAX31328] },
+	{ "max31329", (kernel_ulong_t)&chip[ID_MAX31329] },
+	{ "max31331", (kernel_ulong_t)&chip[ID_MAX31331] },
+	{ "max31334", (kernel_ulong_t)&chip[ID_MAX31334] },
+	{ "max31335", (kernel_ulong_t)&chip[ID_MAX31335] },
+	{ "max31341", (kernel_ulong_t)&chip[ID_MAX31341] },
+	{ "max31342", (kernel_ulong_t)&chip[ID_MAX31342] },
+	{ "max31343", (kernel_ulong_t)&chip[ID_MAX31343] },
 	{ }
 };
+MODULE_DEVICE_TABLE(i2c, max313xx_id);
 
-MODULE_DEVICE_TABLE(of, max31335_of_match);
-
-static struct i2c_driver max31335_driver = {
+static struct i2c_driver max313xx_driver = {
 	.driver = {
-		.name = "rtc-max31335",
-		.of_match_table = max31335_of_match,
+		.name	= "rtc-max31335",
+		.of_match_table = max313xx_of_id,
 	},
-	.probe = max31335_probe,
-	.id_table = max31335_id,
+	.probe		= max313xx_probe,
+	.id_table	= max313xx_id,
 };
-module_i2c_driver(max31335_driver);
+module_i2c_driver(max313xx_driver);
 
 MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
-MODULE_DESCRIPTION("MAX31335 RTC driver");
+MODULE_AUTHOR("Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>");
+MODULE_AUTHOR("Ibrahim Tilki <Ibrahim.Tilki@analog.com>");
+MODULE_DESCRIPTION("MAX313XX RTC driver");
+MODULE_SOFTDEP("pre: regmap-i2c");
 MODULE_LICENSE("GPL");