Эх сурвалжийг харах

Merge tag 'rtc-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "Core:
   - New sysfs interface to set and read clock offset
   - Drivers can now be both I2C and SPI (see pcf2127 and ds3232)

  New drivers:
   - Alphascale ASM9260
   - Epson RX6110SA
   - Maxim max20024 and max77620 (in max77686)
   - Microchip PIC32
   - NXP pcf2129 (in pcf2127)

  Subsystem wide cleanups:
   - remove IRQF_EARLY_RESUME when unecessary

  Drivers:
   - ds1307: clock output, temperature sensor and wakeup-source support
   - ds1685: actually spin forever in poweroff error path
   - ds3232: many cleanups
   - ds3234: merged in ds3232
   - hym8563: fix invalid year calculation
   - max77686: many cleanups
   - max77802 merged in max77686
   - pcf2123: cleanups and offset support
   - pcf85063: cleanups
   - pcf8523: propely handle oscillator stop bit
   - rv3029: many cleanups, trickle charger and temperature sensor support
   - rv8803: convert spin_lock to mutex_lock
   - rx8025: many fixes
   - vr41xx: restore alarm_irq_enable"

* tag 'rtc-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (86 commits)
  rtc: pcf2127: add pcf2129 device id
  rtc: pcf2127: add support for spi interface
  rtc: pcf2127: convert to use regmap
  rtc: rv3029: Add thermometer hwmon support
  rtc: rv3029: Add update_bits helper for eeprom access
  rtc: ds1685: actually spin forever in poweroff error path
  rtc: hym8563: fix invalid year calculation
  rtc: ds3232: use rtc->ops_lock to protect alarm operations
  rtc: ds3232: fix issue when irq is shared several devices
  rtc: ds3232: remove unused UIE code
  rtc: ds3232: add register access error checks
  rtc: ds3232: fix read on /dev/rtc after RTC_AIE_ON
  rtc: merge ds3232 and ds3234
  rtc: ds3232: convert to use regmap
  rtc: pxa: fix Kconfig indentation
  rtc: rv3029: Add device tree property for trickle charger
  rtc: rv3029: Add functions for EEPROM access
  rtc: rv3029: Add i2c register update-bits helper
  rtc: rv3029: Add missing register definitions
  rtc: rv3029: Add "rv3029" I2C device id
  ...
Linus Torvalds 9 жил өмнө
parent
commit
13f6f62f61
40 өөрчлөгдсөн 3854 нэмэгдсэн , 1653 устгасан
  1. 19 0
      Documentation/devicetree/bindings/rtc/alphascale,asm9260-rtc.txt
  2. 39 0
      Documentation/devicetree/bindings/rtc/epson,rx6110.txt
  3. 37 0
      Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
  4. 21 0
      Documentation/devicetree/bindings/rtc/microchip,pic32-rtc.txt
  5. 6 0
      Documentation/rtc.txt
  6. 3 83
      drivers/mfd/max77686.c
  7. 148 104
      drivers/rtc/Kconfig
  8. 3 2
      drivers/rtc/Makefile
  9. 0 13
      drivers/rtc/class.c
  10. 54 0
      drivers/rtc/interface.c
  11. 1 1
      drivers/rtc/rtc-as3722.c
  12. 355 0
      drivers/rtc/rtc-asm9260.c
  13. 2 2
      drivers/rtc/rtc-ds1305.c
  14. 409 2
      drivers/rtc/rtc-ds1307.c
  15. 5 4
      drivers/rtc/rtc-ds1685.c
  16. 283 193
      drivers/rtc/rtc-ds3232.c
  17. 0 171
      drivers/rtc/rtc-ds3234.c
  18. 11 1
      drivers/rtc/rtc-generic.c
  19. 1 1
      drivers/rtc/rtc-hym8563.c
  20. 450 115
      drivers/rtc/rtc-max77686.c
  21. 0 502
      drivers/rtc/rtc-max77802.c
  22. 0 1
      drivers/rtc/rtc-mt6397.c
  23. 1 2
      drivers/rtc/rtc-palmas.c
  24. 194 77
      drivers/rtc/rtc-pcf2123.c
  25. 263 72
      drivers/rtc/rtc-pcf2127.c
  26. 86 76
      drivers/rtc/rtc-pcf85063.c
  27. 3 22
      drivers/rtc/rtc-pcf8523.c
  28. 411 0
      drivers/rtc/rtc-pic32.c
  29. 556 167
      drivers/rtc/rtc-rv3029c2.c
  30. 18 21
      drivers/rtc/rtc-rv8803.c
  31. 402 0
      drivers/rtc/rtc-rx6110.c
  32. 21 4
      drivers/rtc/rtc-rx8025.c
  33. 4 4
      drivers/rtc/rtc-s5m.c
  34. 34 1
      drivers/rtc/rtc-sysfs.c
  35. 1 1
      drivers/rtc/rtc-tps6586x.c
  36. 1 1
      drivers/rtc/rtc-tps65910.c
  37. 1 1
      drivers/rtc/rtc-tps80031.c
  38. 7 6
      drivers/rtc/rtc-vr41xx.c
  39. 0 3
      include/linux/mfd/max77686-private.h
  40. 4 0
      include/linux/rtc.h

+ 19 - 0
Documentation/devicetree/bindings/rtc/alphascale,asm9260-rtc.txt

@@ -0,0 +1,19 @@
+* Alphascale asm9260 SoC Real Time Clock
+
+Required properties:
+- compatible: Should be "alphascale,asm9260-rtc"
+- reg: Physical base address of the controller and length
+       of memory mapped region.
+- interrupts: IRQ line for the RTC.
+- clocks: Reference to the clock entry.
+- clock-names: should contain:
+  * "ahb" for the SoC RTC clock
+
+Example:
+rtc0: rtc@800a0000 {
+	compatible = "alphascale,asm9260-rtc";
+	reg = <0x800a0000 0x100>;
+	clocks = <&acc CLKID_AHB_RTC>;
+	clock-names = "ahb";
+	interrupts = <2>;
+};

+ 39 - 0
Documentation/devicetree/bindings/rtc/epson,rx6110.txt

@@ -0,0 +1,39 @@
+Epson RX6110 Real Time Clock
+============================
+
+The Epson RX6110 can be used with SPI or I2C busses. The kind of
+bus depends on the SPISEL pin and can not be configured via software.
+
+I2C mode
+--------
+
+Required properties:
+  - compatible: should be: "epson,rx6110"
+  - reg : the I2C address of the device for I2C
+
+Example:
+
+	rtc: rtc@32 {
+		compatible = "epson,rx6110"
+		reg = <0x32>;
+	};
+
+SPI mode
+--------
+
+Required properties:
+  - compatible: should be: "epson,rx6110"
+  - reg: chip select number
+  - spi-cs-high: RX6110 needs chipselect high
+  - spi-cpha: RX6110 works with SPI shifted clock phase
+  - spi-cpol: RX6110 works with SPI inverse clock polarity
+
+Example:
+
+	rtc: rtc@3 {
+		compatible = "epson,rx6110"
+		reg = <3>
+		spi-cs-high;
+		spi-cpha;
+		spi-cpol;
+	};

+ 37 - 0
Documentation/devicetree/bindings/rtc/maxim,ds3231.txt

@@ -0,0 +1,37 @@
+* Maxim DS3231 Real Time Clock
+
+Required properties:
+see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+
+Optional property:
+- #clock-cells: Should be 1.
+- clock-output-names:
+  overwrite the default clock names "ds3231_clk_sqw" and "ds3231_clk_32khz".
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. Following indices are allowed:
+    - 0: square-wave output on the SQW pin
+    - 1: square-wave output on the 32kHz pin
+
+- interrupts: rtc alarm/event interrupt. When this property is selected,
+  clock on the SQW pin cannot be used.
+
+Example:
+
+ds3231: ds3231@51 {
+	compatible = "maxim,ds3231";
+	reg = <0x68>;
+	#clock-cells = <1>;
+};
+
+device1 {
+...
+	clocks = <&ds3231 0>;
+...
+};
+
+device2 {
+...
+	clocks = <&ds3231 1>;
+...
+};

+ 21 - 0
Documentation/devicetree/bindings/rtc/microchip,pic32-rtc.txt

@@ -0,0 +1,21 @@
+* Microchip PIC32 Real Time Clock and Calendar
+
+The RTCC keeps time in hours, minutes, and seconds, and one half second. It
+provides a calendar in weekday, date, month, and year. It also provides a
+configurable alarm.
+
+Required properties:
+- compatible: should be: "microchip,pic32mzda-rtc"
+- reg: physical base address of the controller and length of memory mapped
+    region.
+- interrupts: RTC alarm/event interrupt
+- clocks: clock phandle
+
+Example:
+
+	rtc: rtc@1f8c0000 {
+		compatible = "microchip,pic32mzda-rtc";
+		reg = <0x1f8c0000 0x60>;
+		interrupts = <166 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&PBCLK6>;
+	};

+ 6 - 0
Documentation/rtc.txt

@@ -157,6 +157,12 @@ wakealarm:	 The time at which the clock will generate a system wakeup
 		 the epoch by default, or if there's a leading +, seconds in the
 		 future, or if there is a leading +=, seconds ahead of the current
 		 alarm.
+offset:		 The amount which the rtc clock has been adjusted in firmware.
+		 Visible only if the driver supports clock offset adjustment.
+		 The unit is parts per billion, i.e. The number of clock ticks
+		 which are added to or removed from the rtc's base clock per
+		 billion ticks. A positive value makes a day pass more slowly,
+		 longer, and a negative value makes a day pass more quickly.
 
 IOCTL INTERFACE
 ---------------

+ 3 - 83
drivers/mfd/max77686.c

@@ -35,8 +35,6 @@
 #include <linux/err.h>
 #include <linux/of.h>
 
-#define I2C_ADDR_RTC	(0x0C >> 1)
-
 static const struct mfd_cell max77686_devs[] = {
 	{ .name = "max77686-pmic", },
 	{ .name = "max77686-rtc", },
@@ -116,11 +114,6 @@ static const struct regmap_config max77686_regmap_config = {
 	.val_bits = 8,
 };
 
-static const struct regmap_config max77686_rtc_regmap_config = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
 static const struct regmap_config max77802_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -156,25 +149,6 @@ static const struct regmap_irq_chip max77686_irq_chip = {
 	.num_irqs		= ARRAY_SIZE(max77686_irqs),
 };
 
-static const struct regmap_irq max77686_rtc_irqs[] = {
-	/* RTC interrupts */
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
-	{ .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
-};
-
-static const struct regmap_irq_chip max77686_rtc_irq_chip = {
-	.name			= "max77686-rtc",
-	.status_base		= MAX77686_RTC_INT,
-	.mask_base		= MAX77686_RTC_INTM,
-	.num_regs		= 1,
-	.irqs			= max77686_rtc_irqs,
-	.num_irqs		= ARRAY_SIZE(max77686_rtc_irqs),
-};
-
 static const struct regmap_irq_chip max77802_irq_chip = {
 	.name			= "max77802-pmic",
 	.status_base		= MAX77802_REG_INT1,
@@ -184,15 +158,6 @@ static const struct regmap_irq_chip max77802_irq_chip = {
 	.num_irqs		= ARRAY_SIZE(max77686_irqs),
 };
 
-static const struct regmap_irq_chip max77802_rtc_irq_chip = {
-	.name			= "max77802-rtc",
-	.status_base		= MAX77802_RTC_INT,
-	.mask_base		= MAX77802_RTC_INTM,
-	.num_regs		= 1,
-	.irqs			= max77686_rtc_irqs, /* same masks as 77686 */
-	.num_irqs		= ARRAY_SIZE(max77686_rtc_irqs),
-};
-
 static const struct of_device_id max77686_pmic_dt_match[] = {
 	{
 		.compatible = "maxim,max77686",
@@ -214,8 +179,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
 	int ret = 0;
 	const struct regmap_config *config;
 	const struct regmap_irq_chip *irq_chip;
-	const struct regmap_irq_chip *rtc_irq_chip;
-	struct regmap **rtc_regmap;
 	const struct mfd_cell *cells;
 	int n_devs;
 
@@ -242,15 +205,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
 	if (max77686->type == TYPE_MAX77686) {
 		config = &max77686_regmap_config;
 		irq_chip = &max77686_irq_chip;
-		rtc_irq_chip = &max77686_rtc_irq_chip;
-		rtc_regmap = &max77686->rtc_regmap;
 		cells =  max77686_devs;
 		n_devs = ARRAY_SIZE(max77686_devs);
 	} else {
 		config = &max77802_regmap_config;
 		irq_chip = &max77802_irq_chip;
-		rtc_irq_chip = &max77802_rtc_irq_chip;
-		rtc_regmap = &max77686->regmap;
 		cells =  max77802_devs;
 		n_devs = ARRAY_SIZE(max77802_devs);
 	}
@@ -270,60 +229,25 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
 		return -ENODEV;
 	}
 
-	if (max77686->type == TYPE_MAX77686) {
-		max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
-		if (!max77686->rtc) {
-			dev_err(max77686->dev,
-				"Failed to allocate I2C device for RTC\n");
-			return -ENODEV;
-		}
-		i2c_set_clientdata(max77686->rtc, max77686);
-
-		max77686->rtc_regmap =
-			devm_regmap_init_i2c(max77686->rtc,
-					     &max77686_rtc_regmap_config);
-		if (IS_ERR(max77686->rtc_regmap)) {
-			ret = PTR_ERR(max77686->rtc_regmap);
-			dev_err(max77686->dev,
-				"failed to allocate RTC regmap: %d\n",
-				ret);
-			goto err_unregister_i2c;
-		}
-	}
-
 	ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
 				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
 				  IRQF_SHARED, 0, irq_chip,
 				  &max77686->irq_data);
-	if (ret) {
+	if (ret < 0) {
 		dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
-		goto err_unregister_i2c;
-	}
-
-	ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
-				  IRQF_SHARED, 0, rtc_irq_chip,
-				  &max77686->rtc_irq_data);
-	if (ret) {
-		dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
-		goto err_del_irqc;
+		return ret;
 	}
 
 	ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
 	if (ret < 0) {
 		dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
-		goto err_del_rtc_irqc;
+		goto err_del_irqc;
 	}
 
 	return 0;
 
-err_del_rtc_irqc:
-	regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
 err_del_irqc:
 	regmap_del_irq_chip(max77686->irq, max77686->irq_data);
-err_unregister_i2c:
-	if (max77686->type == TYPE_MAX77686)
-		i2c_unregister_device(max77686->rtc);
 
 	return ret;
 }
@@ -334,12 +258,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
 
 	mfd_remove_devices(max77686->dev);
 
-	regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
 	regmap_del_irq_chip(max77686->irq, max77686->irq_data);
 
-	if (max77686->type == TYPE_MAX77686)
-		i2c_unregister_device(max77686->rtc);
-
 	return 0;
 }
 

+ 148 - 104
drivers/rtc/Kconfig

@@ -140,7 +140,6 @@ config RTC_DRV_TEST
 	  will be called rtc-test.
 
 comment "I2C RTC drivers"
-	depends on I2C
 
 if I2C
 
@@ -212,6 +211,15 @@ config RTC_DRV_DS1307
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1307.
 
+config RTC_DRV_DS1307_HWMON
+	bool "HWMON support for rtc-ds1307"
+	depends on RTC_DRV_DS1307 && HWMON
+	depends on !(RTC_DRV_DS1307=y && HWMON=m)
+	default y
+	help
+	  Say Y here if you want to expose temperature sensor data on
+	  rtc-ds1307 (only DS3231)
+
 config RTC_DRV_DS1374
 	tristate "Dallas/Maxim DS1374"
 	help
@@ -239,16 +247,6 @@ config RTC_DRV_DS1672
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1672.
 
-config RTC_DRV_DS3232
-	tristate "Dallas/Maxim DS3232"
-	help
-	  If you say yes here you get support for Dallas Semiconductor
-	  DS3232 real-time clock chips. If an interrupt is associated
-	  with the device, the alarm functionality is supported.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called rtc-ds3232.
-
 config RTC_DRV_HYM8563
 	tristate "Haoyu Microelectronics HYM8563"
 	depends on OF
@@ -317,10 +315,10 @@ config RTC_DRV_MAX8997
 
 config RTC_DRV_MAX77686
 	tristate "Maxim MAX77686"
-	depends on MFD_MAX77686
+	depends on MFD_MAX77686 || MFD_MAX77620
 	help
 	  If you say yes here you will get support for the
-	  RTC of Maxim MAX77686 PMIC.
+	  RTC of Maxim MAX77686/MAX77620/MAX77802 PMIC.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-max77686.
@@ -335,16 +333,6 @@ config RTC_DRV_RK808
 	  This driver can also be built as a module. If so, the module
 	  will be called rk808-rtc.
 
-config RTC_DRV_MAX77802
-	tristate "Maxim 77802 RTC"
-	depends on MFD_MAX77686
-	help
-	  If you say yes here you will get support for the
-	  RTC of Maxim MAX77802 PMIC.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-max77802.
-
 config RTC_DRV_RS5C372
 	tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
 	help
@@ -391,25 +379,6 @@ config RTC_DRV_X1205
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-x1205.
 
-config RTC_DRV_PALMAS
-	tristate "TI Palmas RTC driver"
-	depends on MFD_PALMAS
-	help
-	  If you say yes here you get support for the RTC of TI PALMA series PMIC
-	  chips.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-palma.
-
-config RTC_DRV_PCF2127
-	tristate "NXP PCF2127"
-	help
-	  If you say yes here you get support for the NXP PCF2127/29 RTC
-	  chips.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-pcf2127.
-
 config RTC_DRV_PCF8523
 	tristate "NXP PCF8523"
 	help
@@ -419,6 +388,14 @@ config RTC_DRV_PCF8523
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8523.
 
+config RTC_DRV_PCF85063
+	tristate "NXP PCF85063"
+	help
+	  If you say yes here you get support for the PCF85063 RTC chip
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf85063.
+
 config RTC_DRV_PCF8563
 	tristate "Philips PCF8563/Epson RTC8564"
 	help
@@ -429,14 +406,6 @@ config RTC_DRV_PCF8563
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8563.
 
-config RTC_DRV_PCF85063
-	tristate "nxp PCF85063"
-	help
-	  If you say yes here you get support for the PCF85063 RTC chip
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-pcf85063.
-
 config RTC_DRV_PCF8583
 	tristate "Philips PCF8583"
 	help
@@ -501,6 +470,16 @@ config RTC_DRV_TWL4030
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-twl.
 
+config RTC_DRV_PALMAS
+	tristate "TI Palmas RTC driver"
+	depends on MFD_PALMAS
+	help
+	  If you say yes here you get support for the RTC of TI PALMA series PMIC
+	  chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-palma.
+
 config RTC_DRV_TPS6586X
 	tristate "TI TPS6586X RTC driver"
 	depends on MFD_TPS6586X
@@ -595,14 +574,23 @@ config RTC_DRV_EM3027
 	  will be called rtc-em3027.
 
 config RTC_DRV_RV3029C2
-	tristate "Micro Crystal RTC"
+	tristate "Micro Crystal RV3029"
 	help
 	  If you say yes here you get support for the Micro Crystal
-	  RV3029-C2 RTC chips.
+	  RV3029 RTC chips.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rv3029c2.
 
+config RTC_DRV_RV3029_HWMON
+	bool "HWMON support for RV3029"
+	depends on RTC_DRV_RV3029C2 && HWMON
+	depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
+	default y
+	help
+	  Say Y here if you want to expose temperature sensor data on
+	  rtc-rv3029c2.
+
 config RTC_DRV_RV8803
 	tristate "Micro Crystal RV8803"
 	help
@@ -691,15 +679,6 @@ config RTC_DRV_DS1390
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1390.
 
-config RTC_DRV_MAX6902
-	tristate "Maxim MAX6902"
-	help
-	  If you say yes here you will get support for the
-	  Maxim MAX6902 SPI RTC chip.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-max6902.
-
 config RTC_DRV_R9701
 	tristate "Epson RTC-9701JE"
 	help
@@ -709,6 +688,23 @@ config RTC_DRV_R9701
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-r9701.
 
+config RTC_DRV_RX4581
+	tristate "Epson RX-4581"
+	help
+	  If you say yes here you will get support for the Epson RX-4581.
+
+	  This driver can also be built as a module. If so the module
+	  will be called rtc-rx4581.
+
+config RTC_DRV_RX6110
+	tristate "Epson RX-6110"
+	select REGMAP_SPI
+	help
+	  If you say yes here you will get support for the Epson RX-6610.
+
+	  This driver can also be built as a module. If so the module
+	  will be called rtc-rx6110.
+
 config RTC_DRV_RS5C348
 	tristate "Ricoh RS5C348A/B"
 	help
@@ -718,14 +714,14 @@ config RTC_DRV_RS5C348
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rs5c348.
 
-config RTC_DRV_DS3234
-	tristate "Maxim/Dallas DS3234"
+config RTC_DRV_MAX6902
+	tristate "Maxim MAX6902"
 	help
-	  If you say yes here you get support for the
-	  Maxim/Dallas DS3234 SPI RTC chip.
+	  If you say yes here you will get support for the
+	  Maxim MAX6902 SPI RTC chip.
 
 	  This driver can also be built as a module. If so, the module
-	  will be called rtc-ds3234.
+	  will be called rtc-max6902.
 
 config RTC_DRV_PCF2123
 	tristate "NXP PCF2123"
@@ -736,14 +732,6 @@ config RTC_DRV_PCF2123
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf2123.
 
-config RTC_DRV_RX4581
-	tristate "Epson RX-4581"
-	help
-	  If you say yes here you will get support for the Epson RX-4581.
-
-	  This driver can also be built as a module. If so the module
-	  will be called rtc-rx4581.
-
 config RTC_DRV_MCP795
 	tristate "Microchip MCP795"
 	help
@@ -754,6 +742,41 @@ config RTC_DRV_MCP795
 
 endif # SPI_MASTER
 
+#
+# Helper to resolve issues with configs that have SPI enabled but I2C
+# modular.  See SND_SOC_I2C_AND_SPI for more information
+#
+config RTC_I2C_AND_SPI
+	tristate
+	default m if I2C=m
+	default y if I2C=y
+	default y if SPI_MASTER=y
+	select REGMAP_I2C if I2C
+	select REGMAP_SPI if SPI_MASTER
+
+comment "SPI and I2C RTC drivers"
+
+config RTC_DRV_DS3232
+	tristate "Dallas/Maxim DS3232/DS3234"
+	depends on RTC_I2C_AND_SPI
+	help
+	  If you say yes here you get support for Dallas Semiconductor
+	  DS3232 and DS3234 real-time clock chips. If an interrupt is associated
+	  with the device, the alarm functionality is supported.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called rtc-ds3232.
+
+config RTC_DRV_PCF2127
+	tristate "NXP PCF2127"
+	depends on RTC_I2C_AND_SPI
+	help
+	  If you say yes here you get support for the NXP PCF2127/29 RTC
+	  chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf2127.
+
 comment "Platform RTC drivers"
 
 # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
@@ -1087,7 +1110,7 @@ config RTC_DRV_WM8350
 
 config RTC_DRV_SPEAR
 	tristate "SPEAR ST RTC"
-	depends on PLAT_SPEAR
+	depends on PLAT_SPEAR || COMPILE_TEST
 	default y
 	help
 	 If you say Y here you will get support for the RTC found on
@@ -1119,7 +1142,7 @@ config RTC_DRV_AB8500
 
 config RTC_DRV_NUC900
 	tristate "NUC910/NUC920 RTC driver"
-	depends on ARCH_W90X900
+	depends on ARCH_W90X900 || COMPILE_TEST
 	help
 	  If you say yes here you get support for the RTC subsystem of the
 	  NUC910/NUC920 used in embedded systems.
@@ -1144,9 +1167,19 @@ config RTC_DRV_ZYNQMP
 
 comment "on-CPU RTC drivers"
 
+config RTC_DRV_ASM9260
+	tristate "Alphascale asm9260 RTC"
+	depends on MACH_ASM9260
+	help
+	  If you say yes here you get support for the RTC on the
+	  Alphascale asm9260 SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-asm9260.
+
 config RTC_DRV_DAVINCI
 	tristate "TI DaVinci RTC"
-	depends on ARCH_DAVINCI_DM365
+	depends on ARCH_DAVINCI_DM365 || COMPILE_TEST
 	help
 	  If you say yes here you get support for the RTC on the
 	  DaVinci platforms (DM365).
@@ -1156,7 +1189,7 @@ config RTC_DRV_DAVINCI
 
 config RTC_DRV_DIGICOLOR
 	tristate "Conexant Digicolor RTC"
-	depends on ARCH_DIGICOLOR
+	depends on ARCH_DIGICOLOR || COMPILE_TEST
 	help
 	  If you say yes here you get support for the RTC on Conexant
 	  Digicolor platforms. This currently includes the CX92755 SoC.
@@ -1175,7 +1208,7 @@ config RTC_DRV_IMXDI
 
 config RTC_DRV_OMAP
 	tristate "TI OMAP Real Time Clock"
-	depends on ARCH_OMAP || ARCH_DAVINCI
+	depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
 	help
 	  Say "yes" here to support the on chip real time clock
 	  present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
@@ -1192,7 +1225,7 @@ config HAVE_S3C_RTC
 
 config RTC_DRV_S3C
 	tristate "Samsung S3C series SoC RTC"
-	depends on ARCH_S3C64XX || HAVE_S3C_RTC
+	depends on ARCH_S3C64XX || HAVE_S3C_RTC || COMPILE_TEST
 	help
 	  RTC (Realtime Clock) driver for the clock inbuilt into the
 	  Samsung S3C24XX series of SoCs. This can provide periodic
@@ -1208,7 +1241,7 @@ config RTC_DRV_S3C
 
 config RTC_DRV_EP93XX
 	tristate "Cirrus Logic EP93XX"
-	depends on ARCH_EP93XX
+	depends on ARCH_EP93XX || COMPILE_TEST
 	help
 	  If you say yes here you get support for the
 	  RTC embedded in the Cirrus Logic EP93XX processors.
@@ -1238,7 +1271,7 @@ config RTC_DRV_SH
 
 config RTC_DRV_VR41XX
 	tristate "NEC VR41XX"
-	depends on CPU_VR41XX
+	depends on CPU_VR41XX || COMPILE_TEST
 	help
 	  If you say Y here you will get access to the real time clock
 	  built into your NEC VR41XX CPU.
@@ -1268,14 +1301,14 @@ config RTC_DRV_PL031
 
 config RTC_DRV_AT32AP700X
 	tristate "AT32AP700X series RTC"
-	depends on PLATFORM_AT32AP
+	depends on PLATFORM_AT32AP || COMPILE_TEST
 	help
 	  Driver for the internal RTC (Realtime Clock) on Atmel AVR32
 	  AT32AP700x family processors.
 
 config RTC_DRV_AT91RM9200
 	tristate "AT91RM9200 or some AT91SAM9 RTC"
-	depends on ARCH_AT91
+	depends on ARCH_AT91 || COMPILE_TEST
 	help
 	  Driver for the internal RTC (Realtime Clock) module found on
 	  Atmel AT91RM9200's and some  AT91SAM9 chips. On AT91SAM9 chips
@@ -1283,7 +1316,7 @@ config RTC_DRV_AT91RM9200
 
 config RTC_DRV_AT91SAM9
 	tristate "AT91SAM9 RTT as RTC"
-	depends on ARCH_AT91
+	depends on ARCH_AT91 || COMPILE_TEST
 	select MFD_SYSCON
 	help
 	  Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
@@ -1325,17 +1358,17 @@ config RTC_DRV_GENERIC
 	tristate "Generic RTC support"
 	# Please consider writing a new RTC driver instead of using the generic
 	# RTC abstraction
-	depends on PARISC || M68K || PPC || SUPERH32
+	depends on PARISC || M68K || PPC || SUPERH32 || COMPILE_TEST
 	help
 	  Say Y or M here to enable RTC support on systems using the generic
 	  RTC abstraction. If you do not know what you are doing, you should
 	  just say Y.
 
 config RTC_DRV_PXA
-       tristate "PXA27x/PXA3xx"
-       depends on ARCH_PXA
-       select RTC_DRV_SA1100
-       help
+	tristate "PXA27x/PXA3xx"
+	depends on ARCH_PXA
+	select RTC_DRV_SA1100
+	help
          If you say Y here you will get access to the real time clock
          built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
          consisting of an SA1100 compatible RTC and the extended PXA RTC.
@@ -1345,7 +1378,7 @@ config RTC_DRV_PXA
 
 config RTC_DRV_VT8500
 	tristate "VIA/WonderMedia 85xx SoC RTC"
-	depends on ARCH_VT8500
+	depends on ARCH_VT8500 || COMPILE_TEST
 	help
 	  If you say Y here you will get access to the real time clock
 	  built into your VIA VT8500 SoC or its relatives.
@@ -1360,14 +1393,15 @@ config RTC_DRV_SUN4V
 
 config RTC_DRV_SUN6I
 	tristate "Allwinner A31 RTC"
-	depends on MACH_SUN6I || MACH_SUN8I
+	default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
+	depends on ARCH_SUNXI
 	help
-	  If you say Y here you will get support for the RTC found on
-	  Allwinner A31.
+	  If you say Y here you will get support for the RTC found in
+	  some Allwinner SoCs like the A31 or the A64.
 
 config RTC_DRV_SUNXI
 	tristate "Allwinner sun4i/sun7i RTC"
-	depends on MACH_SUN4I || MACH_SUN7I
+	depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
 	help
 	  If you say Y here you will get support for the RTC found on
 	  Allwinner A10/A20.
@@ -1388,7 +1422,7 @@ config RTC_DRV_TX4939
 
 config RTC_DRV_MV
 	tristate "Marvell SoC RTC"
-	depends on ARCH_DOVE || ARCH_MVEBU
+	depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
 	help
 	  If you say yes here you will get support for the in-chip RTC
 	  that can be found in some of Marvell's SoC devices, such as
@@ -1399,7 +1433,7 @@ config RTC_DRV_MV
 
 config RTC_DRV_ARMADA38X
 	tristate "Armada 38x Marvell SoC RTC"
-	depends on ARCH_MVEBU
+	depends on ARCH_MVEBU || COMPILE_TEST
 	help
 	  If you say yes here you will get support for the in-chip RTC
 	  that can be found in the Armada 38x Marvell's SoC device
@@ -1429,7 +1463,7 @@ config RTC_DRV_PS3
 
 config RTC_DRV_COH901331
 	tristate "ST-Ericsson COH 901 331 RTC"
-	depends on ARCH_U300
+	depends on ARCH_U300 || COMPILE_TEST
 	help
 	  If you say Y here you will get access to ST-Ericsson
 	  COH 901 331 RTC clock found in some ST-Ericsson Mobile
@@ -1441,7 +1475,7 @@ config RTC_DRV_COH901331
 
 config RTC_DRV_STMP
 	tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
-	depends on ARCH_MXS
+	depends on ARCH_MXS || COMPILE_TEST
 	select STMP_DEVICE
 	help
 	  If you say yes here you will get support for the onboard
@@ -1476,7 +1510,7 @@ config RTC_DRV_MPC5121
 
 config RTC_DRV_JZ4740
 	tristate "Ingenic JZ4740 SoC"
-	depends on MACH_JZ4740
+	depends on MACH_JZ4740 || COMPILE_TEST
 	help
 	  If you say yes here you get support for the Ingenic JZ4740 SoC RTC
 	  controller.
@@ -1497,7 +1531,7 @@ config RTC_DRV_LPC24XX
 	  so, the module will be called rtc-lpc24xx.
 
 config RTC_DRV_LPC32XX
-	depends on ARCH_LPC32XX
+	depends on ARCH_LPC32XX || COMPILE_TEST
 	tristate "NXP LPC32XX RTC"
 	help
 	  This enables support for the NXP RTC in the LPC32XX
@@ -1507,7 +1541,7 @@ config RTC_DRV_LPC32XX
 
 config RTC_DRV_PM8XXX
 	tristate "Qualcomm PMIC8XXX RTC"
-	depends on MFD_PM8XXX || MFD_SPMI_PMIC
+	depends on MFD_PM8XXX || MFD_SPMI_PMIC || COMPILE_TEST
 	help
 	  If you say yes here you get support for the
 	  Qualcomm PMIC8XXX RTC.
@@ -1517,7 +1551,7 @@ config RTC_DRV_PM8XXX
 
 config RTC_DRV_TEGRA
 	tristate "NVIDIA Tegra Internal RTC driver"
-	depends on ARCH_TEGRA
+	depends on ARCH_TEGRA || COMPILE_TEST
 	help
 	  If you say yes here you get support for the
 	  Tegra 200 series internal RTC module.
@@ -1603,7 +1637,7 @@ config RTC_DRV_MOXART
 
 config RTC_DRV_MT6397
 	tristate "Mediatek Real Time Clock driver"
-	depends on MFD_MT6397 || COMPILE_TEST
+	depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
 	help
 	  This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
 	  MT6397 PMIC. You should enable MT6397 PMIC MFD before select
@@ -1622,6 +1656,16 @@ config RTC_DRV_XGENE
 	  This driver can also be built as a module, if so, the module
 	  will be called "rtc-xgene".
 
+config RTC_DRV_PIC32
+	tristate "Microchip PIC32 RTC"
+	depends on MACH_PIC32
+	default y
+	help
+	   If you say yes here you get support for the PIC32 RTC module.
+
+	   This driver can also be built as a module. If so, the module
+	   will be called rtc-pic32
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME

+ 3 - 2
drivers/rtc/Makefile

@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_ABB5ZES3)	+= rtc-ab-b5ze-s3.o
 obj-$(CONFIG_RTC_DRV_ABX80X)	+= rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)	+= rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)	+= rtc-as3722.o
+obj-$(CONFIG_RTC_DRV_ASM9260)	+= rtc-asm9260.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_AT91SAM9)	+= rtc-at91sam9.o
@@ -59,7 +60,6 @@ obj-$(CONFIG_RTC_DRV_DS1685_FAMILY)	+= rtc-ds1685.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
 obj-$(CONFIG_RTC_DRV_DS2404)	+= rtc-ds2404.o
 obj-$(CONFIG_RTC_DRV_DS3232)	+= rtc-ds3232.o
-obj-$(CONFIG_RTC_DRV_DS3234)	+= rtc-ds3234.o
 obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EM3027)	+= rtc-em3027.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
@@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MAX77686)	+= rtc-max77686.o
-obj-$(CONFIG_RTC_DRV_MAX77802)	+= rtc-max77802.o
 obj-$(CONFIG_RTC_DRV_MAX8907)	+= rtc-max8907.o
 obj-$(CONFIG_RTC_DRV_MAX8925)	+= rtc-max8925.o
 obj-$(CONFIG_RTC_DRV_MAX8997)	+= rtc-max8997.o
@@ -112,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_PCF85063)	+= rtc-pcf85063.o
 obj-$(CONFIG_RTC_DRV_PCF8523)	+= rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
+obj-$(CONFIG_RTC_DRV_PIC32)	+= rtc-pic32.o
 obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o
@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o
 obj-$(CONFIG_RTC_DRV_RV8803)	+= rtc-rv8803.o
 obj-$(CONFIG_RTC_DRV_RX4581)	+= rtc-rx4581.o
+obj-$(CONFIG_RTC_DRV_RX6110)	+= rtc-rx6110.o
 obj-$(CONFIG_RTC_DRV_RX8010)	+= rtc-rx8010.o
 obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o

+ 0 - 13
drivers/rtc/class.c

@@ -361,17 +361,4 @@ static int __init rtc_init(void)
 	rtc_dev_init();
 	return 0;
 }
-
-static void __exit rtc_exit(void)
-{
-	rtc_dev_exit();
-	class_destroy(rtc_class);
-	ida_destroy(&rtc_ida);
-}
-
 subsys_initcall(rtc_init);
-module_exit(rtc_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("RTC class support");
-MODULE_LICENSE("GPL");

+ 54 - 0
drivers/rtc/interface.c

@@ -939,4 +939,58 @@ void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
 	mutex_unlock(&rtc->ops_lock);
 }
 
+/**
+ * rtc_read_offset - Read the amount of rtc offset in parts per billion
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * see below for details.
+ *
+ * Kernel interface to read rtc clock offset
+ * Returns 0 on success, or a negative number on error.
+ * If read_offset() is not implemented for the rtc, return -EINVAL
+ */
+int rtc_read_offset(struct rtc_device *rtc, long *offset)
+{
+	int ret;
+
+	if (!rtc->ops)
+		return -ENODEV;
+
+	if (!rtc->ops->read_offset)
+		return -EINVAL;
+
+	mutex_lock(&rtc->ops_lock);
+	ret = rtc->ops->read_offset(rtc->dev.parent, offset);
+	mutex_unlock(&rtc->ops_lock);
+	return ret;
+}
 
+/**
+ * rtc_set_offset - Adjusts the duration of the average second
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * Some rtc's allow an adjustment to the average duration of a second
+ * to compensate for differences in the actual clock rate due to temperature,
+ * the crystal, capacitor, etc.
+ *
+ * Kernel interface to adjust an rtc clock offset.
+ * Return 0 on success, or a negative number on error.
+ * If the rtc offset is not setable (or not implemented), return -EINVAL
+ */
+int rtc_set_offset(struct rtc_device *rtc, long offset)
+{
+	int ret;
+
+	if (!rtc->ops)
+		return -ENODEV;
+
+	if (!rtc->ops->set_offset)
+		return -EINVAL;
+
+	mutex_lock(&rtc->ops_lock);
+	ret = rtc->ops->set_offset(rtc->dev.parent, offset);
+	mutex_unlock(&rtc->ops_lock);
+	return ret;
+}

+ 1 - 1
drivers/rtc/rtc-as3722.c

@@ -210,7 +210,7 @@ static int as3722_rtc_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
 
 	ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL,
-			as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
+			as3722_alarm_irq, IRQF_ONESHOT,
 			"rtc-alarm", as3722_rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",

+ 355 - 0
drivers/rtc/rtc-asm9260.c

@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2016 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* Miscellaneous registers */
+/* Interrupt Location Register */
+#define HW_ILR			0x00
+#define BM_RTCALF		BIT(1)
+#define BM_RTCCIF		BIT(0)
+
+/* Clock Control Register */
+#define HW_CCR			0x08
+/* Calibration counter disable */
+#define BM_CCALOFF		BIT(4)
+/* Reset internal oscillator divider */
+#define BM_CTCRST		BIT(1)
+/* Clock Enable */
+#define BM_CLKEN		BIT(0)
+
+/* Counter Increment Interrupt Register */
+#define HW_CIIR			0x0C
+#define BM_CIIR_IMYEAR		BIT(7)
+#define BM_CIIR_IMMON		BIT(6)
+#define BM_CIIR_IMDOY		BIT(5)
+#define BM_CIIR_IMDOW		BIT(4)
+#define BM_CIIR_IMDOM		BIT(3)
+#define BM_CIIR_IMHOUR		BIT(2)
+#define BM_CIIR_IMMIN		BIT(1)
+#define BM_CIIR_IMSEC		BIT(0)
+
+/* Alarm Mask Register */
+#define HW_AMR			0x10
+#define BM_AMR_IMYEAR		BIT(7)
+#define BM_AMR_IMMON		BIT(6)
+#define BM_AMR_IMDOY		BIT(5)
+#define BM_AMR_IMDOW		BIT(4)
+#define BM_AMR_IMDOM		BIT(3)
+#define BM_AMR_IMHOUR		BIT(2)
+#define BM_AMR_IMMIN		BIT(1)
+#define BM_AMR_IMSEC		BIT(0)
+#define BM_AMR_OFF		0xff
+
+/* Consolidated time registers */
+#define HW_CTIME0		0x14
+#define BM_CTIME0_DOW_S		24
+#define BM_CTIME0_DOW_M		0x7
+#define BM_CTIME0_HOUR_S	16
+#define BM_CTIME0_HOUR_M	0x1f
+#define BM_CTIME0_MIN_S		8
+#define BM_CTIME0_MIN_M		0x3f
+#define BM_CTIME0_SEC_S		0
+#define BM_CTIME0_SEC_M		0x3f
+
+#define HW_CTIME1		0x18
+#define BM_CTIME1_YEAR_S	16
+#define BM_CTIME1_YEAR_M	0xfff
+#define BM_CTIME1_MON_S		8
+#define BM_CTIME1_MON_M		0xf
+#define BM_CTIME1_DOM_S		0
+#define BM_CTIME1_DOM_M		0x1f
+
+#define HW_CTIME2		0x1C
+#define BM_CTIME2_DOY_S		0
+#define BM_CTIME2_DOY_M		0xfff
+
+/* Time counter registers */
+#define HW_SEC			0x20
+#define HW_MIN			0x24
+#define HW_HOUR			0x28
+#define HW_DOM			0x2C
+#define HW_DOW			0x30
+#define HW_DOY			0x34
+#define HW_MONTH		0x38
+#define HW_YEAR			0x3C
+
+#define HW_CALIBRATION		0x40
+#define BM_CALDIR_BACK		BIT(17)
+#define BM_CALVAL_M		0x1ffff
+
+/* General purpose registers */
+#define HW_GPREG0		0x44
+#define HW_GPREG1		0x48
+#define HW_GPREG2		0x4C
+#define HW_GPREG3		0x50
+#define HW_GPREG4		0x54
+
+/* Alarm register group */
+#define HW_ALSEC		0x60
+#define HW_ALMIN		0x64
+#define HW_ALHOUR		0x68
+#define HW_ALDOM		0x6C
+#define HW_ALDOW		0x70
+#define HW_ALDOY		0x74
+#define HW_ALMON		0x78
+#define HW_ALYEAR		0x7C
+
+struct asm9260_rtc_priv {
+	struct device		*dev;
+	void __iomem		*iobase;
+	struct rtc_device	*rtc;
+	struct clk		*clk;
+	/* io lock */
+	spinlock_t		lock;
+};
+
+static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
+{
+	struct asm9260_rtc_priv *priv = dev_id;
+	u32 isr;
+	unsigned long events = 0;
+
+	isr = ioread32(priv->iobase + HW_CIIR);
+	if (!isr)
+		return IRQ_NONE;
+
+	iowrite32(0, priv->iobase + HW_CIIR);
+
+	events |= RTC_AF | RTC_IRQF;
+
+	rtc_update_irq(priv->rtc, 1, events);
+
+	return IRQ_HANDLED;
+}
+
+static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+	u32 ctime0, ctime1, ctime2;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&priv->lock, irq_flags);
+	ctime0 = ioread32(priv->iobase + HW_CTIME0);
+	ctime1 = ioread32(priv->iobase + HW_CTIME1);
+	ctime2 = ioread32(priv->iobase + HW_CTIME2);
+
+	if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
+		/*
+		 * woops, counter flipped right now. Now we are safe
+		 * to reread.
+		 */
+		ctime0 = ioread32(priv->iobase + HW_CTIME0);
+		ctime1 = ioread32(priv->iobase + HW_CTIME1);
+		ctime2 = ioread32(priv->iobase + HW_CTIME2);
+	}
+	spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+	tm->tm_sec  = (ctime0 >> BM_CTIME0_SEC_S)  & BM_CTIME0_SEC_M;
+	tm->tm_min  = (ctime0 >> BM_CTIME0_MIN_S)  & BM_CTIME0_MIN_M;
+	tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
+	tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S)  & BM_CTIME0_DOW_M;
+
+	tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S)  & BM_CTIME1_DOM_M;
+	tm->tm_mon  = (ctime1 >> BM_CTIME1_MON_S)  & BM_CTIME1_MON_M;
+	tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;
+
+	tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S)  & BM_CTIME2_DOY_M;
+
+	return 0;
+}
+
+static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&priv->lock, irq_flags);
+	/*
+	 * make sure SEC counter will not flip other counter on write time,
+	 * real value will be written at the enf of sequence.
+	 */
+	iowrite32(0, priv->iobase + HW_SEC);
+
+	iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
+	iowrite32(tm->tm_mon,  priv->iobase + HW_MONTH);
+	iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
+	iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
+	iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
+	iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
+	iowrite32(tm->tm_min,  priv->iobase + HW_MIN);
+	iowrite32(tm->tm_sec,  priv->iobase + HW_SEC);
+	spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+	return 0;
+}
+
+static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&priv->lock, irq_flags);
+	alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
+	alrm->time.tm_mon  = ioread32(priv->iobase + HW_ALMON);
+	alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
+	alrm->time.tm_wday = ioread32(priv->iobase + HW_ALDOW);
+	alrm->time.tm_yday = ioread32(priv->iobase + HW_ALDOY);
+	alrm->time.tm_hour = ioread32(priv->iobase + HW_ALHOUR);
+	alrm->time.tm_min  = ioread32(priv->iobase + HW_ALMIN);
+	alrm->time.tm_sec  = ioread32(priv->iobase + HW_ALSEC);
+
+	alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
+	alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
+	spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+	return rtc_valid_tm(&alrm->time);
+}
+
+static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&priv->lock, irq_flags);
+	iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
+	iowrite32(alrm->time.tm_mon,  priv->iobase + HW_ALMON);
+	iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
+	iowrite32(alrm->time.tm_wday, priv->iobase + HW_ALDOW);
+	iowrite32(alrm->time.tm_yday, priv->iobase + HW_ALDOY);
+	iowrite32(alrm->time.tm_hour, priv->iobase + HW_ALHOUR);
+	iowrite32(alrm->time.tm_min,  priv->iobase + HW_ALMIN);
+	iowrite32(alrm->time.tm_sec,  priv->iobase + HW_ALSEC);
+
+	iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
+	spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+	return 0;
+}
+
+static int asm9260_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+
+	iowrite32(enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
+	return 0;
+}
+
+static const struct rtc_class_ops asm9260_rtc_ops = {
+	.read_time		= asm9260_rtc_read_time,
+	.set_time		= asm9260_rtc_set_time,
+	.read_alarm		= asm9260_rtc_read_alarm,
+	.set_alarm		= asm9260_rtc_set_alarm,
+	.alarm_irq_enable	= asm9260_alarm_irq_enable,
+};
+
+static int __init asm9260_rtc_probe(struct platform_device *pdev)
+{
+	struct asm9260_rtc_priv *priv;
+	struct device *dev = &pdev->dev;
+	struct resource	*res;
+	int irq_alarm, ret;
+	u32 ccr;
+
+	priv = devm_kzalloc(dev, sizeof(struct asm9260_rtc_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = &pdev->dev;
+	platform_set_drvdata(pdev, priv);
+
+	irq_alarm = platform_get_irq(pdev, 0);
+	if (irq_alarm < 0) {
+		dev_err(dev, "No alarm IRQ resource defined\n");
+		return irq_alarm;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->iobase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->iobase))
+		return PTR_ERR(priv->iobase);
+
+	priv->clk = devm_clk_get(dev, "ahb");
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clk!\n");
+		return ret;
+	}
+
+	ccr = ioread32(priv->iobase + HW_CCR);
+	/* if dev is not enabled, reset it */
+	if ((ccr & (BM_CLKEN | BM_CTCRST)) != BM_CLKEN) {
+		iowrite32(BM_CTCRST, priv->iobase + HW_CCR);
+		ccr = 0;
+	}
+
+	iowrite32(BM_CLKEN | ccr, priv->iobase + HW_CCR);
+	iowrite32(0, priv->iobase + HW_CIIR);
+	iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
+
+	priv->rtc = devm_rtc_device_register(dev, dev_name(dev),
+					     &asm9260_rtc_ops, THIS_MODULE);
+	if (IS_ERR(priv->rtc)) {
+		ret = PTR_ERR(priv->rtc);
+		dev_err(dev, "Failed to register RTC device: %d\n", ret);
+		goto err_return;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq_alarm, NULL,
+					asm9260_rtc_irq, IRQF_ONESHOT,
+					dev_name(dev), priv);
+	if (ret < 0) {
+		dev_err(dev, "can't get irq %i, err %d\n",
+			irq_alarm, ret);
+		goto err_return;
+	}
+
+	return 0;
+
+err_return:
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int __exit asm9260_rtc_remove(struct platform_device *pdev)
+{
+	struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev);
+
+	/* Disable alarm matching */
+	iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
+	clk_disable_unprepare(priv->clk);
+	return 0;
+}
+
+static const struct of_device_id asm9260_dt_ids[] = {
+	{ .compatible = "alphascale,asm9260-rtc", },
+	{}
+};
+
+static struct platform_driver asm9260_rtc_driver = {
+	.probe		= asm9260_rtc_probe,
+	.remove		= asm9260_rtc_remove,
+	.driver		= {
+		.name	= "asm9260-rtc",
+		.owner	= THIS_MODULE,
+		.of_match_table = asm9260_dt_ids,
+	},
+};
+
+module_platform_driver(asm9260_rtc_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
+MODULE_DESCRIPTION("Alphascale asm9260 SoC Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");

+ 2 - 2
drivers/rtc/rtc-ds1305.c

@@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
 	struct spi_transfer	x[2];
 	int			status;
 
-	spi = container_of(kobj, struct spi_device, dev.kobj);
+	spi = to_spi_device(kobj_to_dev(kobj));
 
 	addr = DS1305_NVRAM + off;
 	msg_init(&m, x, &addr, count, NULL, buf);
@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
 	struct spi_transfer	x[2];
 	int			status;
 
-	spi = container_of(kobj, struct spi_device, dev.kobj);
+	spi = to_spi_device(kobj_to_dev(kobj));
 
 	addr = (DS1305_WRITE | DS1305_NVRAM) + off;
 	msg_init(&m, x, &addr, count, buf, NULL);

+ 409 - 2
drivers/rtc/rtc-ds1307.c

@@ -19,6 +19,9 @@
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/clk-provider.h>
 
 /*
  * We can't determine type by probing, but if we expect pre-Linux code
@@ -89,6 +92,7 @@ enum ds_type {
 #	define DS1340_BIT_OSF		0x80
 #define DS1337_REG_STATUS	0x0f
 #	define DS1337_BIT_OSF		0x80
+#	define DS3231_BIT_EN32KHZ	0x08
 #	define DS1337_BIT_A2I		0x02
 #	define DS1337_BIT_A1I		0x01
 #define DS1339_REG_ALARM1_SECS	0x07
@@ -118,6 +122,9 @@ struct ds1307 {
 			       u8 length, u8 *values);
 	s32 (*write_block_data)(const struct i2c_client *client, u8 command,
 				u8 length, const u8 *values);
+#ifdef CONFIG_COMMON_CLK
+	struct clk_hw		clks[2];
+#endif
 };
 
 struct chip_desc {
@@ -842,6 +849,378 @@ out:
 	return;
 }
 
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+
+/*
+ * Temperature sensor support for ds3231 devices.
+ */
+
+#define DS3231_REG_TEMPERATURE	0x11
+
+/*
+ * A user-initiated temperature conversion is not started by this function,
+ * so the temperature is updated once every 64 seconds.
+ */
+static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC)
+{
+	struct ds1307 *ds1307 = dev_get_drvdata(dev);
+	u8 temp_buf[2];
+	s16 temp;
+	int ret;
+
+	ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE,
+					sizeof(temp_buf), temp_buf);
+	if (ret < 0)
+		return ret;
+	if (ret != sizeof(temp_buf))
+		return -EIO;
+
+	/*
+	 * Temperature is represented as a 10-bit code with a resolution of
+	 * 0.25 degree celsius and encoded in two's complement format.
+	 */
+	temp = (temp_buf[0] << 8) | temp_buf[1];
+	temp >>= 6;
+	*mC = temp * 250;
+
+	return 0;
+}
+
+static ssize_t ds3231_hwmon_show_temp(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int ret;
+	s16 temp;
+
+	ret = ds3231_hwmon_read_temp(dev, &temp);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%d\n", temp);
+}
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp,
+			NULL, 0);
+
+static struct attribute *ds3231_hwmon_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ds3231_hwmon);
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+	struct device *dev;
+
+	if (ds1307->type != ds_3231)
+		return;
+
+	dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev,
+						ds1307->client->name,
+						ds1307, ds3231_hwmon_groups);
+	if (IS_ERR(dev)) {
+		dev_warn(&ds1307->client->dev,
+			"unable to register hwmon device %ld\n", PTR_ERR(dev));
+	}
+}
+
+#else
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+}
+
+#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Square-wave output support for DS3231
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
+ */
+#ifdef CONFIG_COMMON_CLK
+
+enum {
+	DS3231_CLK_SQW = 0,
+	DS3231_CLK_32KHZ,
+};
+
+#define clk_sqw_to_ds1307(clk)	\
+	container_of(clk, struct ds1307, clks[DS3231_CLK_SQW])
+#define clk_32khz_to_ds1307(clk)	\
+	container_of(clk, struct ds1307, clks[DS3231_CLK_32KHZ])
+
+static int ds3231_clk_sqw_rates[] = {
+	1,
+	1024,
+	4096,
+	8192,
+};
+
+static int ds1337_write_control(struct ds1307 *ds1307, u8 mask, u8 value)
+{
+	struct i2c_client *client = ds1307->client;
+	struct mutex *lock = &ds1307->rtc->ops_lock;
+	int control;
+	int ret;
+
+	mutex_lock(lock);
+
+	control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+	if (control < 0) {
+		ret = control;
+		goto out;
+	}
+
+	control &= ~mask;
+	control |= value;
+
+	ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+out:
+	mutex_unlock(lock);
+
+	return ret;
+}
+
+static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+	int control;
+	int rate_sel = 0;
+
+	control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
+	if (control < 0)
+		return control;
+	if (control & DS1337_BIT_RS1)
+		rate_sel += 1;
+	if (control & DS1337_BIT_RS2)
+		rate_sel += 2;
+
+	return ds3231_clk_sqw_rates[rate_sel];
+}
+
+static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) {
+		if (ds3231_clk_sqw_rates[i] <= rate)
+			return ds3231_clk_sqw_rates[i];
+	}
+
+	return 0;
+}
+
+static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+	int control = 0;
+	int rate_sel;
+
+	for (rate_sel = 0; rate_sel < ARRAY_SIZE(ds3231_clk_sqw_rates);
+			rate_sel++) {
+		if (ds3231_clk_sqw_rates[rate_sel] == rate)
+			break;
+	}
+
+	if (rate_sel == ARRAY_SIZE(ds3231_clk_sqw_rates))
+		return -EINVAL;
+
+	if (rate_sel & 1)
+		control |= DS1337_BIT_RS1;
+	if (rate_sel & 2)
+		control |= DS1337_BIT_RS2;
+
+	return ds1337_write_control(ds1307, DS1337_BIT_RS1 | DS1337_BIT_RS2,
+				control);
+}
+
+static int ds3231_clk_sqw_prepare(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+	return ds1337_write_control(ds1307, DS1337_BIT_INTCN, 0);
+}
+
+static void ds3231_clk_sqw_unprepare(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+	ds1337_write_control(ds1307, DS1337_BIT_INTCN, DS1337_BIT_INTCN);
+}
+
+static int ds3231_clk_sqw_is_prepared(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+	int control;
+
+	control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
+	if (control < 0)
+		return control;
+
+	return !(control & DS1337_BIT_INTCN);
+}
+
+static const struct clk_ops ds3231_clk_sqw_ops = {
+	.prepare = ds3231_clk_sqw_prepare,
+	.unprepare = ds3231_clk_sqw_unprepare,
+	.is_prepared = ds3231_clk_sqw_is_prepared,
+	.recalc_rate = ds3231_clk_sqw_recalc_rate,
+	.round_rate = ds3231_clk_sqw_round_rate,
+	.set_rate = ds3231_clk_sqw_set_rate,
+};
+
+static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	return 32768;
+}
+
+static int ds3231_clk_32khz_control(struct ds1307 *ds1307, bool enable)
+{
+	struct i2c_client *client = ds1307->client;
+	struct mutex *lock = &ds1307->rtc->ops_lock;
+	int status;
+	int ret;
+
+	mutex_lock(lock);
+
+	status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+	if (status < 0) {
+		ret = status;
+		goto out;
+	}
+
+	if (enable)
+		status |= DS3231_BIT_EN32KHZ;
+	else
+		status &= ~DS3231_BIT_EN32KHZ;
+
+	ret = i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, status);
+out:
+	mutex_unlock(lock);
+
+	return ret;
+}
+
+static int ds3231_clk_32khz_prepare(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+
+	return ds3231_clk_32khz_control(ds1307, true);
+}
+
+static void ds3231_clk_32khz_unprepare(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+
+	ds3231_clk_32khz_control(ds1307, false);
+}
+
+static int ds3231_clk_32khz_is_prepared(struct clk_hw *hw)
+{
+	struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+	int status;
+
+	status = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_STATUS);
+	if (status < 0)
+		return status;
+
+	return !!(status & DS3231_BIT_EN32KHZ);
+}
+
+static const struct clk_ops ds3231_clk_32khz_ops = {
+	.prepare = ds3231_clk_32khz_prepare,
+	.unprepare = ds3231_clk_32khz_unprepare,
+	.is_prepared = ds3231_clk_32khz_is_prepared,
+	.recalc_rate = ds3231_clk_32khz_recalc_rate,
+};
+
+static struct clk_init_data ds3231_clks_init[] = {
+	[DS3231_CLK_SQW] = {
+		.name = "ds3231_clk_sqw",
+		.ops = &ds3231_clk_sqw_ops,
+		.flags = CLK_IS_ROOT,
+	},
+	[DS3231_CLK_32KHZ] = {
+		.name = "ds3231_clk_32khz",
+		.ops = &ds3231_clk_32khz_ops,
+		.flags = CLK_IS_ROOT,
+	},
+};
+
+static int ds3231_clks_register(struct ds1307 *ds1307)
+{
+	struct i2c_client *client = ds1307->client;
+	struct device_node *node = client->dev.of_node;
+	struct clk_onecell_data	*onecell;
+	int i;
+
+	onecell = devm_kzalloc(&client->dev, sizeof(*onecell), GFP_KERNEL);
+	if (!onecell)
+		return -ENOMEM;
+
+	onecell->clk_num = ARRAY_SIZE(ds3231_clks_init);
+	onecell->clks = devm_kcalloc(&client->dev, onecell->clk_num,
+					sizeof(onecell->clks[0]), GFP_KERNEL);
+	if (!onecell->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(ds3231_clks_init); i++) {
+		struct clk_init_data init = ds3231_clks_init[i];
+
+		/*
+		 * Interrupt signal due to alarm conditions and square-wave
+		 * output share same pin, so don't initialize both.
+		 */
+		if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags))
+			continue;
+
+		/* optional override of the clockname */
+		of_property_read_string_index(node, "clock-output-names", i,
+						&init.name);
+		ds1307->clks[i].init = &init;
+
+		onecell->clks[i] = devm_clk_register(&client->dev,
+							&ds1307->clks[i]);
+		if (IS_ERR(onecell->clks[i]))
+			return PTR_ERR(onecell->clks[i]);
+	}
+
+	if (!node)
+		return 0;
+
+	of_clk_add_provider(node, of_clk_src_onecell_get, onecell);
+
+	return 0;
+}
+
+static void ds1307_clks_register(struct ds1307 *ds1307)
+{
+	int ret;
+
+	if (ds1307->type != ds_3231)
+		return;
+
+	ret = ds3231_clks_register(ds1307);
+	if (ret) {
+		dev_warn(&ds1307->client->dev,
+			"unable to register clock device %d\n", ret);
+	}
+}
+
+#else
+
+static void ds1307_clks_register(struct ds1307 *ds1307)
+{
+}
+
+#endif /* CONFIG_COMMON_CLK */
+
 static int ds1307_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -851,6 +1230,7 @@ static int ds1307_probe(struct i2c_client *client,
 	struct chip_desc	*chip = &chips[id->driver_data];
 	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 	bool			want_irq = false;
+	bool			ds1307_can_wakeup_device = false;
 	unsigned char		*buf;
 	struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
 	irq_handler_t	irq_handler = ds1307_irq;
@@ -898,6 +1278,20 @@ static int ds1307_probe(struct i2c_client *client,
 		ds1307->write_block_data = ds1307_write_block_data;
 	}
 
+#ifdef CONFIG_OF
+/*
+ * For devices with no IRQ directly connected to the SoC, the RTC chip
+ * can be forced as a wakeup source by stating that explicitly in
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * If the "wakeup-source" property is set, don't request an IRQ.
+ * This will guarantee the 'wakealarm' sysfs entry is available on the device,
+ * if supported by the RTC.
+ */
+	if (of_property_read_bool(client->dev.of_node, "wakeup-source")) {
+		ds1307_can_wakeup_device = true;
+	}
+#endif
+
 	switch (ds1307->type) {
 	case ds_1337:
 	case ds_1339:
@@ -916,11 +1310,13 @@ static int ds1307_probe(struct i2c_client *client,
 			ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
 
 		/*
-		 * Using IRQ?  Disable the square wave and both alarms.
+		 * Using IRQ or defined as wakeup-source?
+		 * Disable the square wave and both alarms.
 		 * For some variants, be sure alarms can trigger when we're
 		 * running on Vbackup (BBSQI/BBSQW)
 		 */
-		if (ds1307->client->irq > 0 && chip->alarm) {
+		if (chip->alarm && (ds1307->client->irq > 0 ||
+						ds1307_can_wakeup_device)) {
 			ds1307->regs[0] |= DS1337_BIT_INTCN
 					| bbsqi_bitpos[ds1307->type];
 			ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
@@ -1135,6 +1531,14 @@ read_rtc:
 		return PTR_ERR(ds1307->rtc);
 	}
 
+	if (ds1307_can_wakeup_device) {
+		/* Disable request for an IRQ */
+		want_irq = false;
+		dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n");
+		/* We cannot support UIE mode if we do not have an IRQ line */
+		ds1307->rtc->uie_unsupported = 1;
+	}
+
 	if (want_irq) {
 		err = devm_request_threaded_irq(&client->dev,
 						client->irq, NULL, irq_handler,
@@ -1182,6 +1586,9 @@ read_rtc:
 		}
 	}
 
+	ds1307_hwmon_register(ds1307);
+	ds1307_clks_register(ds1307);
+
 	return 0;
 
 exit:

+ 5 - 4
drivers/rtc/rtc-ds1685.c

@@ -187,9 +187,9 @@ ds1685_rtc_end_data_access(struct ds1685_priv *rtc)
  * Only use this where you are certain another lock will not be held.
  */
 static inline void
-ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long flags)
+ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long *flags)
 {
-	spin_lock_irqsave(&rtc->lock, flags);
+	spin_lock_irqsave(&rtc->lock, *flags);
 	ds1685_rtc_switch_to_bank1(rtc);
 }
 
@@ -1300,7 +1300,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
 {
 	struct ds1685_priv *rtc = dev_get_drvdata(dev);
 	u8 reg = 0, bit = 0, tmp;
-	unsigned long flags = 0;
+	unsigned long flags;
 	long int val = 0;
 	const struct ds1685_rtc_ctrl_regs *reg_info =
 		ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
@@ -1321,7 +1321,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
 	bit = reg_info->bit;
 
 	/* Safe to spinlock during a write. */
-	ds1685_rtc_begin_ctrl_access(rtc, flags);
+	ds1685_rtc_begin_ctrl_access(rtc, &flags);
 	tmp = rtc->read(rtc, reg);
 	rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
 	ds1685_rtc_end_ctrl_access(rtc, flags);
@@ -2161,6 +2161,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
 	/* Check for valid RTC data, else, spin forever. */
 	if (unlikely(!pdev)) {
 		pr_emerg("platform device data not available, spinning forever ...\n");
+		while(1);
 		unreachable();
 	} else {
 		/* Get the rtc data. */

+ 283 - 193
drivers/rtc/rtc-ds3232.c

@@ -1,19 +1,15 @@
 /*
- * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
+ * RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
  *
  * Copyright (C) 2009-2011 Freescale Semiconductor.
  * Author: Jack Lan <jack.lan@freescale.com>
+ * Copyright (C) 2008 MIMOMax Wireless Ltd.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-/*
- * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
- * recommened in .../Documentation/i2c/writing-clients section
- * "Sending and receiving", using SMBus level communication is preferred.
- */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
@@ -21,10 +17,11 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
-#include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 
 #define DS3232_REG_SECONDS	0x00
 #define DS3232_REG_MINUTES	0x01
@@ -50,39 +47,33 @@
 #       define DS3232_REG_SR_A1F   0x01
 
 struct ds3232 {
-	struct i2c_client *client;
+	struct device *dev;
+	struct regmap *regmap;
+	int irq;
 	struct rtc_device *rtc;
-	struct work_struct work;
 
-	/* The mutex protects alarm operations, and prevents a race
-	 * between the enable_irq() in the workqueue and the free_irq()
-	 * in the remove function.
-	 */
-	struct mutex mutex;
 	bool suspended;
-	int exiting;
 };
 
-static struct i2c_driver ds3232_driver;
-
-static int ds3232_check_rtc_status(struct i2c_client *client)
+static int ds3232_check_rtc_status(struct device *dev)
 {
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	int ret = 0;
 	int control, stat;
 
-	stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-	if (stat < 0)
-		return stat;
+	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+	if (ret)
+		return ret;
 
 	if (stat & DS3232_REG_SR_OSF)
-		dev_warn(&client->dev,
+		dev_warn(dev,
 				"oscillator discontinuity flagged, "
 				"time unreliable\n");
 
 	stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
 
-	ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
-	if (ret < 0)
+	ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+	if (ret)
 		return ret;
 
 	/* If the alarm is pending, clear it before requesting
@@ -90,31 +81,28 @@ static int ds3232_check_rtc_status(struct i2c_client *client)
 	 * before everything is initialized.
 	 */
 
-	control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-	if (control < 0)
-		return control;
+	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+	if (ret)
+		return ret;
 
 	control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
 	control |= DS3232_REG_CR_INTCN;
 
-	return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+	return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
 }
 
 static int ds3232_read_time(struct device *dev, struct rtc_time *time)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	int ret;
 	u8 buf[7];
 	unsigned int year, month, day, hour, minute, second;
 	unsigned int week, twelve_hr, am_pm;
 	unsigned int century, add_century = 0;
 
-	ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf);
-
-	if (ret < 0)
+	ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
+	if (ret)
 		return ret;
-	if (ret < 7)
-		return -EIO;
 
 	second = buf[0];
 	minute = buf[1];
@@ -159,7 +147,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
 
 static int ds3232_set_time(struct device *dev, struct rtc_time *time)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	u8 buf[7];
 
 	/* Extract time from rtc_time and load into ds3232*/
@@ -179,8 +167,7 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
 		buf[6] = bin2bcd(time->tm_year);
 	}
 
-	return i2c_smbus_write_i2c_block_data(client,
-					      DS3232_REG_SECONDS, 7, buf);
+	return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
 }
 
 /*
@@ -190,24 +177,19 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
  */
 static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	int control, stat;
 	int ret;
 	u8 buf[4];
 
-	mutex_lock(&ds3232->mutex);
-
-	ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-	if (ret < 0)
+	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+	if (ret)
 		goto out;
-	stat = ret;
-	ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-	if (ret < 0)
+	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+	if (ret)
 		goto out;
-	control = ret;
-	ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-	if (ret < 0)
+	ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
+	if (ret)
 		goto out;
 
 	alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
@@ -226,7 +208,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
 	ret = 0;
 out:
-	mutex_unlock(&ds3232->mutex);
 	return ret;
 }
 
@@ -236,166 +217,129 @@ out:
  */
 static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	int control, stat;
 	int ret;
 	u8 buf[4];
 
-	if (client->irq <= 0)
+	if (ds3232->irq <= 0)
 		return -EINVAL;
 
-	mutex_lock(&ds3232->mutex);
-
 	buf[0] = bin2bcd(alarm->time.tm_sec);
 	buf[1] = bin2bcd(alarm->time.tm_min);
 	buf[2] = bin2bcd(alarm->time.tm_hour);
 	buf[3] = bin2bcd(alarm->time.tm_mday);
 
 	/* clear alarm interrupt enable bit */
-	ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-	if (ret < 0)
+	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+	if (ret)
 		goto out;
-	control = ret;
 	control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
-	ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
-	if (ret < 0)
+	ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
+	if (ret)
 		goto out;
 
 	/* clear any pending alarm flag */
-	ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-	if (ret < 0)
+	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+	if (ret)
 		goto out;
-	stat = ret;
 	stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
-	ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
-	if (ret < 0)
+	ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+	if (ret)
 		goto out;
 
-	ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
+	ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
+	if (ret)
+		goto out;
 
 	if (alarm->enabled) {
 		control |= DS3232_REG_CR_A1IE;
-		ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+		ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
 	}
 out:
-	mutex_unlock(&ds3232->mutex);
 	return ret;
 }
 
-static void ds3232_update_alarm(struct i2c_client *client)
+static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
 {
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 	int control;
 	int ret;
-	u8 buf[4];
-
-	mutex_lock(&ds3232->mutex);
-
-	ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-	if (ret < 0)
-		goto unlock;
-
-	buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-								0x80 : buf[0];
-	buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-								0x80 : buf[1];
-	buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-								0x80 : buf[2];
-	buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-								0x80 : buf[3];
-
-	ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-	if (ret < 0)
-		goto unlock;
 
-	control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-	if (control < 0)
-		goto unlock;
+	ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+	if (ret)
+		return ret;
 
-	if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF))
+	if (enabled)
 		/* enable alarm1 interrupt */
 		control |= DS3232_REG_CR_A1IE;
 	else
 		/* disable alarm1 interrupt */
 		control &= ~(DS3232_REG_CR_A1IE);
-	i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+	ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
 
-unlock:
-	mutex_unlock(&ds3232->mutex);
+	return ret;
 }
 
 static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
 
-	if (client->irq <= 0)
+	if (ds3232->irq <= 0)
 		return -EINVAL;
 
-	if (enabled)
-		ds3232->rtc->irq_data |= RTC_AF;
-	else
-		ds3232->rtc->irq_data &= ~RTC_AF;
-
-	ds3232_update_alarm(client);
-	return 0;
+	return ds3232_update_alarm(dev, enabled);
 }
 
 static irqreturn_t ds3232_irq(int irq, void *dev_id)
 {
-	struct i2c_client *client = dev_id;
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-	disable_irq_nosync(irq);
-
-	/*
-	 * If rtc as a wakeup source, can't schedule the work
-	 * at system resume flow, because at this time the i2c bus
-	 * has not been resumed.
-	 */
-	if (!ds3232->suspended)
-		schedule_work(&ds3232->work);
-
-	return IRQ_HANDLED;
-}
-
-static void ds3232_work(struct work_struct *work)
-{
-	struct ds3232 *ds3232 = container_of(work, struct ds3232, work);
-	struct i2c_client *client = ds3232->client;
+	struct device *dev = dev_id;
+	struct ds3232 *ds3232 = dev_get_drvdata(dev);
+	struct mutex *lock = &ds3232->rtc->ops_lock;
+	int ret;
 	int stat, control;
 
-	mutex_lock(&ds3232->mutex);
+	mutex_lock(lock);
 
-	stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-	if (stat < 0)
+	ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+	if (ret)
 		goto unlock;
 
 	if (stat & DS3232_REG_SR_A1F) {
-		control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-		if (control < 0) {
-			pr_warn("Read Control Register error - Disable IRQ%d\n",
-				client->irq);
+		ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+		if (ret) {
+			dev_warn(ds3232->dev,
+				 "Read Control Register error %d\n", ret);
 		} else {
 			/* disable alarm1 interrupt */
 			control &= ~(DS3232_REG_CR_A1IE);
-			i2c_smbus_write_byte_data(client, DS3232_REG_CR,
-						control);
+			ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
+					   control);
+			if (ret) {
+				dev_warn(ds3232->dev,
+					 "Write Control Register error %d\n",
+					 ret);
+				goto unlock;
+			}
 
 			/* clear the alarm pend flag */
 			stat &= ~DS3232_REG_SR_A1F;
-			i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
+			ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+			if (ret) {
+				dev_warn(ds3232->dev,
+					 "Write Status Register error %d\n",
+					 ret);
+				goto unlock;
+			}
 
 			rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
-
-			if (!ds3232->exiting)
-				enable_irq(client->irq);
 		}
 	}
 
 unlock:
-	mutex_unlock(&ds3232->mutex);
+	mutex_unlock(lock);
+
+	return IRQ_HANDLED;
 }
 
 static const struct rtc_class_ops ds3232_rtc_ops = {
@@ -406,67 +350,50 @@ static const struct rtc_class_ops ds3232_rtc_ops = {
 	.alarm_irq_enable = ds3232_alarm_irq_enable,
 };
 
-static int ds3232_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
+			const char *name)
 {
 	struct ds3232 *ds3232;
 	int ret;
 
-	ds3232 = devm_kzalloc(&client->dev, sizeof(struct ds3232), GFP_KERNEL);
+	ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
 	if (!ds3232)
 		return -ENOMEM;
 
-	ds3232->client = client;
-	i2c_set_clientdata(client, ds3232);
-
-	INIT_WORK(&ds3232->work, ds3232_work);
-	mutex_init(&ds3232->mutex);
+	ds3232->regmap = regmap;
+	ds3232->irq = irq;
+	ds3232->dev = dev;
+	dev_set_drvdata(dev, ds3232);
 
-	ret = ds3232_check_rtc_status(client);
+	ret = ds3232_check_rtc_status(dev);
 	if (ret)
 		return ret;
 
-	if (client->irq > 0) {
-		ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
-				       IRQF_SHARED, "ds3232", client);
+	if (ds3232->irq > 0) {
+		ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
+						ds3232_irq,
+						IRQF_SHARED | IRQF_ONESHOT,
+						name, dev);
 		if (ret) {
-			dev_err(&client->dev, "unable to request IRQ\n");
-		}
-		device_init_wakeup(&client->dev, 1);
-	}
-	ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
-					  &ds3232_rtc_ops, THIS_MODULE);
-	return PTR_ERR_OR_ZERO(ds3232->rtc);
-}
-
-static int ds3232_remove(struct i2c_client *client)
-{
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-	if (client->irq > 0) {
-		mutex_lock(&ds3232->mutex);
-		ds3232->exiting = 1;
-		mutex_unlock(&ds3232->mutex);
-
-		devm_free_irq(&client->dev, client->irq, client);
-		cancel_work_sync(&ds3232->work);
+			ds3232->irq = 0;
+			dev_err(dev, "unable to request IRQ\n");
+		} else
+			device_init_wakeup(dev, 1);
 	}
+	ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
+						THIS_MODULE);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(ds3232->rtc);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int ds3232_suspend(struct device *dev)
 {
 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
-	struct i2c_client *client = to_i2c_client(dev);
 
-	if (device_can_wakeup(dev)) {
-		ds3232->suspended = true;
-		if (irq_set_irq_wake(client->irq, 1)) {
+	if (device_may_wakeup(dev)) {
+		if (enable_irq_wake(ds3232->irq))
 			dev_warn_once(dev, "Cannot set wakeup source\n");
-			ds3232->suspended = false;
-		}
 	}
 
 	return 0;
@@ -475,16 +402,9 @@ static int ds3232_suspend(struct device *dev)
 static int ds3232_resume(struct device *dev)
 {
 	struct ds3232 *ds3232 = dev_get_drvdata(dev);
-	struct i2c_client *client = to_i2c_client(dev);
 
-	if (ds3232->suspended) {
-		ds3232->suspended = false;
-
-		/* Clear the hardware alarm pend flag */
-		schedule_work(&ds3232->work);
-
-		irq_set_irq_wake(client->irq, 0);
-	}
+	if (device_may_wakeup(dev))
+		disable_irq_wake(ds3232->irq);
 
 	return 0;
 }
@@ -494,6 +414,27 @@ static const struct dev_pm_ops ds3232_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
 };
 
+#if IS_ENABLED(CONFIG_I2C)
+
+static int ds3232_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	static const struct regmap_config config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+	};
+
+	regmap = devm_regmap_init_i2c(client, &config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+			__func__, PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	return ds3232_probe(&client->dev, regmap, client->irq, client->name);
+}
+
 static const struct i2c_device_id ds3232_id[] = {
 	{ "ds3232", 0 },
 	{ }
@@ -505,13 +446,162 @@ static struct i2c_driver ds3232_driver = {
 		.name = "rtc-ds3232",
 		.pm	= &ds3232_pm_ops,
 	},
-	.probe = ds3232_probe,
-	.remove = ds3232_remove,
+	.probe = ds3232_i2c_probe,
 	.id_table = ds3232_id,
 };
 
-module_i2c_driver(ds3232_driver);
+static int ds3232_register_driver(void)
+{
+	return i2c_add_driver(&ds3232_driver);
+}
+
+static void ds3232_unregister_driver(void)
+{
+	i2c_del_driver(&ds3232_driver);
+}
+
+#else
+
+static int ds3232_register_driver(void)
+{
+	return 0;
+}
+
+static void ds3232_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int ds3234_probe(struct spi_device *spi)
+{
+	int res;
+	unsigned int tmp;
+	static const struct regmap_config config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.write_flag_mask = 0x80,
+	};
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spi(spi, &config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+			__func__, PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	spi->mode = SPI_MODE_3;
+	spi->bits_per_word = 8;
+	spi_setup(spi);
+
+	res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
+	if (res)
+		return res;
+
+	/* Control settings
+	 *
+	 * CONTROL_REG
+	 * BIT 7	6	5	4	3	2	1	0
+	 *     EOSC	BBSQW	CONV	RS2	RS1	INTCN	A2IE	A1IE
+	 *
+	 *     0	0	0	1	1	1	0	0
+	 *
+	 * CONTROL_STAT_REG
+	 * BIT 7	6	5	4	3	2	1	0
+	 *     OSF	BB32kHz	CRATE1	CRATE0	EN32kHz	BSY	A2F	A1F
+	 *
+	 *     1	0	0	0	1	0	0	0
+	 */
+	res = regmap_read(regmap, DS3232_REG_CR, &tmp);
+	if (res)
+		return res;
+	res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
+	if (res)
+		return res;
+
+	res = regmap_read(regmap, DS3232_REG_SR, &tmp);
+	if (res)
+		return res;
+	res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
+	if (res)
+		return res;
+
+	/* Print our settings */
+	res = regmap_read(regmap, DS3232_REG_CR, &tmp);
+	if (res)
+		return res;
+	dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
+
+	res = regmap_read(regmap, DS3232_REG_SR, &tmp);
+	if (res)
+		return res;
+	dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
+
+	return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
+}
+
+static struct spi_driver ds3234_driver = {
+	.driver = {
+		.name	 = "ds3234",
+	},
+	.probe	 = ds3234_probe,
+};
+
+static int ds3234_register_driver(void)
+{
+	return spi_register_driver(&ds3234_driver);
+}
+
+static void ds3234_unregister_driver(void)
+{
+	spi_unregister_driver(&ds3234_driver);
+}
+
+#else
+
+static int ds3234_register_driver(void)
+{
+	return 0;
+}
+
+static void ds3234_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init ds323x_init(void)
+{
+	int ret;
+
+	ret = ds3232_register_driver();
+	if (ret) {
+		pr_err("Failed to register ds3232 driver: %d\n", ret);
+		return ret;
+	}
+
+	ret = ds3234_register_driver();
+	if (ret) {
+		pr_err("Failed to register ds3234 driver: %d\n", ret);
+		ds3232_unregister_driver();
+	}
+
+	return ret;
+}
+module_init(ds323x_init)
+
+static void __exit ds323x_exit(void)
+{
+	ds3234_unregister_driver();
+	ds3232_unregister_driver();
+}
+module_exit(ds323x_exit)
 
 MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
-MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver");
+MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:ds3234");

+ 0 - 171
drivers/rtc/rtc-ds3234.c

@@ -1,171 +0,0 @@
-/* rtc-ds3234.c
- *
- * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
- * and SRAM.
- *
- * Copyright (C) 2008 MIMOMax Wireless Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/rtc.h>
-#include <linux/spi/spi.h>
-#include <linux/bcd.h>
-
-#define DS3234_REG_SECONDS	0x00
-#define DS3234_REG_MINUTES	0x01
-#define DS3234_REG_HOURS	0x02
-#define DS3234_REG_DAY		0x03
-#define DS3234_REG_DATE		0x04
-#define DS3234_REG_MONTH	0x05
-#define DS3234_REG_YEAR		0x06
-#define DS3234_REG_CENTURY	(1 << 7) /* Bit 7 of the Month register */
-
-#define DS3234_REG_CONTROL	0x0E
-#define DS3234_REG_CONT_STAT	0x0F
-
-static int ds3234_set_reg(struct device *dev, unsigned char address,
-				unsigned char data)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	unsigned char buf[2];
-
-	/* MSB must be '1' to indicate write */
-	buf[0] = address | 0x80;
-	buf[1] = data;
-
-	return spi_write_then_read(spi, buf, 2, NULL, 0);
-}
-
-static int ds3234_get_reg(struct device *dev, unsigned char address,
-				unsigned char *data)
-{
-	struct spi_device *spi = to_spi_device(dev);
-
-	*data = address & 0x7f;
-
-	return spi_write_then_read(spi, data, 1, data, 1);
-}
-
-static int ds3234_read_time(struct device *dev, struct rtc_time *dt)
-{
-	int err;
-	unsigned char buf[8];
-	struct spi_device *spi = to_spi_device(dev);
-
-	buf[0] = 0x00; /* Start address */
-
-	err = spi_write_then_read(spi, buf, 1, buf, 8);
-	if (err != 0)
-		return err;
-
-	/* Seconds, Minutes, Hours, Day, Date, Month, Year */
-	dt->tm_sec	= bcd2bin(buf[0]);
-	dt->tm_min	= bcd2bin(buf[1]);
-	dt->tm_hour	= bcd2bin(buf[2] & 0x3f);
-	dt->tm_wday	= bcd2bin(buf[3]) - 1; /* 0 = Sun */
-	dt->tm_mday	= bcd2bin(buf[4]);
-	dt->tm_mon	= bcd2bin(buf[5] & 0x1f) - 1; /* 0 = Jan */
-	dt->tm_year	= bcd2bin(buf[6] & 0xff) + 100; /* Assume 20YY */
-
-	return rtc_valid_tm(dt);
-}
-
-static int ds3234_set_time(struct device *dev, struct rtc_time *dt)
-{
-	ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
-	ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
-	ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
-
-	/* 0 = Sun */
-	ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1));
-	ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday));
-
-	/* 0 = Jan */
-	ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1));
-
-	/* Assume 20YY although we just want to make sure not to go negative. */
-	if (dt->tm_year > 100)
-		dt->tm_year -= 100;
-
-	ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year));
-
-	return 0;
-}
-
-static const struct rtc_class_ops ds3234_rtc_ops = {
-	.read_time	= ds3234_read_time,
-	.set_time	= ds3234_set_time,
-};
-
-static int ds3234_probe(struct spi_device *spi)
-{
-	struct rtc_device *rtc;
-	unsigned char tmp;
-	int res;
-
-	spi->mode = SPI_MODE_3;
-	spi->bits_per_word = 8;
-	spi_setup(spi);
-
-	res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
-	if (res != 0)
-		return res;
-
-	/* Control settings
-	 *
-	 * CONTROL_REG
-	 * BIT 7	6	5	4	3	2	1	0
-	 *     EOSC	BBSQW	CONV	RS2	RS1	INTCN	A2IE	A1IE
-	 *
-	 *     0	0	0	1	1	1	0	0
-	 *
-	 * CONTROL_STAT_REG
-	 * BIT 7	6	5	4	3	2	1	0
-	 *     OSF	BB32kHz	CRATE1	CRATE0	EN32kHz	BSY	A2F	A1F
-	 *
-	 *     1	0	0	0	1	0	0	0
-	 */
-	ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
-	ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c);
-
-	ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
-	ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88);
-
-	/* Print our settings */
-	ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
-	dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
-
-	ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
-	dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
-
-	rtc = devm_rtc_device_register(&spi->dev, "ds3234",
-				&ds3234_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
-
-	spi_set_drvdata(spi, rtc);
-
-	return 0;
-}
-
-static struct spi_driver ds3234_driver = {
-	.driver = {
-		.name	 = "ds3234",
-	},
-	.probe	 = ds3234_probe,
-};
-
-module_spi_driver(ds3234_driver);
-
-MODULE_DESCRIPTION("DS3234 SPI RTC driver");
-MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:ds3234");

+ 11 - 1
drivers/rtc/rtc-generic.c

@@ -9,6 +9,8 @@
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 
+#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
+    defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
 #include <asm/rtc.h>
 
 static int generic_get_time(struct device *dev, struct rtc_time *tm)
@@ -33,13 +35,21 @@ static const struct rtc_class_ops generic_rtc_ops = {
 	.read_time = generic_get_time,
 	.set_time = generic_set_time,
 };
+#else
+#define generic_rtc_ops *(struct rtc_class_ops*)NULL
+#endif
 
 static int __init generic_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
+	const struct rtc_class_ops *ops;
+
+	ops = dev_get_platdata(&dev->dev);
+	if (!ops)
+		ops = &generic_rtc_ops;
 
 	rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
-					&generic_rtc_ops, THIS_MODULE);
+					ops, THIS_MODULE);
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
 

+ 1 - 1
drivers/rtc/rtc-hym8563.c

@@ -144,7 +144,7 @@ static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	 * it does not seem to carry it over a subsequent write/read.
 	 * So we'll limit ourself to 100 years, starting at 2000 for now.
 	 */
-	buf[6] = tm->tm_year - 100;
+	buf[6] = bin2bcd(tm->tm_year - 100);
 
 	/*
 	 * CTL1 only contains TEST-mode bits apart from stop,

+ 450 - 115
drivers/rtc/rtc-max77686.c

@@ -1,5 +1,5 @@
 /*
- * RTC driver for Maxim MAX77686
+ * RTC driver for Maxim MAX77686 and MAX77802
  *
  * Copyright (C) 2012 Samsung Electronics Co.Ltd
  *
@@ -12,8 +12,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
+#include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/rtc.h>
 #include <linux/delay.h>
@@ -24,24 +23,38 @@
 #include <linux/irqdomain.h>
 #include <linux/regmap.h>
 
+#define MAX77686_I2C_ADDR_RTC		(0x0C >> 1)
+#define MAX77620_I2C_ADDR_RTC		0x68
+#define MAX77686_INVALID_I2C_ADDR	(-1)
+
+/* Define non existing register */
+#define MAX77686_INVALID_REG		(-1)
+
 /* RTC Control Register */
 #define BCD_EN_SHIFT			0
-#define BCD_EN_MASK			(1 << BCD_EN_SHIFT)
+#define BCD_EN_MASK			BIT(BCD_EN_SHIFT)
 #define MODEL24_SHIFT			1
-#define MODEL24_MASK			(1 << MODEL24_SHIFT)
+#define MODEL24_MASK			BIT(MODEL24_SHIFT)
 /* RTC Update Register1 */
 #define RTC_UDR_SHIFT			0
-#define RTC_UDR_MASK			(1 << RTC_UDR_SHIFT)
+#define RTC_UDR_MASK			BIT(RTC_UDR_SHIFT)
 #define RTC_RBUDR_SHIFT			4
-#define RTC_RBUDR_MASK			(1 << RTC_RBUDR_SHIFT)
+#define RTC_RBUDR_MASK			BIT(RTC_RBUDR_SHIFT)
 /* RTC Hour register */
 #define HOUR_PM_SHIFT			6
-#define HOUR_PM_MASK			(1 << HOUR_PM_SHIFT)
+#define HOUR_PM_MASK			BIT(HOUR_PM_SHIFT)
 /* RTC Alarm Enable */
 #define ALARM_ENABLE_SHIFT		7
-#define ALARM_ENABLE_MASK		(1 << ALARM_ENABLE_SHIFT)
+#define ALARM_ENABLE_MASK		BIT(ALARM_ENABLE_SHIFT)
 
-#define MAX77686_RTC_UPDATE_DELAY	16
+#define REG_RTC_NONE			0xdeadbeef
+
+/*
+ * MAX77802 has separate register (RTCAE1) for alarm enable instead
+ * using 1 bit from registers RTC{SEC,MIN,HOUR,DAY,MONTH,YEAR,DATE}
+ * as in done in MAX77686.
+ */
+#define MAX77802_ALARM_ENABLE_VALUE	0x77
 
 enum {
 	RTC_SEC = 0,
@@ -54,15 +67,38 @@ enum {
 	RTC_NR_TIME
 };
 
+struct max77686_rtc_driver_data {
+	/* Minimum usecs needed for a RTC update */
+	unsigned long		delay;
+	/* Mask used to read RTC registers value */
+	u8			mask;
+	/* Registers offset to I2C addresses map */
+	const unsigned int	*map;
+	/* Has a separate alarm enable register? */
+	bool			alarm_enable_reg;
+	/* I2C address for RTC block */
+	int			rtc_i2c_addr;
+	/* RTC interrupt via platform resource */
+	bool			rtc_irq_from_platform;
+	/* Pending alarm status register */
+	int			alarm_pending_status_reg;
+	/* RTC IRQ CHIP for regmap */
+	const struct regmap_irq_chip *rtc_irq_chip;
+};
+
 struct max77686_rtc_info {
 	struct device		*dev;
-	struct max77686_dev	*max77686;
 	struct i2c_client	*rtc;
 	struct rtc_device	*rtc_dev;
 	struct mutex		lock;
 
 	struct regmap		*regmap;
+	struct regmap		*rtc_regmap;
+
+	const struct max77686_rtc_driver_data *drv_data;
+	struct regmap_irq_chip_data *rtc_irq_data;
 
+	int rtc_irq;
 	int virq;
 	int rtc_24hr_mode;
 };
@@ -72,29 +108,190 @@ enum MAX77686_RTC_OP {
 	MAX77686_RTC_READ,
 };
 
+/* These are not registers but just offsets that are mapped to addresses */
+enum max77686_rtc_reg_offset {
+	REG_RTC_CONTROLM = 0,
+	REG_RTC_CONTROL,
+	REG_RTC_UPDATE0,
+	REG_WTSR_SMPL_CNTL,
+	REG_RTC_SEC,
+	REG_RTC_MIN,
+	REG_RTC_HOUR,
+	REG_RTC_WEEKDAY,
+	REG_RTC_MONTH,
+	REG_RTC_YEAR,
+	REG_RTC_DATE,
+	REG_ALARM1_SEC,
+	REG_ALARM1_MIN,
+	REG_ALARM1_HOUR,
+	REG_ALARM1_WEEKDAY,
+	REG_ALARM1_MONTH,
+	REG_ALARM1_YEAR,
+	REG_ALARM1_DATE,
+	REG_ALARM2_SEC,
+	REG_ALARM2_MIN,
+	REG_ALARM2_HOUR,
+	REG_ALARM2_WEEKDAY,
+	REG_ALARM2_MONTH,
+	REG_ALARM2_YEAR,
+	REG_ALARM2_DATE,
+	REG_RTC_AE1,
+	REG_RTC_END,
+};
+
+/* Maps RTC registers offset to the MAX77686 register addresses */
+static const unsigned int max77686_map[REG_RTC_END] = {
+	[REG_RTC_CONTROLM]   = MAX77686_RTC_CONTROLM,
+	[REG_RTC_CONTROL]    = MAX77686_RTC_CONTROL,
+	[REG_RTC_UPDATE0]    = MAX77686_RTC_UPDATE0,
+	[REG_WTSR_SMPL_CNTL] = MAX77686_WTSR_SMPL_CNTL,
+	[REG_RTC_SEC]        = MAX77686_RTC_SEC,
+	[REG_RTC_MIN]        = MAX77686_RTC_MIN,
+	[REG_RTC_HOUR]       = MAX77686_RTC_HOUR,
+	[REG_RTC_WEEKDAY]    = MAX77686_RTC_WEEKDAY,
+	[REG_RTC_MONTH]      = MAX77686_RTC_MONTH,
+	[REG_RTC_YEAR]       = MAX77686_RTC_YEAR,
+	[REG_RTC_DATE]       = MAX77686_RTC_DATE,
+	[REG_ALARM1_SEC]     = MAX77686_ALARM1_SEC,
+	[REG_ALARM1_MIN]     = MAX77686_ALARM1_MIN,
+	[REG_ALARM1_HOUR]    = MAX77686_ALARM1_HOUR,
+	[REG_ALARM1_WEEKDAY] = MAX77686_ALARM1_WEEKDAY,
+	[REG_ALARM1_MONTH]   = MAX77686_ALARM1_MONTH,
+	[REG_ALARM1_YEAR]    = MAX77686_ALARM1_YEAR,
+	[REG_ALARM1_DATE]    = MAX77686_ALARM1_DATE,
+	[REG_ALARM2_SEC]     = MAX77686_ALARM2_SEC,
+	[REG_ALARM2_MIN]     = MAX77686_ALARM2_MIN,
+	[REG_ALARM2_HOUR]    = MAX77686_ALARM2_HOUR,
+	[REG_ALARM2_WEEKDAY] = MAX77686_ALARM2_WEEKDAY,
+	[REG_ALARM2_MONTH]   = MAX77686_ALARM2_MONTH,
+	[REG_ALARM2_YEAR]    = MAX77686_ALARM2_YEAR,
+	[REG_ALARM2_DATE]    = MAX77686_ALARM2_DATE,
+	[REG_RTC_AE1]	     = REG_RTC_NONE,
+};
+
+static const struct regmap_irq max77686_rtc_irqs[] = {
+	/* RTC interrupts */
+	REGMAP_IRQ_REG(0, 0, MAX77686_RTCINT_RTC60S_MSK),
+	REGMAP_IRQ_REG(1, 0, MAX77686_RTCINT_RTCA1_MSK),
+	REGMAP_IRQ_REG(2, 0, MAX77686_RTCINT_RTCA2_MSK),
+	REGMAP_IRQ_REG(3, 0, MAX77686_RTCINT_SMPL_MSK),
+	REGMAP_IRQ_REG(4, 0, MAX77686_RTCINT_RTC1S_MSK),
+	REGMAP_IRQ_REG(5, 0, MAX77686_RTCINT_WTSR_MSK),
+};
+
+static const struct regmap_irq_chip max77686_rtc_irq_chip = {
+	.name		= "max77686-rtc",
+	.status_base	= MAX77686_RTC_INT,
+	.mask_base	= MAX77686_RTC_INTM,
+	.num_regs	= 1,
+	.irqs		= max77686_rtc_irqs,
+	.num_irqs	= ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct max77686_rtc_driver_data max77686_drv_data = {
+	.delay = 16000,
+	.mask  = 0x7f,
+	.map   = max77686_map,
+	.alarm_enable_reg  = false,
+	.rtc_irq_from_platform = false,
+	.alarm_pending_status_reg = MAX77686_REG_STATUS2,
+	.rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
+	.rtc_irq_chip = &max77686_rtc_irq_chip,
+};
+
+static const struct max77686_rtc_driver_data max77620_drv_data = {
+	.delay = 16000,
+	.mask  = 0x7f,
+	.map   = max77686_map,
+	.alarm_enable_reg  = false,
+	.rtc_irq_from_platform = true,
+	.alarm_pending_status_reg = MAX77686_INVALID_REG,
+	.rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
+	.rtc_irq_chip = &max77686_rtc_irq_chip,
+};
+
+static const unsigned int max77802_map[REG_RTC_END] = {
+	[REG_RTC_CONTROLM]   = MAX77802_RTC_CONTROLM,
+	[REG_RTC_CONTROL]    = MAX77802_RTC_CONTROL,
+	[REG_RTC_UPDATE0]    = MAX77802_RTC_UPDATE0,
+	[REG_WTSR_SMPL_CNTL] = MAX77802_WTSR_SMPL_CNTL,
+	[REG_RTC_SEC]        = MAX77802_RTC_SEC,
+	[REG_RTC_MIN]        = MAX77802_RTC_MIN,
+	[REG_RTC_HOUR]       = MAX77802_RTC_HOUR,
+	[REG_RTC_WEEKDAY]    = MAX77802_RTC_WEEKDAY,
+	[REG_RTC_MONTH]      = MAX77802_RTC_MONTH,
+	[REG_RTC_YEAR]       = MAX77802_RTC_YEAR,
+	[REG_RTC_DATE]       = MAX77802_RTC_DATE,
+	[REG_ALARM1_SEC]     = MAX77802_ALARM1_SEC,
+	[REG_ALARM1_MIN]     = MAX77802_ALARM1_MIN,
+	[REG_ALARM1_HOUR]    = MAX77802_ALARM1_HOUR,
+	[REG_ALARM1_WEEKDAY] = MAX77802_ALARM1_WEEKDAY,
+	[REG_ALARM1_MONTH]   = MAX77802_ALARM1_MONTH,
+	[REG_ALARM1_YEAR]    = MAX77802_ALARM1_YEAR,
+	[REG_ALARM1_DATE]    = MAX77802_ALARM1_DATE,
+	[REG_ALARM2_SEC]     = MAX77802_ALARM2_SEC,
+	[REG_ALARM2_MIN]     = MAX77802_ALARM2_MIN,
+	[REG_ALARM2_HOUR]    = MAX77802_ALARM2_HOUR,
+	[REG_ALARM2_WEEKDAY] = MAX77802_ALARM2_WEEKDAY,
+	[REG_ALARM2_MONTH]   = MAX77802_ALARM2_MONTH,
+	[REG_ALARM2_YEAR]    = MAX77802_ALARM2_YEAR,
+	[REG_ALARM2_DATE]    = MAX77802_ALARM2_DATE,
+	[REG_RTC_AE1]	     = MAX77802_RTC_AE1,
+};
+
+static const struct regmap_irq_chip max77802_rtc_irq_chip = {
+	.name		= "max77802-rtc",
+	.status_base	= MAX77802_RTC_INT,
+	.mask_base	= MAX77802_RTC_INTM,
+	.num_regs	= 1,
+	.irqs		= max77686_rtc_irqs, /* same masks as 77686 */
+	.num_irqs	= ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct max77686_rtc_driver_data max77802_drv_data = {
+	.delay = 200,
+	.mask  = 0xff,
+	.map   = max77802_map,
+	.alarm_enable_reg  = true,
+	.rtc_irq_from_platform = false,
+	.alarm_pending_status_reg = MAX77686_REG_STATUS2,
+	.rtc_i2c_addr = MAX77686_INVALID_I2C_ADDR,
+	.rtc_irq_chip = &max77802_rtc_irq_chip,
+};
+
 static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
-				   int rtc_24hr_mode)
+				    struct max77686_rtc_info *info)
 {
-	tm->tm_sec = data[RTC_SEC] & 0x7f;
-	tm->tm_min = data[RTC_MIN] & 0x7f;
-	if (rtc_24hr_mode)
+	u8 mask = info->drv_data->mask;
+
+	tm->tm_sec = data[RTC_SEC] & mask;
+	tm->tm_min = data[RTC_MIN] & mask;
+	if (info->rtc_24hr_mode) {
 		tm->tm_hour = data[RTC_HOUR] & 0x1f;
-	else {
+	} else {
 		tm->tm_hour = data[RTC_HOUR] & 0x0f;
 		if (data[RTC_HOUR] & HOUR_PM_MASK)
 			tm->tm_hour += 12;
 	}
 
 	/* Only a single bit is set in data[], so fls() would be equivalent */
-	tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
+	tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1;
 	tm->tm_mday = data[RTC_DATE] & 0x1f;
 	tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
-	tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
+	tm->tm_year = data[RTC_YEAR] & mask;
 	tm->tm_yday = 0;
 	tm->tm_isdst = 0;
+
+	/*
+	 * MAX77686 uses 1 bit from sec/min/hour/etc RTC registers and the
+	 * year values are just 0..99 so add 100 to support up to 2099.
+	 */
+	if (!info->drv_data->alarm_enable_reg)
+		tm->tm_year += 100;
 }
 
-static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data,
+				   struct max77686_rtc_info *info)
 {
 	data[RTC_SEC] = tm->tm_sec;
 	data[RTC_MIN] = tm->tm_min;
@@ -102,35 +299,44 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
 	data[RTC_WEEKDAY] = 1 << tm->tm_wday;
 	data[RTC_DATE] = tm->tm_mday;
 	data[RTC_MONTH] = tm->tm_mon + 1;
+
+	if (info->drv_data->alarm_enable_reg) {
+		data[RTC_YEAR] = tm->tm_year;
+		return 0;
+	}
+
 	data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
 
 	if (tm->tm_year < 100) {
-		pr_warn("RTC cannot handle the year %d.  Assume it's 2000.\n",
+		dev_err(info->dev, "RTC cannot handle the year %d.\n",
 			1900 + tm->tm_year);
 		return -EINVAL;
 	}
+
 	return 0;
 }
 
 static int max77686_rtc_update(struct max77686_rtc_info *info,
-	enum MAX77686_RTC_OP op)
+			       enum MAX77686_RTC_OP op)
 {
 	int ret;
 	unsigned int data;
+	unsigned long delay = info->drv_data->delay;
 
 	if (op == MAX77686_RTC_WRITE)
 		data = 1 << RTC_UDR_SHIFT;
 	else
 		data = 1 << RTC_RBUDR_SHIFT;
 
-	ret = regmap_update_bits(info->max77686->rtc_regmap,
-				 MAX77686_RTC_UPDATE0, data, data);
+	ret = regmap_update_bits(info->rtc_regmap,
+				 info->drv_data->map[REG_RTC_UPDATE0],
+				 data, data);
 	if (ret < 0)
-		dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
-				__func__, ret, data);
+		dev_err(info->dev, "Fail to write update reg(ret=%d, data=0x%x)\n",
+			ret, data);
 	else {
-		/* Minimum 16ms delay required before RTC update. */
-		msleep(MAX77686_RTC_UPDATE_DELAY);
+		/* Minimum delay required before RTC update. */
+		usleep_range(delay, delay * 2);
 	}
 
 	return ret;
@@ -148,14 +354,15 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_bulk_read(info->max77686->rtc_regmap,
-				MAX77686_RTC_SEC, data, RTC_NR_TIME);
+	ret = regmap_bulk_read(info->rtc_regmap,
+			       info->drv_data->map[REG_RTC_SEC],
+			       data, ARRAY_SIZE(data));
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,	ret);
+		dev_err(info->dev, "Fail to read time reg(%d)\n", ret);
 		goto out;
 	}
 
-	max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
+	max77686_rtc_data_to_tm(data, tm, info);
 
 	ret = rtc_valid_tm(tm);
 
@@ -170,17 +377,17 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	u8 data[RTC_NR_TIME];
 	int ret;
 
-	ret = max77686_rtc_tm_to_data(tm, data);
+	ret = max77686_rtc_tm_to_data(tm, data, info);
 	if (ret < 0)
 		return ret;
 
 	mutex_lock(&info->lock);
 
-	ret = regmap_bulk_write(info->max77686->rtc_regmap,
-				 MAX77686_RTC_SEC, data, RTC_NR_TIME);
+	ret = regmap_bulk_write(info->rtc_regmap,
+				info->drv_data->map[REG_RTC_SEC],
+				data, ARRAY_SIZE(data));
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
-				ret);
+		dev_err(info->dev, "Fail to write time reg(%d)\n", ret);
 		goto out;
 	}
 
@@ -196,6 +403,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	struct max77686_rtc_info *info = dev_get_drvdata(dev);
 	u8 data[RTC_NR_TIME];
 	unsigned int val;
+	const unsigned int *map = info->drv_data->map;
 	int i, ret;
 
 	mutex_lock(&info->lock);
@@ -204,29 +412,53 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_bulk_read(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+	ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+			       data, ARRAY_SIZE(data));
 	if (ret < 0) {
-		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
-				__func__, __LINE__, ret);
+		dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
 		goto out;
 	}
 
-	max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+	max77686_rtc_data_to_tm(data, &alrm->time, info);
 
 	alrm->enabled = 0;
-	for (i = 0; i < RTC_NR_TIME; i++) {
-		if (data[i] & ALARM_ENABLE_MASK) {
+
+	if (info->drv_data->alarm_enable_reg) {
+		if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+			ret = -EINVAL;
+			dev_err(info->dev,
+				"alarm enable register not set(%d)\n", ret);
+			goto out;
+		}
+
+		ret = regmap_read(info->rtc_regmap, map[REG_RTC_AE1], &val);
+		if (ret < 0) {
+			dev_err(info->dev,
+				"fail to read alarm enable(%d)\n", ret);
+			goto out;
+		}
+
+		if (val)
 			alrm->enabled = 1;
-			break;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(data); i++) {
+			if (data[i] & ALARM_ENABLE_MASK) {
+				alrm->enabled = 1;
+				break;
+			}
 		}
 	}
 
 	alrm->pending = 0;
-	ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
+
+	if (info->drv_data->alarm_pending_status_reg == MAX77686_INVALID_REG)
+		goto out;
+
+	ret = regmap_read(info->regmap,
+			  info->drv_data->alarm_pending_status_reg, &val);
 	if (ret < 0) {
-		dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
-				__func__, __LINE__, ret);
+		dev_err(info->dev,
+			"Fail to read alarm pending status reg(%d)\n", ret);
 		goto out;
 	}
 
@@ -235,7 +467,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 out:
 	mutex_unlock(&info->lock);
-	return 0;
+	return ret;
 }
 
 static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
@@ -243,6 +475,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
 	u8 data[RTC_NR_TIME];
 	int ret, i;
 	struct rtc_time tm;
+	const unsigned int *map = info->drv_data->map;
 
 	if (!mutex_is_locked(&info->lock))
 		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -251,24 +484,34 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_bulk_read(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-				__func__, ret);
-		goto out;
-	}
+	if (info->drv_data->alarm_enable_reg) {
+		if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+			ret = -EINVAL;
+			dev_err(info->dev,
+				"alarm enable register not set(%d)\n", ret);
+			goto out;
+		}
+
+		ret = regmap_write(info->rtc_regmap, map[REG_RTC_AE1], 0);
+	} else {
+		ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+				       data, ARRAY_SIZE(data));
+		if (ret < 0) {
+			dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+			goto out;
+		}
 
-	max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
+		max77686_rtc_data_to_tm(data, &tm, info);
 
-	for (i = 0; i < RTC_NR_TIME; i++)
-		data[i] &= ~ALARM_ENABLE_MASK;
+		for (i = 0; i < ARRAY_SIZE(data); i++)
+			data[i] &= ~ALARM_ENABLE_MASK;
+
+		ret = regmap_bulk_write(info->rtc_regmap, map[REG_ALARM1_SEC],
+					data, ARRAY_SIZE(data));
+	}
 
-	ret = regmap_bulk_write(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-				__func__, ret);
+		dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
 		goto out;
 	}
 
@@ -282,6 +525,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
 	u8 data[RTC_NR_TIME];
 	int ret;
 	struct rtc_time tm;
+	const unsigned int *map = info->drv_data->map;
 
 	if (!mutex_is_locked(&info->lock))
 		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -290,32 +534,36 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_bulk_read(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-				__func__, ret);
-		goto out;
+	if (info->drv_data->alarm_enable_reg) {
+		ret = regmap_write(info->rtc_regmap, map[REG_RTC_AE1],
+				   MAX77802_ALARM_ENABLE_VALUE);
+	} else {
+		ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+				       data, ARRAY_SIZE(data));
+		if (ret < 0) {
+			dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+			goto out;
+		}
+
+		max77686_rtc_data_to_tm(data, &tm, info);
+
+		data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
+		data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
+		data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
+		data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
+		if (data[RTC_MONTH] & 0xf)
+			data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
+		if (data[RTC_YEAR] & info->drv_data->mask)
+			data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
+		if (data[RTC_DATE] & 0x1f)
+			data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
+
+		ret = regmap_bulk_write(info->rtc_regmap, map[REG_ALARM1_SEC],
+					data, ARRAY_SIZE(data));
 	}
 
-	max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
-
-	data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
-	data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
-	data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
-	data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
-	if (data[RTC_MONTH] & 0xf)
-		data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
-	if (data[RTC_YEAR] & 0x7f)
-		data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
-	if (data[RTC_DATE] & 0x1f)
-		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
-
-	ret = regmap_bulk_write(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-				__func__, ret);
+		dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
 		goto out;
 	}
 
@@ -330,7 +578,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	u8 data[RTC_NR_TIME];
 	int ret;
 
-	ret = max77686_rtc_tm_to_data(&alrm->time, data);
+	ret = max77686_rtc_tm_to_data(&alrm->time, data, info);
 	if (ret < 0)
 		return ret;
 
@@ -340,12 +588,12 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_bulk_write(info->max77686->rtc_regmap,
-				 MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+	ret = regmap_bulk_write(info->rtc_regmap,
+				info->drv_data->map[REG_ALARM1_SEC],
+				data, ARRAY_SIZE(data));
 
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-				__func__, ret);
+		dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
 		goto out;
 	}
 
@@ -361,7 +609,7 @@ out:
 }
 
 static int max77686_rtc_alarm_irq_enable(struct device *dev,
-					unsigned int enabled)
+					 unsigned int enabled)
 {
 	struct max77686_rtc_info *info = dev_get_drvdata(dev);
 	int ret;
@@ -380,7 +628,7 @@ static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data)
 {
 	struct max77686_rtc_info *info = data;
 
-	dev_info(info->dev, "%s:irq(%d)\n", __func__, irq);
+	dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq);
 
 	rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
 
@@ -406,10 +654,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
 
 	info->rtc_24hr_mode = 1;
 
-	ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2);
+	ret = regmap_bulk_write(info->rtc_regmap,
+				info->drv_data->map[REG_RTC_CONTROLM],
+				data, ARRAY_SIZE(data));
 	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
-				__func__, ret);
+		dev_err(info->dev, "Fail to write controlm reg(%d)\n", ret);
 		return ret;
 	}
 
@@ -417,28 +666,97 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
 	return ret;
 }
 
+static const struct regmap_config max77686_rtc_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
+{
+	struct device *parent = info->dev->parent;
+	struct i2c_client *parent_i2c = to_i2c_client(parent);
+	int ret;
+
+	if (info->drv_data->rtc_irq_from_platform) {
+		struct platform_device *pdev = to_platform_device(info->dev);
+
+		info->rtc_irq = platform_get_irq(pdev, 0);
+		if (info->rtc_irq < 0) {
+			dev_err(info->dev, "Failed to get rtc interrupts: %d\n",
+				info->rtc_irq);
+			return info->rtc_irq;
+		}
+	} else {
+		info->rtc_irq =  parent_i2c->irq;
+	}
+
+	info->regmap = dev_get_regmap(parent, NULL);
+	if (!info->regmap) {
+		dev_err(info->dev, "Failed to get rtc regmap\n");
+		return -ENODEV;
+	}
+
+	if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) {
+		info->rtc_regmap = info->regmap;
+		goto add_rtc_irq;
+	}
+
+	info->rtc = i2c_new_dummy(parent_i2c->adapter,
+				  info->drv_data->rtc_i2c_addr);
+	if (!info->rtc) {
+		dev_err(info->dev, "Failed to allocate I2C device for RTC\n");
+		return -ENODEV;
+	}
+
+	info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
+						&max77686_rtc_regmap_config);
+	if (IS_ERR(info->rtc_regmap)) {
+		ret = PTR_ERR(info->rtc_regmap);
+		dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
+		goto err_unregister_i2c;
+	}
+
+add_rtc_irq:
+	ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
+				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+				  IRQF_SHARED, 0, info->drv_data->rtc_irq_chip,
+				  &info->rtc_irq_data);
+	if (ret < 0) {
+		dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
+		goto err_unregister_i2c;
+	}
+
+	return 0;
+
+err_unregister_i2c:
+	if (info->rtc)
+		i2c_unregister_device(info->rtc);
+	return ret;
+}
+
 static int max77686_rtc_probe(struct platform_device *pdev)
 {
-	struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
 	struct max77686_rtc_info *info;
+	const struct platform_device_id *id = platform_get_device_id(pdev);
 	int ret;
 
-	dev_info(&pdev->dev, "%s\n", __func__);
-
 	info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info),
-				GFP_KERNEL);
+			    GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
 	mutex_init(&info->lock);
 	info->dev = &pdev->dev;
-	info->max77686 = max77686;
-	info->rtc = max77686->rtc;
+	info->drv_data = (const struct max77686_rtc_driver_data *)
+		id->driver_data;
+
+	ret = max77686_init_rtc_regmap(info);
+	if (ret < 0)
+		return ret;
 
 	platform_set_drvdata(pdev, info);
 
 	ret = max77686_rtc_init_reg(info);
-
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
 		goto err_rtc;
@@ -446,7 +764,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
+	info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name,
 					&max77686_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(info->rtc_dev)) {
@@ -457,29 +775,43 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 		goto err_rtc;
 	}
 
-	if (!max77686->rtc_irq_data) {
-		ret = -EINVAL;
-		dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
-		goto err_rtc;
-	}
-
-	info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
+	info->virq = regmap_irq_get_virq(info->rtc_irq_data,
 					 MAX77686_RTCIRQ_RTCA1);
-	if (!info->virq) {
+	if (info->virq <= 0) {
 		ret = -ENXIO;
 		goto err_rtc;
 	}
 
-	ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
-				max77686_rtc_alarm_irq, 0, "rtc-alarm1", info);
-	if (ret < 0)
+	ret = request_threaded_irq(info->virq, NULL, max77686_rtc_alarm_irq, 0,
+				   "rtc-alarm1", info);
+	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
 			info->virq, ret);
+		goto err_rtc;
+	}
+
+	return 0;
 
 err_rtc:
+	regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data);
+	if (info->rtc)
+		i2c_unregister_device(info->rtc);
+
 	return ret;
 }
 
+static int max77686_rtc_remove(struct platform_device *pdev)
+{
+	struct max77686_rtc_info *info = platform_get_drvdata(pdev);
+
+	free_irq(info->virq, info);
+	regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data);
+	if (info->rtc)
+		i2c_unregister_device(info->rtc);
+
+	return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int max77686_rtc_suspend(struct device *dev)
 {
@@ -508,7 +840,9 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
 			 max77686_rtc_suspend, max77686_rtc_resume);
 
 static const struct platform_device_id rtc_id[] = {
-	{ "max77686-rtc", 0 },
+	{ "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, },
+	{ "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, },
+	{ "max77620-rtc", .driver_data = (kernel_ulong_t)&max77620_drv_data, },
 	{},
 };
 MODULE_DEVICE_TABLE(platform, rtc_id);
@@ -519,6 +853,7 @@ static struct platform_driver max77686_rtc_driver = {
 		.pm	= &max77686_rtc_pm_ops,
 	},
 	.probe		= max77686_rtc_probe,
+	.remove		= max77686_rtc_remove,
 	.id_table	= rtc_id,
 };
 

+ 0 - 502
drivers/rtc/rtc-max77802.c

@@ -1,502 +0,0 @@
-/*
- * RTC driver for Maxim MAX77802
- *
- * Copyright (C) 2013 Google, Inc
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8997.c
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/rtc.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-/* RTC Control Register */
-#define BCD_EN_SHIFT			0
-#define BCD_EN_MASK			(1 << BCD_EN_SHIFT)
-#define MODEL24_SHIFT			1
-#define MODEL24_MASK			(1 << MODEL24_SHIFT)
-/* RTC Update Register1 */
-#define RTC_UDR_SHIFT			0
-#define RTC_UDR_MASK			(1 << RTC_UDR_SHIFT)
-#define RTC_RBUDR_SHIFT			4
-#define RTC_RBUDR_MASK			(1 << RTC_RBUDR_SHIFT)
-/* RTC Hour register */
-#define HOUR_PM_SHIFT			6
-#define HOUR_PM_MASK			(1 << HOUR_PM_SHIFT)
-/* RTC Alarm Enable */
-#define ALARM_ENABLE_SHIFT		7
-#define ALARM_ENABLE_MASK		(1 << ALARM_ENABLE_SHIFT)
-
-/* For the RTCAE1 register, we write this value to enable the alarm */
-#define ALARM_ENABLE_VALUE		0x77
-
-#define MAX77802_RTC_UPDATE_DELAY_US	200
-
-enum {
-	RTC_SEC = 0,
-	RTC_MIN,
-	RTC_HOUR,
-	RTC_WEEKDAY,
-	RTC_MONTH,
-	RTC_YEAR,
-	RTC_DATE,
-	RTC_NR_TIME
-};
-
-struct max77802_rtc_info {
-	struct device		*dev;
-	struct max77686_dev	*max77802;
-	struct i2c_client	*rtc;
-	struct rtc_device	*rtc_dev;
-	struct mutex		lock;
-
-	struct regmap		*regmap;
-
-	int virq;
-	int rtc_24hr_mode;
-};
-
-enum MAX77802_RTC_OP {
-	MAX77802_RTC_WRITE,
-	MAX77802_RTC_READ,
-};
-
-static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
-				   int rtc_24hr_mode)
-{
-	tm->tm_sec = data[RTC_SEC] & 0xff;
-	tm->tm_min = data[RTC_MIN] & 0xff;
-	if (rtc_24hr_mode)
-		tm->tm_hour = data[RTC_HOUR] & 0x1f;
-	else {
-		tm->tm_hour = data[RTC_HOUR] & 0x0f;
-		if (data[RTC_HOUR] & HOUR_PM_MASK)
-			tm->tm_hour += 12;
-	}
-
-	/* Only a single bit is set in data[], so fls() would be equivalent */
-	tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
-	tm->tm_mday = data[RTC_DATE] & 0x1f;
-	tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
-
-	tm->tm_year = data[RTC_YEAR] & 0xff;
-	tm->tm_yday = 0;
-	tm->tm_isdst = 0;
-}
-
-static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
-{
-	data[RTC_SEC] = tm->tm_sec;
-	data[RTC_MIN] = tm->tm_min;
-	data[RTC_HOUR] = tm->tm_hour;
-	data[RTC_WEEKDAY] = 1 << tm->tm_wday;
-	data[RTC_DATE] = tm->tm_mday;
-	data[RTC_MONTH] = tm->tm_mon + 1;
-	data[RTC_YEAR] = tm->tm_year;
-
-	return 0;
-}
-
-static int max77802_rtc_update(struct max77802_rtc_info *info,
-	enum MAX77802_RTC_OP op)
-{
-	int ret;
-	unsigned int data;
-
-	if (op == MAX77802_RTC_WRITE)
-		data = 1 << RTC_UDR_SHIFT;
-	else
-		data = 1 << RTC_RBUDR_SHIFT;
-
-	ret = regmap_update_bits(info->max77802->regmap,
-				 MAX77802_RTC_UPDATE0, data, data);
-	if (ret < 0)
-		dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
-				__func__, ret, data);
-	else {
-		/* Minimum delay required before RTC update. */
-		usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
-			     MAX77802_RTC_UPDATE_DELAY_US * 2);
-	}
-
-	return ret;
-}
-
-static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
-	struct max77802_rtc_info *info = dev_get_drvdata(dev);
-	u8 data[RTC_NR_TIME];
-	int ret;
-
-	mutex_lock(&info->lock);
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-	if (ret < 0)
-		goto out;
-
-	ret = regmap_bulk_read(info->max77802->regmap,
-				MAX77802_RTC_SEC, data, RTC_NR_TIME);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
-			ret);
-		goto out;
-	}
-
-	max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
-
-	ret = rtc_valid_tm(tm);
-
-out:
-	mutex_unlock(&info->lock);
-	return ret;
-}
-
-static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
-	struct max77802_rtc_info *info = dev_get_drvdata(dev);
-	u8 data[RTC_NR_TIME];
-	int ret;
-
-	ret = max77802_rtc_tm_to_data(tm, data);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&info->lock);
-
-	ret = regmap_bulk_write(info->max77802->regmap,
-				 MAX77802_RTC_SEC, data, RTC_NR_TIME);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
-			ret);
-		goto out;
-	}
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-
-out:
-	mutex_unlock(&info->lock);
-	return ret;
-}
-
-static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-	struct max77802_rtc_info *info = dev_get_drvdata(dev);
-	u8 data[RTC_NR_TIME];
-	unsigned int val;
-	int ret;
-
-	mutex_lock(&info->lock);
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-	if (ret < 0)
-		goto out;
-
-	ret = regmap_bulk_read(info->max77802->regmap,
-				 MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
-	if (ret < 0) {
-		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
-				__func__, __LINE__, ret);
-		goto out;
-	}
-
-	max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
-
-	alrm->enabled = 0;
-	ret = regmap_read(info->max77802->regmap,
-			  MAX77802_RTC_AE1, &val);
-	if (ret < 0) {
-		dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
-			__func__, __LINE__, ret);
-		goto out;
-	}
-	if (val)
-		alrm->enabled = 1;
-
-	alrm->pending = 0;
-	ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
-	if (ret < 0) {
-		dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
-				__func__, __LINE__, ret);
-		goto out;
-	}
-
-	if (val & (1 << 2)) /* RTCA1 */
-		alrm->pending = 1;
-
-out:
-	mutex_unlock(&info->lock);
-	return 0;
-}
-
-static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
-{
-	int ret;
-
-	if (!mutex_is_locked(&info->lock))
-		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-	if (ret < 0)
-		goto out;
-
-	ret = regmap_write(info->max77802->regmap,
-			   MAX77802_RTC_AE1, 0);
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-			__func__, ret);
-		goto out;
-	}
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
-	return ret;
-}
-
-static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
-{
-	int ret;
-
-	if (!mutex_is_locked(&info->lock))
-		dev_warn(info->dev, "%s: should have mutex locked\n",
-			 __func__);
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-	if (ret < 0)
-		goto out;
-
-	ret = regmap_write(info->max77802->regmap,
-				   MAX77802_RTC_AE1,
-				   ALARM_ENABLE_VALUE);
-
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-				__func__, ret);
-		goto out;
-	}
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
-	return ret;
-}
-
-static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-	struct max77802_rtc_info *info = dev_get_drvdata(dev);
-	u8 data[RTC_NR_TIME];
-	int ret;
-
-	ret = max77802_rtc_tm_to_data(&alrm->time, data);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&info->lock);
-
-	ret = max77802_rtc_stop_alarm(info);
-	if (ret < 0)
-		goto out;
-
-	ret = regmap_bulk_write(info->max77802->regmap,
-				 MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
-
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-				__func__, ret);
-		goto out;
-	}
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-	if (ret < 0)
-		goto out;
-
-	if (alrm->enabled)
-		ret = max77802_rtc_start_alarm(info);
-out:
-	mutex_unlock(&info->lock);
-	return ret;
-}
-
-static int max77802_rtc_alarm_irq_enable(struct device *dev,
-					 unsigned int enabled)
-{
-	struct max77802_rtc_info *info = dev_get_drvdata(dev);
-	int ret;
-
-	mutex_lock(&info->lock);
-	if (enabled)
-		ret = max77802_rtc_start_alarm(info);
-	else
-		ret = max77802_rtc_stop_alarm(info);
-	mutex_unlock(&info->lock);
-
-	return ret;
-}
-
-static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
-{
-	struct max77802_rtc_info *info = data;
-
-	dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
-
-	rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
-
-	return IRQ_HANDLED;
-}
-
-static const struct rtc_class_ops max77802_rtc_ops = {
-	.read_time = max77802_rtc_read_time,
-	.set_time = max77802_rtc_set_time,
-	.read_alarm = max77802_rtc_read_alarm,
-	.set_alarm = max77802_rtc_set_alarm,
-	.alarm_irq_enable = max77802_rtc_alarm_irq_enable,
-};
-
-static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
-{
-	u8 data[2];
-	int ret;
-
-	max77802_rtc_update(info, MAX77802_RTC_READ);
-
-	/* Set RTC control register : Binary mode, 24hour mdoe */
-	data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-	data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-
-	info->rtc_24hr_mode = 1;
-
-	ret = regmap_bulk_write(info->max77802->regmap,
-				MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
-	if (ret < 0) {
-		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
-				__func__, ret);
-		return ret;
-	}
-
-	ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-	return ret;
-}
-
-static int max77802_rtc_probe(struct platform_device *pdev)
-{
-	struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
-	struct max77802_rtc_info *info;
-	int ret;
-
-	dev_dbg(&pdev->dev, "%s\n", __func__);
-
-	info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
-			    GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	mutex_init(&info->lock);
-	info->dev = &pdev->dev;
-	info->max77802 = max77802;
-	info->rtc = max77802->i2c;
-
-	platform_set_drvdata(pdev, info);
-
-	ret = max77802_rtc_init_reg(info);
-
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
-		return ret;
-	}
-
-	device_init_wakeup(&pdev->dev, 1);
-
-	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
-						 &max77802_rtc_ops, THIS_MODULE);
-
-	if (IS_ERR(info->rtc_dev)) {
-		ret = PTR_ERR(info->rtc_dev);
-		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
-		if (ret == 0)
-			ret = -EINVAL;
-		return ret;
-	}
-
-	if (!max77802->rtc_irq_data) {
-		dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
-		return -EINVAL;
-	}
-
-	info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
-					 MAX77686_RTCIRQ_RTCA1);
-
-	if (info->virq <= 0) {
-		dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
-			MAX77686_RTCIRQ_RTCA1);
-		return -EINVAL;
-	}
-
-	ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
-					max77802_rtc_alarm_irq, 0, "rtc-alarm1",
-					info);
-	if (ret < 0)
-		dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
-			info->virq, ret);
-
-	return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int max77802_rtc_suspend(struct device *dev)
-{
-	if (device_may_wakeup(dev)) {
-		struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
-		return enable_irq_wake(info->virq);
-	}
-
-	return 0;
-}
-
-static int max77802_rtc_resume(struct device *dev)
-{
-	if (device_may_wakeup(dev)) {
-		struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
-		return disable_irq_wake(info->virq);
-	}
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
-			 max77802_rtc_suspend, max77802_rtc_resume);
-
-static const struct platform_device_id rtc_id[] = {
-	{ "max77802-rtc", 0 },
-	{},
-};
-MODULE_DEVICE_TABLE(platform, rtc_id);
-
-static struct platform_driver max77802_rtc_driver = {
-	.driver		= {
-		.name	= "max77802-rtc",
-		.pm	= &max77802_rtc_pm_ops,
-	},
-	.probe		= max77802_rtc_probe,
-	.id_table	= rtc_id,
-};
-
-module_platform_driver(max77802_rtc_driver);
-
-MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
-MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
-MODULE_LICENSE("GPL");

+ 0 - 1
drivers/rtc/rtc-mt6397.c

@@ -419,4 +419,3 @@ module_platform_driver(mtk_rtc_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
 MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
-MODULE_ALIAS("platform:mt6397-rtc");

+ 1 - 2
drivers/rtc/rtc-palmas.c

@@ -311,8 +311,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
 
 	ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL,
 			palmas_rtc_interrupt,
-			IRQF_TRIGGER_LOW | IRQF_ONESHOT |
-			IRQF_EARLY_RESUME,
+			IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 			dev_name(&pdev->dev), palmas_rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret);

+ 194 - 77
drivers/rtc/rtc-pcf2123.c

@@ -48,6 +48,7 @@
 
 #define DRV_VERSION "0.6"
 
+/* REGISTERS */
 #define PCF2123_REG_CTRL1	(0x00)	/* Control Register 1 */
 #define PCF2123_REG_CTRL2	(0x01)	/* Control Register 2 */
 #define PCF2123_REG_SC		(0x02)	/* datetime */
@@ -57,10 +58,54 @@
 #define PCF2123_REG_DW		(0x06)
 #define PCF2123_REG_MO		(0x07)
 #define PCF2123_REG_YR		(0x08)
+#define PCF2123_REG_ALRM_MN	(0x09)	/* Alarm Registers */
+#define PCF2123_REG_ALRM_HR	(0x0a)
+#define PCF2123_REG_ALRM_DM	(0x0b)
+#define PCF2123_REG_ALRM_DW	(0x0c)
+#define PCF2123_REG_OFFSET	(0x0d)	/* Clock Rate Offset Register */
+#define PCF2123_REG_TMR_CLKOUT	(0x0e)	/* Timer Registers */
+#define PCF2123_REG_CTDWN_TMR	(0x0f)
+
+/* PCF2123_REG_CTRL1 BITS */
+#define CTRL1_CLEAR		(0)	/* Clear */
+#define CTRL1_CORR_INT		BIT(1)	/* Correction irq enable */
+#define CTRL1_12_HOUR		BIT(2)	/* 12 hour time */
+#define CTRL1_SW_RESET	(BIT(3) | BIT(4) | BIT(6))	/* Software reset */
+#define CTRL1_STOP		BIT(5)	/* Stop the clock */
+#define CTRL1_EXT_TEST		BIT(7)	/* External clock test mode */
+
+/* PCF2123_REG_CTRL2 BITS */
+#define CTRL2_TIE		BIT(0)	/* Countdown timer irq enable */
+#define CTRL2_AIE		BIT(1)	/* Alarm irq enable */
+#define CTRL2_TF		BIT(2)	/* Countdown timer flag */
+#define CTRL2_AF		BIT(3)	/* Alarm flag */
+#define CTRL2_TI_TP		BIT(4)	/* Irq pin generates pulse */
+#define CTRL2_MSF		BIT(5)	/* Minute or second irq flag */
+#define CTRL2_SI		BIT(6)	/* Second irq enable */
+#define CTRL2_MI		BIT(7)	/* Minute irq enable */
+
+/* PCF2123_REG_SC BITS */
+#define OSC_HAS_STOPPED		BIT(7)	/* Clock has been stopped */
+
+/* PCF2123_REG_ALRM_XX BITS */
+#define ALRM_ENABLE		BIT(7)	/* MN, HR, DM, or DW alarm enable */
+
+/* PCF2123_REG_TMR_CLKOUT BITS */
+#define CD_TMR_4096KHZ		(0)	/* 4096 KHz countdown timer */
+#define CD_TMR_64HZ		(1)	/* 64 Hz countdown timer */
+#define CD_TMR_1HZ		(2)	/* 1 Hz countdown timer */
+#define CD_TMR_60th_HZ		(3)	/* 60th Hz countdown timer */
+#define CD_TMR_TE		BIT(3)	/* Countdown timer enable */
+
+/* PCF2123_REG_OFFSET BITS */
+#define OFFSET_SIGN_BIT		BIT(6)	/* 2's complement sign bit */
+#define OFFSET_COARSE		BIT(7)	/* Coarse mode offset */
+#define OFFSET_STEP		(2170)	/* Offset step in parts per billion */
+
+/* READ/WRITE ADDRESS BITS */
+#define PCF2123_WRITE		BIT(4)
+#define PCF2123_READ		(BIT(4) | BIT(7))
 
-#define PCF2123_SUBADDR		(1 << 4)
-#define PCF2123_WRITE		((0 << 7) | PCF2123_SUBADDR)
-#define PCF2123_READ		((1 << 7) | PCF2123_SUBADDR)
 
 static struct spi_driver pcf2123_driver;
 
@@ -84,12 +129,44 @@ static inline void pcf2123_delay_trec(void)
 	ndelay(30);
 }
 
+static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int ret;
+
+	reg |= PCF2123_READ;
+	ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
+	pcf2123_delay_trec();
+
+	return ret;
+}
+
+static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int ret;
+
+	txbuf[0] |= PCF2123_WRITE;
+	ret = spi_write(spi, txbuf, size);
+	pcf2123_delay_trec();
+
+	return ret;
+}
+
+static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val)
+{
+	u8 txbuf[2];
+
+	txbuf[0] = reg;
+	txbuf[1] = val;
+	return pcf2123_write(dev, txbuf, sizeof(txbuf));
+}
+
 static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
 			    char *buffer)
 {
-	struct spi_device *spi = to_spi_device(dev);
 	struct pcf2123_sysfs_reg *r;
-	u8 txbuf[1], rxbuf[1];
+	u8 rxbuf[1];
 	unsigned long reg;
 	int ret;
 
@@ -99,19 +176,16 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
 	if (ret)
 		return ret;
 
-	txbuf[0] = PCF2123_READ | reg;
-	ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
+	ret = pcf2123_read(dev, reg, rxbuf, 1);
 	if (ret < 0)
 		return -EIO;
-	pcf2123_delay_trec();
+
 	return sprintf(buffer, "0x%x\n", rxbuf[0]);
 }
 
 static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
 			     const char *buffer, size_t count) {
-	struct spi_device *spi = to_spi_device(dev);
 	struct pcf2123_sysfs_reg *r;
-	u8 txbuf[2];
 	unsigned long reg;
 	unsigned long val;
 
@@ -127,27 +201,78 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
 	if (ret)
 		return ret;
 
-	txbuf[0] = PCF2123_WRITE | reg;
-	txbuf[1] = val;
-	ret = spi_write(spi, txbuf, sizeof(txbuf));
+	pcf2123_write_reg(dev, reg, val);
 	if (ret < 0)
 		return -EIO;
-	pcf2123_delay_trec();
 	return count;
 }
 
+static int pcf2123_read_offset(struct device *dev, long *offset)
+{
+	int ret;
+	s8 reg;
+
+	ret = pcf2123_read(dev, PCF2123_REG_OFFSET, &reg, 1);
+	if (ret < 0)
+		return ret;
+
+	if (reg & OFFSET_COARSE)
+		reg <<= 1; /* multiply by 2 and sign extend */
+	else
+		reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
+
+	*offset = ((long)reg) * OFFSET_STEP;
+
+	return 0;
+}
+
+/*
+ * The offset register is a 7 bit signed value with a coarse bit in bit 7.
+ * The main difference between the two is normal offset adjusts the first
+ * second of n minutes every other hour, with 61, 62 and 63 being shoved
+ * into the 60th minute.
+ * The coarse adjustment does the same, but every hour.
+ * the two overlap, with every even normal offset value corresponding
+ * to a coarse offset. Based on this algorithm, it seems that despite the
+ * name, coarse offset is a better fit for overlapping values.
+ */
+static int pcf2123_set_offset(struct device *dev, long offset)
+{
+	s8 reg;
+
+	if (offset > OFFSET_STEP * 127)
+		reg = 127;
+	else if (offset < OFFSET_STEP * -128)
+		reg = -128;
+	else
+		reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP);
+
+	/* choose fine offset only for odd values in the normal range */
+	if (reg & 1 && reg <= 63 && reg >= -64) {
+		/* Normal offset. Clear the coarse bit */
+		reg &= ~OFFSET_COARSE;
+	} else {
+		/* Coarse offset. Divide by 2 and set the coarse bit */
+		reg >>= 1;
+		reg |= OFFSET_COARSE;
+	}
+
+	return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg);
+}
+
 static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	struct spi_device *spi = to_spi_device(dev);
-	u8 txbuf[1], rxbuf[7];
+	u8 rxbuf[7];
 	int ret;
 
-	txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
-	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
-			rxbuf, sizeof(rxbuf));
+	ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
 	if (ret < 0)
 		return ret;
-	pcf2123_delay_trec();
+
+	if (rxbuf[0] & OSC_HAS_STOPPED) {
+		dev_info(dev, "clock was stopped. Time is not valid\n");
+		return -EINVAL;
+	}
 
 	tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
 	tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
@@ -170,7 +295,6 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	struct spi_device *spi = to_spi_device(dev);
 	u8 txbuf[8];
 	int ret;
 
@@ -181,15 +305,12 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
 	/* Stop the counter first */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-	txbuf[1] = 0x20;
-	ret = spi_write(spi, txbuf, 2);
+	ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
 	if (ret < 0)
 		return ret;
-	pcf2123_delay_trec();
 
 	/* Set the new time */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
+	txbuf[0] = PCF2123_REG_SC;
 	txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
 	txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
 	txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
@@ -198,18 +319,48 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
 	txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
 
-	ret = spi_write(spi, txbuf, sizeof(txbuf));
+	ret = pcf2123_write(dev, txbuf, sizeof(txbuf));
 	if (ret < 0)
 		return ret;
-	pcf2123_delay_trec();
 
 	/* Start the counter */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-	txbuf[1] = 0x00;
-	ret = spi_write(spi, txbuf, 2);
+	ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int pcf2123_reset(struct device *dev)
+{
+	int ret;
+	u8  rxbuf[2];
+
+	ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
+	if (ret < 0)
+		return ret;
+
+	/* Stop the counter */
+	dev_dbg(dev, "stopping RTC\n");
+	ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
+	if (ret < 0)
+		return ret;
+
+	/* See if the counter was actually stopped */
+	dev_dbg(dev, "checking for presence of RTC\n");
+	ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf));
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n",
+		rxbuf[0], rxbuf[1]);
+	if (!(rxbuf[0] & CTRL1_STOP))
+		return -ENODEV;
+
+	/* Start the counter */
+	ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
 	if (ret < 0)
 		return ret;
-	pcf2123_delay_trec();
 
 	return 0;
 }
@@ -217,13 +368,16 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static const struct rtc_class_ops pcf2123_rtc_ops = {
 	.read_time	= pcf2123_rtc_read_time,
 	.set_time	= pcf2123_rtc_set_time,
+	.read_offset	= pcf2123_read_offset,
+	.set_offset	= pcf2123_set_offset,
+
 };
 
 static int pcf2123_probe(struct spi_device *spi)
 {
 	struct rtc_device *rtc;
+	struct rtc_time tm;
 	struct pcf2123_plat_data *pdata;
-	u8 txbuf[2], rxbuf[2];
 	int ret, i;
 
 	pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
@@ -232,56 +386,19 @@ static int pcf2123_probe(struct spi_device *spi)
 		return -ENOMEM;
 	spi->dev.platform_data = pdata;
 
-	/* Send a software reset command */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-	txbuf[1] = 0x58;
-	dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n",
-			txbuf[0], txbuf[1]);
-	ret = spi_write(spi, txbuf, 2 * sizeof(u8));
-	if (ret < 0)
-		goto kfree_exit;
-	pcf2123_delay_trec();
-
-	/* Stop the counter */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-	txbuf[1] = 0x20;
-	dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n",
-			txbuf[0], txbuf[1]);
-	ret = spi_write(spi, txbuf, 2 * sizeof(u8));
-	if (ret < 0)
-		goto kfree_exit;
-	pcf2123_delay_trec();
-
-	/* See if the counter was actually stopped */
-	txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
-	dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n",
-			txbuf[0]);
-	ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8),
-					rxbuf, 2 * sizeof(u8));
-	dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n",
-			rxbuf[0], rxbuf[1]);
-	if (ret < 0)
-		goto kfree_exit;
-	pcf2123_delay_trec();
-
-	if (!(rxbuf[0] & 0x20)) {
-		dev_err(&spi->dev, "chip not found\n");
-		ret = -ENODEV;
-		goto kfree_exit;
+	ret = pcf2123_rtc_read_time(&spi->dev, &tm);
+	if (ret < 0) {
+		ret = pcf2123_reset(&spi->dev);
+		if (ret < 0) {
+			dev_err(&spi->dev, "chip not found\n");
+			goto kfree_exit;
+		}
 	}
 
 	dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
 	dev_info(&spi->dev, "spiclk %u KHz.\n",
 			(spi->max_speed_hz + 500) / 1000);
 
-	/* Start the counter */
-	txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-	txbuf[1] = 0x00;
-	ret = spi_write(spi, txbuf, sizeof(txbuf));
-	if (ret < 0)
-		goto kfree_exit;
-	pcf2123_delay_trec();
-
 	/* Finalize the initialization */
 	rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name,
 			&pcf2123_rtc_ops, THIS_MODULE);

+ 263 - 72
drivers/rtc/rtc-pcf2127.c

@@ -1,12 +1,12 @@
 /*
- * An I2C driver for the NXP PCF2127 RTC
+ * An I2C and SPI driver for the NXP PCF2127/29 RTC
  * Copyright 2013 Til-Technologies
  *
  * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
  *
  * based on the other drivers in this same directory.
  *
- * http://www.nxp.com/documents/data_sheet/PCF2127AT.pdf
+ * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,11 +14,13 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 
 #define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
 #define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
@@ -36,29 +38,30 @@
 
 #define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 
-static struct i2c_driver pcf2127_driver;
-
 struct pcf2127 {
 	struct rtc_device *rtc;
+	struct regmap *regmap;
 };
 
 /*
  * In the routines that deal directly with the pcf2127 hardware, we use
  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
  */
-static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	unsigned char buf[10] = { PCF2127_REG_CTRL1 };
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	unsigned char buf[10];
+	int ret;
 
-	/* read registers */
-	if (i2c_master_send(client, buf, 1) != 1 ||
-		i2c_master_recv(client, buf, sizeof(buf)) != sizeof(buf)) {
-		dev_err(&client->dev, "%s: read error\n", __func__);
-		return -EIO;
+	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, buf,
+				sizeof(buf));
+	if (ret) {
+		dev_err(dev, "%s: read error\n", __func__);
+		return ret;
 	}
 
 	if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
-		dev_info(&client->dev,
+		dev_info(dev,
 			"low voltage detected, check/replace RTC battery.\n");
 
 	if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
@@ -66,12 +69,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 		 * no need clear the flag here,
 		 * it will be cleared once the new date is saved
 		 */
-		dev_warn(&client->dev,
+		dev_warn(dev,
 			 "oscillator stop detected, date/time is not reliable\n");
 		return -EINVAL;
 	}
 
-	dev_dbg(&client->dev,
+	dev_dbg(dev,
 		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
 		"sec=%02x, min=%02x, hr=%02x, "
 		"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
@@ -91,7 +94,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 	if (tm->tm_year < 70)
 		tm->tm_year += 100;	/* assume we are in 1970...2069 */
 
-	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
 		__func__,
 		tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -100,20 +103,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 	return rtc_valid_tm(tm);
 }
 
-static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	unsigned char buf[8];
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+	unsigned char buf[7];
 	int i = 0, err;
 
-	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+	dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
 		__func__,
 		tm->tm_sec, tm->tm_min, tm->tm_hour,
 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
-	/* start register address */
-	buf[i++] = PCF2127_REG_SC;
-
 	/* hours, minutes and seconds */
 	buf[i++] = bin2bcd(tm->tm_sec);	/* this will also clear OSF flag */
 	buf[i++] = bin2bcd(tm->tm_min);
@@ -128,11 +129,11 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 	buf[i++] = bin2bcd(tm->tm_year % 100);
 
 	/* write register's data */
-	err = i2c_master_send(client, buf, i);
-	if (err != i) {
-		dev_err(&client->dev,
+	err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
+	if (err) {
+		dev_err(dev,
 			"%s: err=%d", __func__, err);
-		return -EIO;
+		return err;
 	}
 
 	return 0;
@@ -142,26 +143,17 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf2127_rtc_ioctl(struct device *dev,
 				unsigned int cmd, unsigned long arg)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	unsigned char buf = PCF2127_REG_CTRL3;
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
 	int touser;
 	int ret;
 
 	switch (cmd) {
 	case RTC_VL_READ:
-		ret = i2c_master_send(client, &buf, 1);
-		if (!ret)
-			ret = -EIO;
-		if (ret < 0)
-			return ret;
-
-		ret = i2c_master_recv(client, &buf, 1);
-		if (!ret)
-			ret = -EIO;
-		if (ret < 0)
+		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser);
+		if (ret)
 			return ret;
 
-		touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+		touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0;
 
 		if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
 			return -EFAULT;
@@ -174,71 +166,270 @@ static int pcf2127_rtc_ioctl(struct device *dev,
 #define pcf2127_rtc_ioctl NULL
 #endif
 
-static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
-	return pcf2127_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
-	return pcf2127_set_datetime(to_i2c_client(dev), tm);
-}
-
 static const struct rtc_class_ops pcf2127_rtc_ops = {
 	.ioctl		= pcf2127_rtc_ioctl,
 	.read_time	= pcf2127_rtc_read_time,
 	.set_time	= pcf2127_rtc_set_time,
 };
 
-static int pcf2127_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
+static int pcf2127_probe(struct device *dev, struct regmap *regmap,
+			const char *name)
 {
 	struct pcf2127 *pcf2127;
 
-	dev_dbg(&client->dev, "%s\n", __func__);
+	dev_dbg(dev, "%s\n", __func__);
 
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-		return -ENODEV;
-
-	pcf2127 = devm_kzalloc(&client->dev, sizeof(struct pcf2127),
-				GFP_KERNEL);
+	pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
 	if (!pcf2127)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, pcf2127);
+	pcf2127->regmap = regmap;
+
+	dev_set_drvdata(dev, pcf2127);
 
-	pcf2127->rtc = devm_rtc_device_register(&client->dev,
-				pcf2127_driver.driver.name,
-				&pcf2127_rtc_ops, THIS_MODULE);
+	pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
+						THIS_MODULE);
 
 	return PTR_ERR_OR_ZERO(pcf2127->rtc);
 }
 
-static const struct i2c_device_id pcf2127_id[] = {
-	{ "pcf2127", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, pcf2127_id);
-
 #ifdef CONFIG_OF
 static const struct of_device_id pcf2127_of_match[] = {
 	{ .compatible = "nxp,pcf2127" },
+	{ .compatible = "nxp,pcf2129" },
 	{}
 };
 MODULE_DEVICE_TABLE(of, pcf2127_of_match);
 #endif
 
-static struct i2c_driver pcf2127_driver = {
+#if IS_ENABLED(CONFIG_I2C)
+
+static int pcf2127_i2c_write(void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	ret = i2c_master_send(client, data, count);
+	if (ret != count)
+		return ret < 0 ? ret : -EIO;
+
+	return 0;
+}
+
+static int pcf2127_i2c_gather_write(void *context,
+				const void *reg, size_t reg_size,
+				const void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+	void *buf;
+
+	if (WARN_ON(reg_size != 1))
+		return -EINVAL;
+
+	buf = kmalloc(val_size + 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, reg, 1);
+	memcpy(buf + 1, val, val_size);
+
+	ret = i2c_master_send(client, buf, val_size + 1);
+	if (ret != val_size + 1)
+		return ret < 0 ? ret : -EIO;
+
+	return 0;
+}
+
+static int pcf2127_i2c_read(void *context, const void *reg, size_t reg_size,
+				void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+
+	if (WARN_ON(reg_size != 1))
+		return -EINVAL;
+
+	ret = i2c_master_send(client, reg, 1);
+	if (ret != 1)
+		return ret < 0 ? ret : -EIO;
+
+	ret = i2c_master_recv(client, val, val_size);
+	if (ret != val_size)
+		return ret < 0 ? ret : -EIO;
+
+	return 0;
+}
+
+/*
+ * The reason we need this custom regmap_bus instead of using regmap_init_i2c()
+ * is that the STOP condition is required between set register address and
+ * read register data when reading from registers.
+ */
+static const struct regmap_bus pcf2127_i2c_regmap = {
+	.write = pcf2127_i2c_write,
+	.gather_write = pcf2127_i2c_gather_write,
+	.read = pcf2127_i2c_read,
+};
+
+static struct i2c_driver pcf2127_i2c_driver;
+
+static int pcf2127_i2c_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	static const struct regmap_config config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+	};
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap,
+					&client->dev, &config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+			__func__, PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	return pcf2127_probe(&client->dev, regmap,
+				pcf2127_i2c_driver.driver.name);
+}
+
+static const struct i2c_device_id pcf2127_i2c_id[] = {
+	{ "pcf2127", 0 },
+	{ "pcf2129", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
+
+static struct i2c_driver pcf2127_i2c_driver = {
+	.driver		= {
+		.name	= "rtc-pcf2127-i2c",
+		.of_match_table = of_match_ptr(pcf2127_of_match),
+	},
+	.probe		= pcf2127_i2c_probe,
+	.id_table	= pcf2127_i2c_id,
+};
+
+static int pcf2127_i2c_register_driver(void)
+{
+	return i2c_add_driver(&pcf2127_i2c_driver);
+}
+
+static void pcf2127_i2c_unregister_driver(void)
+{
+	i2c_del_driver(&pcf2127_i2c_driver);
+}
+
+#else
+
+static int pcf2127_i2c_register_driver(void)
+{
+	return 0;
+}
+
+static void pcf2127_i2c_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static struct spi_driver pcf2127_spi_driver;
+
+static int pcf2127_spi_probe(struct spi_device *spi)
+{
+	static const struct regmap_config config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+		.read_flag_mask = 0xa0,
+		.write_flag_mask = 0x20,
+	};
+	struct regmap *regmap;
+
+	regmap = devm_regmap_init_spi(spi, &config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+			__func__, PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+}
+
+static const struct spi_device_id pcf2127_spi_id[] = {
+	{ "pcf2127", 0 },
+	{ "pcf2129", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
+
+static struct spi_driver pcf2127_spi_driver = {
 	.driver		= {
-		.name	= "rtc-pcf2127",
+		.name	= "rtc-pcf2127-spi",
 		.of_match_table = of_match_ptr(pcf2127_of_match),
 	},
-	.probe		= pcf2127_probe,
-	.id_table	= pcf2127_id,
+	.probe		= pcf2127_spi_probe,
+	.id_table	= pcf2127_spi_id,
 };
 
-module_i2c_driver(pcf2127_driver);
+static int pcf2127_spi_register_driver(void)
+{
+	return spi_register_driver(&pcf2127_spi_driver);
+}
+
+static void pcf2127_spi_unregister_driver(void)
+{
+	spi_unregister_driver(&pcf2127_spi_driver);
+}
+
+#else
+
+static int pcf2127_spi_register_driver(void)
+{
+	return 0;
+}
+
+static void pcf2127_spi_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init pcf2127_init(void)
+{
+	int ret;
+
+	ret = pcf2127_i2c_register_driver();
+	if (ret) {
+		pr_err("Failed to register pcf2127 i2c driver: %d\n", ret);
+		return ret;
+	}
+
+	ret = pcf2127_spi_register_driver();
+	if (ret) {
+		pr_err("Failed to register pcf2127 spi driver: %d\n", ret);
+		pcf2127_i2c_unregister_driver();
+	}
+
+	return ret;
+}
+module_init(pcf2127_init)
+
+static void __exit pcf2127_exit(void)
+{
+	pcf2127_spi_unregister_driver();
+	pcf2127_i2c_unregister_driver();
+}
+module_exit(pcf2127_exit)
 
 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
-MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
+MODULE_DESCRIPTION("NXP PCF2127/29 RTC driver");
 MODULE_LICENSE("GPL v2");

+ 86 - 76
drivers/rtc/rtc-pcf85063.c

@@ -16,12 +16,12 @@
 #include <linux/rtc.h>
 #include <linux/module.h>
 
-#define DRV_VERSION "0.0.1"
-
 #define PCF85063_REG_CTRL1		0x00 /* status */
+#define PCF85063_REG_CTRL1_STOP		BIT(5)
 #define PCF85063_REG_CTRL2		0x01
 
 #define PCF85063_REG_SC			0x04 /* datetime */
+#define PCF85063_REG_SC_OS		0x80
 #define PCF85063_REG_MN			0x05
 #define PCF85063_REG_HR			0x06
 #define PCF85063_REG_DM			0x07
@@ -29,15 +29,31 @@
 #define PCF85063_REG_MO			0x09
 #define PCF85063_REG_YR			0x0A
 
-#define PCF85063_MO_C			0x80 /* century */
-
 static struct i2c_driver pcf85063_driver;
 
-struct pcf85063 {
-	struct rtc_device *rtc;
-	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
-	int voltage_low; /* indicates if a low_voltage was detected */
-};
+static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
+{
+	s32 ret;
+
+	ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failing to stop the clock\n");
+		return -EIO;
+	}
+
+	/* stop the clock */
+	ret |= PCF85063_REG_CTRL1_STOP;
+
+	ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failing to stop the clock\n");
+		return -EIO;
+	}
+
+	*ctrl1 = ret;
+
+	return 0;
+}
 
 /*
  * In the routines that deal directly with the pcf85063 hardware, we use
@@ -45,81 +61,85 @@ struct pcf85063 {
  */
 static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-	struct pcf85063 *pcf85063 = i2c_get_clientdata(client);
-	unsigned char buf[13] = { PCF85063_REG_CTRL1 };
-	struct i2c_msg msgs[] = {
-		{/* setup read ptr */
-			.addr = client->addr,
-			.len = 1,
-			.buf = buf
-		},
-		{/* read status + date */
-			.addr = client->addr,
-			.flags = I2C_M_RD,
-			.len = 13,
-			.buf = buf
-		},
-	};
-
-	/* read registers */
-	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
-		dev_err(&client->dev, "%s: read error\n", __func__);
+	int rc;
+	u8 regs[7];
+
+	/*
+	 * while reading, the time/date registers are blocked and not updated
+	 * anymore until the access is finished. To not lose a second
+	 * event, the access must be finished within one second. So, read all
+	 * time/date registers in one turn.
+	 */
+	rc = i2c_smbus_read_i2c_block_data(client, PCF85063_REG_SC,
+					   sizeof(regs), regs);
+	if (rc != sizeof(regs)) {
+		dev_err(&client->dev, "date/time register read error\n");
 		return -EIO;
 	}
 
-	tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F);
-	tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F);
-	tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */
-	tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F);
-	tm->tm_wday = buf[PCF85063_REG_DW] & 0x07;
-	tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-	tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]);
+	/* if the clock has lost its power it makes no sense to use its time */
+	if (regs[0] & PCF85063_REG_SC_OS) {
+		dev_warn(&client->dev, "Power loss detected, invalid time\n");
+		return -EINVAL;
+	}
+
+	tm->tm_sec = bcd2bin(regs[0] & 0x7F);
+	tm->tm_min = bcd2bin(regs[1] & 0x7F);
+	tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */
+	tm->tm_mday = bcd2bin(regs[3] & 0x3F);
+	tm->tm_wday = regs[4] & 0x07;
+	tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
+	tm->tm_year = bcd2bin(regs[6]);
 	if (tm->tm_year < 70)
 		tm->tm_year += 100;	/* assume we are in 1970...2069 */
-	/* detect the polarity heuristically. see note above. */
-	pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
-		(tm->tm_year >= 100) : (tm->tm_year < 100);
 
 	return rtc_valid_tm(tm);
 }
 
 static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-	int i = 0, err = 0;
-	unsigned char buf[11];
+	int rc;
+	u8 regs[8];
 
-	/* Control & status */
-	buf[PCF85063_REG_CTRL1] = 0;
-	buf[PCF85063_REG_CTRL2] = 5;
+	/*
+	 * to accurately set the time, reset the divider chain and keep it in
+	 * reset state until all time/date registers are written
+	 */
+	rc = pcf85063_stop_clock(client, &regs[7]);
+	if (rc != 0)
+		return rc;
 
 	/* hours, minutes and seconds */
-	buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F;
+	regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */
 
-	buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min);
-	buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour);
+	regs[1] = bin2bcd(tm->tm_min);
+	regs[2] = bin2bcd(tm->tm_hour);
 
 	/* Day of month, 1 - 31 */
-	buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday);
+	regs[3] = bin2bcd(tm->tm_mday);
 
 	/* Day, 0 - 6 */
-	buf[PCF85063_REG_DW] = tm->tm_wday & 0x07;
+	regs[4] = tm->tm_wday & 0x07;
 
 	/* month, 1 - 12 */
-	buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1);
+	regs[5] = bin2bcd(tm->tm_mon + 1);
 
 	/* year and century */
-	buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100);
-
-	/* write register's data */
-	for (i = 0; i < sizeof(buf); i++) {
-		unsigned char data[2] = { i, buf[i] };
-
-		err = i2c_master_send(client, data, sizeof(data));
-		if (err != sizeof(data)) {
-			dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n",
-					__func__, err, data[0], data[1]);
-			return -EIO;
-		}
+	regs[6] = bin2bcd(tm->tm_year % 100);
+
+	/*
+	 * after all time/date registers are written, let the 'address auto
+	 * increment' feature wrap around and write register CTRL1 to re-enable
+	 * the clock divider chain again
+	 */
+	regs[7] &= ~PCF85063_REG_CTRL1_STOP;
+
+	/* write all registers at once */
+	rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
+					    sizeof(regs), regs);
+	if (rc < 0) {
+		dev_err(&client->dev, "date/time register write error\n");
+		return rc;
 	}
 
 	return 0;
@@ -143,27 +163,18 @@ static const struct rtc_class_ops pcf85063_rtc_ops = {
 static int pcf85063_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
-	struct pcf85063 *pcf85063;
+	struct rtc_device *rtc;
 
 	dev_dbg(&client->dev, "%s\n", __func__);
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
 
-	pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
-				GFP_KERNEL);
-	if (!pcf85063)
-		return -ENOMEM;
-
-	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
-	i2c_set_clientdata(client, pcf85063);
-
-	pcf85063->rtc = devm_rtc_device_register(&client->dev,
-				pcf85063_driver.driver.name,
-				&pcf85063_rtc_ops, THIS_MODULE);
+	rtc = devm_rtc_device_register(&client->dev,
+				       pcf85063_driver.driver.name,
+				       &pcf85063_rtc_ops, THIS_MODULE);
 
-	return PTR_ERR_OR_ZERO(pcf85063->rtc);
+	return PTR_ERR_OR_ZERO(rtc);
 }
 
 static const struct i2c_device_id pcf85063_id[] = {
@@ -194,4 +205,3 @@ module_i2c_driver(pcf85063_driver);
 MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>");
 MODULE_DESCRIPTION("PCF85063 RTC driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);

+ 3 - 22
drivers/rtc/rtc-pcf8523.c

@@ -178,28 +178,8 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	if (err < 0)
 		return err;
 
-	if (regs[0] & REG_SECONDS_OS) {
-		/*
-		 * If the oscillator was stopped, try to clear the flag. Upon
-		 * power-up the flag is always set, but if we cannot clear it
-		 * the oscillator isn't running properly for some reason. The
-		 * sensible thing therefore is to return an error, signalling
-		 * that the clock cannot be assumed to be correct.
-		 */
-
-		regs[0] &= ~REG_SECONDS_OS;
-
-		err = pcf8523_write(client, REG_SECONDS, regs[0]);
-		if (err < 0)
-			return err;
-
-		err = pcf8523_read(client, REG_SECONDS, &regs[0]);
-		if (err < 0)
-			return err;
-
-		if (regs[0] & REG_SECONDS_OS)
-			return -EAGAIN;
-	}
+	if (regs[0] & REG_SECONDS_OS)
+		return -EINVAL;
 
 	tm->tm_sec = bcd2bin(regs[0] & 0x7f);
 	tm->tm_min = bcd2bin(regs[1] & 0x7f);
@@ -235,6 +215,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
 		return err;
 
 	regs[0] = REG_SECONDS;
+	/* This will purposely overwrite REG_SECONDS_OS */
 	regs[1] = bin2bcd(tm->tm_sec);
 	regs[2] = bin2bcd(tm->tm_min);
 	regs[3] = bin2bcd(tm->tm_hour);

+ 411 - 0
drivers/rtc/rtc-pic32.c

@@ -0,0 +1,411 @@
+/*
+ * PIC32 RTC driver
+ *
+ * Joshua Henderson <joshua.henderson@microchip.com>
+ * Copyright (C) 2016 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/mach-pic32/pic32.h>
+
+#define PIC32_RTCCON		0x00
+#define PIC32_RTCCON_ON		BIT(15)
+#define PIC32_RTCCON_SIDL	BIT(13)
+#define PIC32_RTCCON_RTCCLKSEL	(3 << 9)
+#define PIC32_RTCCON_RTCCLKON	BIT(6)
+#define PIC32_RTCCON_RTCWREN	BIT(3)
+#define PIC32_RTCCON_RTCSYNC	BIT(2)
+#define PIC32_RTCCON_HALFSEC	BIT(1)
+#define PIC32_RTCCON_RTCOE	BIT(0)
+
+#define PIC32_RTCALRM		0x10
+#define PIC32_RTCALRM_ALRMEN	BIT(15)
+#define PIC32_RTCALRM_CHIME	BIT(14)
+#define PIC32_RTCALRM_PIV	BIT(13)
+#define PIC32_RTCALRM_ALARMSYNC	BIT(12)
+#define PIC32_RTCALRM_AMASK	0x0F00
+#define PIC32_RTCALRM_ARPT	0xFF
+
+#define PIC32_RTCHOUR		0x23
+#define PIC32_RTCMIN		0x22
+#define PIC32_RTCSEC		0x21
+#define PIC32_RTCYEAR		0x33
+#define PIC32_RTCMON		0x32
+#define PIC32_RTCDAY		0x31
+
+#define PIC32_ALRMTIME		0x40
+#define PIC32_ALRMDATE		0x50
+
+#define PIC32_ALRMHOUR		0x43
+#define PIC32_ALRMMIN		0x42
+#define PIC32_ALRMSEC		0x41
+#define PIC32_ALRMYEAR		0x53
+#define PIC32_ALRMMON		0x52
+#define PIC32_ALRMDAY		0x51
+
+struct pic32_rtc_dev {
+	struct rtc_device	*rtc;
+	void __iomem		*reg_base;
+	struct clk		*clk;
+	spinlock_t		alarm_lock;
+	int			alarm_irq;
+	bool			alarm_clk_enabled;
+};
+
+static void pic32_rtc_alarm_clk_enable(struct pic32_rtc_dev *pdata,
+				       bool enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->alarm_lock, flags);
+	if (enable) {
+		if (!pdata->alarm_clk_enabled) {
+			clk_enable(pdata->clk);
+			pdata->alarm_clk_enabled = true;
+		}
+	} else {
+		if (pdata->alarm_clk_enabled) {
+			clk_disable(pdata->clk);
+			pdata->alarm_clk_enabled = false;
+		}
+	}
+	spin_unlock_irqrestore(&pdata->alarm_lock, flags);
+}
+
+static irqreturn_t pic32_rtc_alarmirq(int irq, void *id)
+{
+	struct pic32_rtc_dev *pdata = (struct pic32_rtc_dev *)id;
+
+	clk_enable(pdata->clk);
+	rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
+	clk_disable(pdata->clk);
+
+	pic32_rtc_alarm_clk_enable(pdata, false);
+
+	return IRQ_HANDLED;
+}
+
+static int pic32_rtc_setaie(struct device *dev, unsigned int enabled)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	void __iomem *base = pdata->reg_base;
+
+	clk_enable(pdata->clk);
+
+	writel(PIC32_RTCALRM_ALRMEN,
+	       base + (enabled ? PIC32_SET(PIC32_RTCALRM) :
+		       PIC32_CLR(PIC32_RTCALRM)));
+
+	clk_disable(pdata->clk);
+
+	pic32_rtc_alarm_clk_enable(pdata, enabled);
+
+	return 0;
+}
+
+static int pic32_rtc_setfreq(struct device *dev, int freq)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	void __iomem *base = pdata->reg_base;
+
+	clk_enable(pdata->clk);
+
+	writel(PIC32_RTCALRM_AMASK, base + PIC32_CLR(PIC32_RTCALRM));
+	writel(freq << 8, base + PIC32_SET(PIC32_RTCALRM));
+	writel(PIC32_RTCALRM_CHIME, base + PIC32_SET(PIC32_RTCALRM));
+
+	clk_disable(pdata->clk);
+
+	return 0;
+}
+
+static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	void __iomem *base = pdata->reg_base;
+	unsigned int tries = 0;
+
+	clk_enable(pdata->clk);
+
+	do {
+		rtc_tm->tm_hour = readb(base + PIC32_RTCHOUR);
+		rtc_tm->tm_min = readb(base + PIC32_RTCMIN);
+		rtc_tm->tm_mon  = readb(base + PIC32_RTCMON);
+		rtc_tm->tm_mday = readb(base + PIC32_RTCDAY);
+		rtc_tm->tm_year = readb(base + PIC32_RTCYEAR);
+		rtc_tm->tm_sec  = readb(base + PIC32_RTCSEC);
+
+		/*
+		 * The only way to work out whether the system was mid-update
+		 * when we read it is to check the second counter, and if it
+		 * is zero, then we re-try the entire read.
+		 */
+		tries += 1;
+	} while (rtc_tm->tm_sec == 0 && tries < 2);
+
+	rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+	rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+	rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+	rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+	rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon) - 1;
+	rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+
+	rtc_tm->tm_year += 100;
+
+	dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
+		1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+		rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+	clk_disable(pdata->clk);
+	return rtc_valid_tm(rtc_tm);
+}
+
+static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	void __iomem *base = pdata->reg_base;
+	int year = tm->tm_year - 100;
+
+	dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	if (year < 0 || year >= 100) {
+		dev_err(dev, "rtc only supports 100 years\n");
+		return -EINVAL;
+	}
+
+	clk_enable(pdata->clk);
+	writeb(bin2bcd(tm->tm_sec),  base + PIC32_RTCSEC);
+	writeb(bin2bcd(tm->tm_min),  base + PIC32_RTCMIN);
+	writeb(bin2bcd(tm->tm_hour), base + PIC32_RTCHOUR);
+	writeb(bin2bcd(tm->tm_mday), base + PIC32_RTCDAY);
+	writeb(bin2bcd(tm->tm_mon + 1), base + PIC32_RTCMON);
+	writeb(bin2bcd(year), base + PIC32_RTCYEAR);
+	clk_disable(pdata->clk);
+
+	return 0;
+}
+
+static int pic32_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	struct rtc_time *alm_tm = &alrm->time;
+	void __iomem *base = pdata->reg_base;
+	unsigned int alm_en;
+
+	clk_enable(pdata->clk);
+	alm_tm->tm_sec  = readb(base + PIC32_ALRMSEC);
+	alm_tm->tm_min  = readb(base + PIC32_ALRMMIN);
+	alm_tm->tm_hour = readb(base + PIC32_ALRMHOUR);
+	alm_tm->tm_mon  = readb(base + PIC32_ALRMMON);
+	alm_tm->tm_mday = readb(base + PIC32_ALRMDAY);
+	alm_tm->tm_year = readb(base + PIC32_ALRMYEAR);
+
+	alm_en = readb(base + PIC32_RTCALRM);
+
+	alrm->enabled = (alm_en & PIC32_RTCALRM_ALRMEN) ? 1 : 0;
+
+	dev_dbg(dev, "getalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
+		alm_en,
+		1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+		alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+	alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
+	alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+	alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
+	alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
+	alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon) - 1;
+	alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
+
+	clk_disable(pdata->clk);
+	return 0;
+}
+
+static int pic32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alrm->time;
+	void __iomem *base = pdata->reg_base;
+
+	clk_enable(pdata->clk);
+	dev_dbg(dev, "setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
+		alrm->enabled,
+		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	writel(0x00, base + PIC32_ALRMTIME);
+	writel(0x00, base + PIC32_ALRMDATE);
+
+	pic32_rtc_setaie(dev, alrm->enabled);
+
+	clk_disable(pdata->clk);
+	return 0;
+}
+
+static int pic32_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+	void __iomem *base = pdata->reg_base;
+	unsigned int repeat;
+
+	clk_enable(pdata->clk);
+
+	repeat = readw(base + PIC32_RTCALRM);
+	repeat &= PIC32_RTCALRM_ARPT;
+	seq_printf(seq, "periodic_IRQ\t: %s\n", repeat  ? "yes" : "no");
+
+	clk_disable(pdata->clk);
+	return 0;
+}
+
+static const struct rtc_class_ops pic32_rtcops = {
+	.read_time	  = pic32_rtc_gettime,
+	.set_time	  = pic32_rtc_settime,
+	.read_alarm	  = pic32_rtc_getalarm,
+	.set_alarm	  = pic32_rtc_setalarm,
+	.proc		  = pic32_rtc_proc,
+	.alarm_irq_enable = pic32_rtc_setaie,
+};
+
+static void pic32_rtc_enable(struct pic32_rtc_dev *pdata, int en)
+{
+	void __iomem *base = pdata->reg_base;
+
+	if (!base)
+		return;
+
+	clk_enable(pdata->clk);
+	if (!en) {
+		writel(PIC32_RTCCON_ON, base + PIC32_CLR(PIC32_RTCCON));
+	} else {
+		pic32_syskey_unlock();
+
+		writel(PIC32_RTCCON_RTCWREN, base + PIC32_SET(PIC32_RTCCON));
+		writel(3 << 9, base + PIC32_CLR(PIC32_RTCCON));
+
+		if (!(readl(base + PIC32_RTCCON) & PIC32_RTCCON_ON))
+			writel(PIC32_RTCCON_ON, base + PIC32_SET(PIC32_RTCCON));
+	}
+	clk_disable(pdata->clk);
+}
+
+static int pic32_rtc_remove(struct platform_device *pdev)
+{
+	struct pic32_rtc_dev *pdata = platform_get_drvdata(pdev);
+
+	pic32_rtc_setaie(&pdev->dev, 0);
+	clk_unprepare(pdata->clk);
+	pdata->clk = NULL;
+
+	return 0;
+}
+
+static int pic32_rtc_probe(struct platform_device *pdev)
+{
+	struct pic32_rtc_dev *pdata;
+	struct resource *res;
+	int ret;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, pdata);
+
+	pdata->alarm_irq = platform_get_irq(pdev, 0);
+	if (pdata->alarm_irq < 0) {
+		dev_err(&pdev->dev, "no irq for alarm\n");
+		return pdata->alarm_irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pdata->reg_base))
+		return PTR_ERR(pdata->reg_base);
+
+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pdata->clk)) {
+		dev_err(&pdev->dev, "failed to find rtc clock source\n");
+		ret = PTR_ERR(pdata->clk);
+		pdata->clk = NULL;
+		return ret;
+	}
+
+	spin_lock_init(&pdata->alarm_lock);
+
+	clk_prepare_enable(pdata->clk);
+
+	pic32_rtc_enable(pdata, 1);
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+						 &pic32_rtcops,
+						 THIS_MODULE);
+	if (IS_ERR(pdata->rtc)) {
+		ret = PTR_ERR(pdata->rtc);
+		goto err_nortc;
+	}
+
+	pdata->rtc->max_user_freq = 128;
+
+	pic32_rtc_setfreq(&pdev->dev, 1);
+	ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
+			       pic32_rtc_alarmirq, 0,
+			       dev_name(&pdev->dev), pdata);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"IRQ %d error %d\n", pdata->alarm_irq, ret);
+		goto err_nortc;
+	}
+
+	clk_disable(pdata->clk);
+
+	return 0;
+
+err_nortc:
+	pic32_rtc_enable(pdata, 0);
+	clk_disable_unprepare(pdata->clk);
+
+	return ret;
+}
+
+static const struct of_device_id pic32_rtc_dt_ids[] = {
+	{ .compatible = "microchip,pic32mzda-rtc" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids);
+
+static struct platform_driver pic32_rtc_driver = {
+	.probe		= pic32_rtc_probe,
+	.remove		= pic32_rtc_remove,
+	.driver		= {
+		.name	= "pic32-rtc",
+		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(pic32_rtc_dt_ids),
+	},
+};
+module_platform_driver(pic32_rtc_driver);
+
+MODULE_DESCRIPTION("Microchip PIC32 RTC Driver");
+MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
+MODULE_LICENSE("GPL");

+ 556 - 167
drivers/rtc/rtc-rv3029c2.c

@@ -1,7 +1,8 @@
 /*
- * Micro Crystal RV-3029C2 rtc class driver
+ * Micro Crystal RV-3029 rtc class driver
  *
  * Author: Gregory Hermant <gregory.hermant@calao-systems.com>
+ *         Michael Buesch <m@bues.ch>
  *
  * based on previously existing rtc class drivers
  *
@@ -9,89 +10,120 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * NOTE: Currently this driver only supports the bare minimum for read
- * and write the RTC and alarms. The extra features provided by this chip
- * (trickle charger, eeprom, T° compensation) are unavailable.
  */
 
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
 
 /* Register map */
 /* control section */
-#define RV3029C2_ONOFF_CTRL		0x00
-#define RV3029C2_IRQ_CTRL		0x01
-#define RV3029C2_IRQ_CTRL_AIE		(1 << 0)
-#define RV3029C2_IRQ_FLAGS		0x02
-#define RV3029C2_IRQ_FLAGS_AF		(1 << 0)
-#define RV3029C2_STATUS			0x03
-#define RV3029C2_STATUS_VLOW1		(1 << 2)
-#define RV3029C2_STATUS_VLOW2		(1 << 3)
-#define RV3029C2_STATUS_SR		(1 << 4)
-#define RV3029C2_STATUS_PON		(1 << 5)
-#define RV3029C2_STATUS_EEBUSY		(1 << 7)
-#define RV3029C2_RST_CTRL		0x04
-#define RV3029C2_CONTROL_SECTION_LEN	0x05
+#define RV3029_ONOFF_CTRL		0x00
+#define RV3029_ONOFF_CTRL_WE		BIT(0)
+#define RV3029_ONOFF_CTRL_TE		BIT(1)
+#define RV3029_ONOFF_CTRL_TAR		BIT(2)
+#define RV3029_ONOFF_CTRL_EERE		BIT(3)
+#define RV3029_ONOFF_CTRL_SRON		BIT(4)
+#define RV3029_ONOFF_CTRL_TD0		BIT(5)
+#define RV3029_ONOFF_CTRL_TD1		BIT(6)
+#define RV3029_ONOFF_CTRL_CLKINT	BIT(7)
+#define RV3029_IRQ_CTRL			0x01
+#define RV3029_IRQ_CTRL_AIE		BIT(0)
+#define RV3029_IRQ_CTRL_TIE		BIT(1)
+#define RV3029_IRQ_CTRL_V1IE		BIT(2)
+#define RV3029_IRQ_CTRL_V2IE		BIT(3)
+#define RV3029_IRQ_CTRL_SRIE		BIT(4)
+#define RV3029_IRQ_FLAGS		0x02
+#define RV3029_IRQ_FLAGS_AF		BIT(0)
+#define RV3029_IRQ_FLAGS_TF		BIT(1)
+#define RV3029_IRQ_FLAGS_V1IF		BIT(2)
+#define RV3029_IRQ_FLAGS_V2IF		BIT(3)
+#define RV3029_IRQ_FLAGS_SRF		BIT(4)
+#define RV3029_STATUS			0x03
+#define RV3029_STATUS_VLOW1		BIT(2)
+#define RV3029_STATUS_VLOW2		BIT(3)
+#define RV3029_STATUS_SR		BIT(4)
+#define RV3029_STATUS_PON		BIT(5)
+#define RV3029_STATUS_EEBUSY		BIT(7)
+#define RV3029_RST_CTRL			0x04
+#define RV3029_RST_CTRL_SYSR		BIT(4)
+#define RV3029_CONTROL_SECTION_LEN	0x05
 
 /* watch section */
-#define RV3029C2_W_SEC			0x08
-#define RV3029C2_W_MINUTES		0x09
-#define RV3029C2_W_HOURS		0x0A
-#define RV3029C2_REG_HR_12_24		(1<<6)  /* 24h/12h mode */
-#define RV3029C2_REG_HR_PM		(1<<5)  /* PM/AM bit in 12h mode */
-#define RV3029C2_W_DATE			0x0B
-#define RV3029C2_W_DAYS			0x0C
-#define RV3029C2_W_MONTHS		0x0D
-#define RV3029C2_W_YEARS		0x0E
-#define RV3029C2_WATCH_SECTION_LEN	0x07
+#define RV3029_W_SEC			0x08
+#define RV3029_W_MINUTES		0x09
+#define RV3029_W_HOURS			0x0A
+#define RV3029_REG_HR_12_24		BIT(6) /* 24h/12h mode */
+#define RV3029_REG_HR_PM		BIT(5) /* PM/AM bit in 12h mode */
+#define RV3029_W_DATE			0x0B
+#define RV3029_W_DAYS			0x0C
+#define RV3029_W_MONTHS			0x0D
+#define RV3029_W_YEARS			0x0E
+#define RV3029_WATCH_SECTION_LEN	0x07
 
 /* alarm section */
-#define RV3029C2_A_SC			0x10
-#define RV3029C2_A_MN			0x11
-#define RV3029C2_A_HR			0x12
-#define RV3029C2_A_DT			0x13
-#define RV3029C2_A_DW			0x14
-#define RV3029C2_A_MO			0x15
-#define RV3029C2_A_YR			0x16
-#define RV3029C2_ALARM_SECTION_LEN	0x07
+#define RV3029_A_SC			0x10
+#define RV3029_A_MN			0x11
+#define RV3029_A_HR			0x12
+#define RV3029_A_DT			0x13
+#define RV3029_A_DW			0x14
+#define RV3029_A_MO			0x15
+#define RV3029_A_YR			0x16
+#define RV3029_ALARM_SECTION_LEN	0x07
 
 /* timer section */
-#define RV3029C2_TIMER_LOW		0x18
-#define RV3029C2_TIMER_HIGH		0x19
+#define RV3029_TIMER_LOW		0x18
+#define RV3029_TIMER_HIGH		0x19
 
 /* temperature section */
-#define RV3029C2_TEMP_PAGE		0x20
+#define RV3029_TEMP_PAGE		0x20
 
 /* eeprom data section */
-#define RV3029C2_E2P_EEDATA1		0x28
-#define RV3029C2_E2P_EEDATA2		0x29
+#define RV3029_E2P_EEDATA1		0x28
+#define RV3029_E2P_EEDATA2		0x29
+#define RV3029_E2PDATA_SECTION_LEN	0x02
 
 /* eeprom control section */
-#define RV3029C2_CONTROL_E2P_EECTRL	0x30
-#define RV3029C2_TRICKLE_1K		(1<<0)  /*  1K resistance */
-#define RV3029C2_TRICKLE_5K		(1<<1)  /*  5K resistance */
-#define RV3029C2_TRICKLE_20K		(1<<2)  /* 20K resistance */
-#define RV3029C2_TRICKLE_80K		(1<<3)  /* 80K resistance */
-#define RV3029C2_CONTROL_E2P_XTALOFFSET	0x31
-#define RV3029C2_CONTROL_E2P_QCOEF	0x32
-#define RV3029C2_CONTROL_E2P_TURNOVER	0x33
+#define RV3029_CONTROL_E2P_EECTRL	0x30
+#define RV3029_EECTRL_THP		BIT(0) /* temp scan interval */
+#define RV3029_EECTRL_THE		BIT(1) /* thermometer enable */
+#define RV3029_EECTRL_FD0		BIT(2) /* CLKOUT */
+#define RV3029_EECTRL_FD1		BIT(3) /* CLKOUT */
+#define RV3029_TRICKLE_1K		BIT(4) /* 1.5K resistance */
+#define RV3029_TRICKLE_5K		BIT(5) /* 5K   resistance */
+#define RV3029_TRICKLE_20K		BIT(6) /* 20K  resistance */
+#define RV3029_TRICKLE_80K		BIT(7) /* 80K  resistance */
+#define RV3029_TRICKLE_MASK		(RV3029_TRICKLE_1K |\
+					 RV3029_TRICKLE_5K |\
+					 RV3029_TRICKLE_20K |\
+					 RV3029_TRICKLE_80K)
+#define RV3029_TRICKLE_SHIFT		4
+#define RV3029_CONTROL_E2P_XOFFS	0x31 /* XTAL offset */
+#define RV3029_CONTROL_E2P_XOFFS_SIGN	BIT(7) /* Sign: 1->pos, 0->neg */
+#define RV3029_CONTROL_E2P_QCOEF	0x32 /* XTAL temp drift coef */
+#define RV3029_CONTROL_E2P_TURNOVER	0x33 /* XTAL turnover temp (in *C) */
+#define RV3029_CONTROL_E2P_TOV_MASK	0x3F /* XTAL turnover temp mask */
 
 /* user ram section */
-#define RV3029C2_USR1_RAM_PAGE		0x38
-#define RV3029C2_USR1_SECTION_LEN	0x04
-#define RV3029C2_USR2_RAM_PAGE		0x3C
-#define RV3029C2_USR2_SECTION_LEN	0x04
+#define RV3029_USR1_RAM_PAGE		0x38
+#define RV3029_USR1_SECTION_LEN		0x04
+#define RV3029_USR2_RAM_PAGE		0x3C
+#define RV3029_USR2_SECTION_LEN		0x04
 
 static int
-rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
-	unsigned len)
+rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+		     unsigned len)
 {
 	int ret;
 
-	if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
-		(reg + len > RV3029C2_USR1_RAM_PAGE + 8))
+	if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
+		(reg + len > RV3029_USR1_RAM_PAGE + 8))
 		return -EINVAL;
 
 	ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -103,20 +135,38 @@ rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
 }
 
 static int
-rv3029c2_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
-			unsigned len)
+rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+		      unsigned len)
 {
-	if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
-		(reg + len > RV3029C2_USR1_RAM_PAGE + 8))
+	if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
+		(reg + len > RV3029_USR1_RAM_PAGE + 8))
 		return -EINVAL;
 
 	return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
 }
 
 static int
-rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf)
+rv3029_i2c_update_bits(struct i2c_client *client, u8 reg, u8 mask, u8 set)
+{
+	u8 buf;
+	int ret;
+
+	ret = rv3029_i2c_read_regs(client, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+	buf &= ~mask;
+	buf |= set & mask;
+	ret = rv3029_i2c_write_regs(client, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int
+rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
 {
-	int ret = rv3029c2_i2c_read_regs(client, RV3029C2_STATUS, buf, 1);
+	int ret = rv3029_i2c_read_regs(client, RV3029_STATUS, buf, 1);
 
 	if (ret < 0)
 		return -EIO;
@@ -125,83 +175,224 @@ rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf)
 }
 
 static int
-rv3029c2_i2c_set_sr(struct i2c_client *client, u8 val)
+rv3029_i2c_set_sr(struct i2c_client *client, u8 val)
 {
 	u8 buf[1];
 	int sr;
 
 	buf[0] = val;
-	sr = rv3029c2_i2c_write_regs(client, RV3029C2_STATUS, buf, 1);
+	sr = rv3029_i2c_write_regs(client, RV3029_STATUS, buf, 1);
 	dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
 	if (sr < 0)
 		return -EIO;
 	return 0;
 }
 
+static int rv3029_eeprom_busywait(struct i2c_client *client)
+{
+	int i, ret;
+	u8 sr;
+
+	for (i = 100; i > 0; i--) {
+		ret = rv3029_i2c_get_sr(client, &sr);
+		if (ret < 0)
+			break;
+		if (!(sr & RV3029_STATUS_EEBUSY))
+			break;
+		usleep_range(1000, 10000);
+	}
+	if (i <= 0) {
+		dev_err(&client->dev, "EEPROM busy wait timeout.\n");
+		return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int rv3029_eeprom_exit(struct i2c_client *client)
+{
+	/* Re-enable eeprom refresh */
+	return rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
+				      RV3029_ONOFF_CTRL_EERE,
+				      RV3029_ONOFF_CTRL_EERE);
+}
+
+static int rv3029_eeprom_enter(struct i2c_client *client)
+{
+	int ret;
+	u8 sr;
+
+	/* Check whether we are in the allowed voltage range. */
+	ret = rv3029_i2c_get_sr(client, &sr);
+	if (ret < 0)
+		return ret;
+	if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+		/* We clear the bits and retry once just in case
+		 * we had a brown out in early startup.
+		 */
+		sr &= ~RV3029_STATUS_VLOW1;
+		sr &= ~RV3029_STATUS_VLOW2;
+		ret = rv3029_i2c_set_sr(client, sr);
+		if (ret < 0)
+			return ret;
+		usleep_range(1000, 10000);
+		ret = rv3029_i2c_get_sr(client, &sr);
+		if (ret < 0)
+			return ret;
+		if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+			dev_err(&client->dev,
+				"Supply voltage is too low to safely access the EEPROM.\n");
+			return -ENODEV;
+		}
+	}
+
+	/* Disable eeprom refresh. */
+	ret = rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
+				     RV3029_ONOFF_CTRL_EERE, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for any previous eeprom accesses to finish. */
+	ret = rv3029_eeprom_busywait(client);
+	if (ret < 0)
+		rv3029_eeprom_exit(client);
+
+	return ret;
+}
+
+static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
+			      u8 buf[], size_t len)
+{
+	int ret, err;
+
+	err = rv3029_eeprom_enter(client);
+	if (err < 0)
+		return err;
+
+	ret = rv3029_i2c_read_regs(client, reg, buf, len);
+
+	err = rv3029_eeprom_exit(client);
+	if (err < 0)
+		return err;
+
+	return ret;
+}
+
+static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
+			       u8 const buf[], size_t len)
+{
+	int ret, err;
+	size_t i;
+	u8 tmp;
+
+	err = rv3029_eeprom_enter(client);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < len; i++, reg++) {
+		ret = rv3029_i2c_read_regs(client, reg, &tmp, 1);
+		if (ret < 0)
+			break;
+		if (tmp != buf[i]) {
+			ret = rv3029_i2c_write_regs(client, reg, &buf[i], 1);
+			if (ret < 0)
+				break;
+		}
+		ret = rv3029_eeprom_busywait(client);
+		if (ret < 0)
+			break;
+	}
+
+	err = rv3029_eeprom_exit(client);
+	if (err < 0)
+		return err;
+
+	return ret;
+}
+
+static int rv3029_eeprom_update_bits(struct i2c_client *client,
+				     u8 reg, u8 mask, u8 set)
+{
+	u8 buf;
+	int ret;
+
+	ret = rv3029_eeprom_read(client, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+	buf &= ~mask;
+	buf |= set & mask;
+	ret = rv3029_eeprom_write(client, reg, &buf, 1);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int
-rv3029c2_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 {
 	u8 buf[1];
 	int ret;
-	u8 regs[RV3029C2_WATCH_SECTION_LEN] = { 0, };
+	u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };
 
-	ret = rv3029c2_i2c_get_sr(client, buf);
+	ret = rv3029_i2c_get_sr(client, buf);
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return -EIO;
 	}
 
-	ret = rv3029c2_i2c_read_regs(client, RV3029C2_W_SEC , regs,
-					RV3029C2_WATCH_SECTION_LEN);
+	ret = rv3029_i2c_read_regs(client, RV3029_W_SEC, regs,
+				   RV3029_WATCH_SECTION_LEN);
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading RTC section failed\n",
 			__func__);
 		return ret;
 	}
 
-	tm->tm_sec = bcd2bin(regs[RV3029C2_W_SEC-RV3029C2_W_SEC]);
-	tm->tm_min = bcd2bin(regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC]);
+	tm->tm_sec = bcd2bin(regs[RV3029_W_SEC-RV3029_W_SEC]);
+	tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES-RV3029_W_SEC]);
 
 	/* HR field has a more complex interpretation */
 	{
-		const u8 _hr = regs[RV3029C2_W_HOURS-RV3029C2_W_SEC];
-		if (_hr & RV3029C2_REG_HR_12_24) {
+		const u8 _hr = regs[RV3029_W_HOURS-RV3029_W_SEC];
+
+		if (_hr & RV3029_REG_HR_12_24) {
 			/* 12h format */
 			tm->tm_hour = bcd2bin(_hr & 0x1f);
-			if (_hr & RV3029C2_REG_HR_PM)	/* PM flag set */
+			if (_hr & RV3029_REG_HR_PM)	/* PM flag set */
 				tm->tm_hour += 12;
 		} else /* 24h format */
 			tm->tm_hour = bcd2bin(_hr & 0x3f);
 	}
 
-	tm->tm_mday = bcd2bin(regs[RV3029C2_W_DATE-RV3029C2_W_SEC]);
-	tm->tm_mon = bcd2bin(regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC]) - 1;
-	tm->tm_year = bcd2bin(regs[RV3029C2_W_YEARS-RV3029C2_W_SEC]) + 100;
-	tm->tm_wday = bcd2bin(regs[RV3029C2_W_DAYS-RV3029C2_W_SEC]) - 1;
+	tm->tm_mday = bcd2bin(regs[RV3029_W_DATE-RV3029_W_SEC]);
+	tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS-RV3029_W_SEC]) - 1;
+	tm->tm_year = bcd2bin(regs[RV3029_W_YEARS-RV3029_W_SEC]) + 100;
+	tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS-RV3029_W_SEC]) - 1;
 
 	return 0;
 }
 
-static int rv3029c2_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	return rv3029c2_i2c_read_time(to_i2c_client(dev), tm);
+	return rv3029_i2c_read_time(to_i2c_client(dev), tm);
 }
 
 static int
-rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 {
 	struct rtc_time *const tm = &alarm->time;
 	int ret;
 	u8 regs[8];
 
-	ret = rv3029c2_i2c_get_sr(client, regs);
+	ret = rv3029_i2c_get_sr(client, regs);
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return -EIO;
 	}
 
-	ret = rv3029c2_i2c_read_regs(client, RV3029C2_A_SC, regs,
-					RV3029C2_ALARM_SECTION_LEN);
+	ret = rv3029_i2c_read_regs(client, RV3029_A_SC, regs,
+				   RV3029_ALARM_SECTION_LEN);
 
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading alarm section failed\n",
@@ -209,51 +400,42 @@ rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 		return ret;
 	}
 
-	tm->tm_sec = bcd2bin(regs[RV3029C2_A_SC-RV3029C2_A_SC] & 0x7f);
-	tm->tm_min = bcd2bin(regs[RV3029C2_A_MN-RV3029C2_A_SC] & 0x7f);
-	tm->tm_hour = bcd2bin(regs[RV3029C2_A_HR-RV3029C2_A_SC] & 0x3f);
-	tm->tm_mday = bcd2bin(regs[RV3029C2_A_DT-RV3029C2_A_SC] & 0x3f);
-	tm->tm_mon = bcd2bin(regs[RV3029C2_A_MO-RV3029C2_A_SC] & 0x1f) - 1;
-	tm->tm_year = bcd2bin(regs[RV3029C2_A_YR-RV3029C2_A_SC] & 0x7f) + 100;
-	tm->tm_wday = bcd2bin(regs[RV3029C2_A_DW-RV3029C2_A_SC] & 0x07) - 1;
+	tm->tm_sec = bcd2bin(regs[RV3029_A_SC-RV3029_A_SC] & 0x7f);
+	tm->tm_min = bcd2bin(regs[RV3029_A_MN-RV3029_A_SC] & 0x7f);
+	tm->tm_hour = bcd2bin(regs[RV3029_A_HR-RV3029_A_SC] & 0x3f);
+	tm->tm_mday = bcd2bin(regs[RV3029_A_DT-RV3029_A_SC] & 0x3f);
+	tm->tm_mon = bcd2bin(regs[RV3029_A_MO-RV3029_A_SC] & 0x1f) - 1;
+	tm->tm_year = bcd2bin(regs[RV3029_A_YR-RV3029_A_SC] & 0x7f) + 100;
+	tm->tm_wday = bcd2bin(regs[RV3029_A_DW-RV3029_A_SC] & 0x07) - 1;
 
 	return 0;
 }
 
 static int
-rv3029c2_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	return rv3029c2_i2c_read_alarm(to_i2c_client(dev), alarm);
+	return rv3029_i2c_read_alarm(to_i2c_client(dev), alarm);
 }
 
-static int rv3029c2_rtc_i2c_alarm_set_irq(struct i2c_client *client,
+static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
 					int enable)
 {
 	int ret;
-	u8 buf[1];
-
-	/* enable AIE irq */
-	ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_CTRL,	buf, 1);
-	if (ret < 0) {
-		dev_err(&client->dev, "can't read INT reg\n");
-		return ret;
-	}
-	if (enable)
-		buf[0] |= RV3029C2_IRQ_CTRL_AIE;
-	else
-		buf[0] &= ~RV3029C2_IRQ_CTRL_AIE;
 
-	ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_CTRL, buf, 1);
+	/* enable/disable AIE irq */
+	ret = rv3029_i2c_update_bits(client, RV3029_IRQ_CTRL,
+				     RV3029_IRQ_CTRL_AIE,
+				     (enable ? RV3029_IRQ_CTRL_AIE : 0));
 	if (ret < 0) {
-		dev_err(&client->dev, "can't set INT reg\n");
+		dev_err(&client->dev, "can't update INT reg\n");
 		return ret;
 	}
 
 	return 0;
 }
 
-static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
-					struct rtc_wkalrm *alarm)
+static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
+				    struct rtc_wkalrm *alarm)
 {
 	struct rtc_time *const tm = &alarm->time;
 	int ret;
@@ -267,50 +449,41 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
 	if (tm->tm_year < 100)
 		return -EINVAL;
 
-	ret = rv3029c2_i2c_get_sr(client, regs);
+	ret = rv3029_i2c_get_sr(client, regs);
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return -EIO;
 	}
-	regs[RV3029C2_A_SC-RV3029C2_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
-	regs[RV3029C2_A_MN-RV3029C2_A_SC] = bin2bcd(tm->tm_min & 0x7f);
-	regs[RV3029C2_A_HR-RV3029C2_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
-	regs[RV3029C2_A_DT-RV3029C2_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
-	regs[RV3029C2_A_MO-RV3029C2_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
-	regs[RV3029C2_A_DW-RV3029C2_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
-	regs[RV3029C2_A_YR-RV3029C2_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
-
-	ret = rv3029c2_i2c_write_regs(client, RV3029C2_A_SC, regs,
-					RV3029C2_ALARM_SECTION_LEN);
+	regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
+	regs[RV3029_A_MN-RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
+	regs[RV3029_A_HR-RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
+	regs[RV3029_A_DT-RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
+	regs[RV3029_A_MO-RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
+	regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
+	regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
+
+	ret = rv3029_i2c_write_regs(client, RV3029_A_SC, regs,
+				    RV3029_ALARM_SECTION_LEN);
 	if (ret < 0)
 		return ret;
 
 	if (alarm->enabled) {
-		u8 buf[1];
-
 		/* clear AF flag */
-		ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_FLAGS,
-						buf, 1);
-		if (ret < 0) {
-			dev_err(&client->dev, "can't read alarm flag\n");
-			return ret;
-		}
-		buf[0] &= ~RV3029C2_IRQ_FLAGS_AF;
-		ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_FLAGS,
-						buf, 1);
+		ret = rv3029_i2c_update_bits(client, RV3029_IRQ_FLAGS,
+					     RV3029_IRQ_FLAGS_AF, 0);
 		if (ret < 0) {
-			dev_err(&client->dev, "can't set alarm flag\n");
+			dev_err(&client->dev, "can't clear alarm flag\n");
 			return ret;
 		}
 		/* enable AIE irq */
-		ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1);
+		ret = rv3029_rtc_i2c_alarm_set_irq(client, 1);
 		if (ret)
 			return ret;
 
 		dev_dbg(&client->dev, "alarm IRQ armed\n");
 	} else {
 		/* disable AIE irq */
-		ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 0);
+		ret = rv3029_rtc_i2c_alarm_set_irq(client, 0);
 		if (ret)
 			return ret;
 
@@ -320,13 +493,13 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
 	return 0;
 }
 
-static int rv3029c2_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	return rv3029c2_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
+	return rv3029_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
 }
 
 static int
-rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 {
 	u8 regs[8];
 	int ret;
@@ -339,26 +512,26 @@ rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 	if (tm->tm_year < 100)
 		return -EINVAL;
 
-	regs[RV3029C2_W_SEC-RV3029C2_W_SEC] = bin2bcd(tm->tm_sec);
-	regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC] = bin2bcd(tm->tm_min);
-	regs[RV3029C2_W_HOURS-RV3029C2_W_SEC] = bin2bcd(tm->tm_hour);
-	regs[RV3029C2_W_DATE-RV3029C2_W_SEC] = bin2bcd(tm->tm_mday);
-	regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC] = bin2bcd(tm->tm_mon+1);
-	regs[RV3029C2_W_DAYS-RV3029C2_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
-	regs[RV3029C2_W_YEARS-RV3029C2_W_SEC] = bin2bcd(tm->tm_year - 100);
+	regs[RV3029_W_SEC-RV3029_W_SEC] = bin2bcd(tm->tm_sec);
+	regs[RV3029_W_MINUTES-RV3029_W_SEC] = bin2bcd(tm->tm_min);
+	regs[RV3029_W_HOURS-RV3029_W_SEC] = bin2bcd(tm->tm_hour);
+	regs[RV3029_W_DATE-RV3029_W_SEC] = bin2bcd(tm->tm_mday);
+	regs[RV3029_W_MONTHS-RV3029_W_SEC] = bin2bcd(tm->tm_mon+1);
+	regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
+	regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
 
-	ret = rv3029c2_i2c_write_regs(client, RV3029C2_W_SEC, regs,
-					RV3029C2_WATCH_SECTION_LEN);
+	ret = rv3029_i2c_write_regs(client, RV3029_W_SEC, regs,
+				    RV3029_WATCH_SECTION_LEN);
 	if (ret < 0)
 		return ret;
 
-	ret = rv3029c2_i2c_get_sr(client, regs);
+	ret = rv3029_i2c_get_sr(client, regs);
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return ret;
 	}
 	/* clear PON bit */
-	ret = rv3029c2_i2c_set_sr(client, (regs[0] & ~RV3029C2_STATUS_PON));
+	ret = rv3029_i2c_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
 	if (ret < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return ret;
@@ -367,26 +540,238 @@ rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 	return 0;
 }
 
-static int rv3029c2_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	return rv3029c2_i2c_set_time(to_i2c_client(dev), tm);
+	return rv3029_i2c_set_time(to_i2c_client(dev), tm);
 }
 
-static const struct rtc_class_ops rv3029c2_rtc_ops = {
-	.read_time	= rv3029c2_rtc_read_time,
-	.set_time	= rv3029c2_rtc_set_time,
-	.read_alarm	= rv3029c2_rtc_read_alarm,
-	.set_alarm	= rv3029c2_rtc_set_alarm,
+static const struct rv3029_trickle_tab_elem {
+	u32 r;		/* resistance in ohms */
+	u8 conf;	/* trickle config bits */
+} rv3029_trickle_tab[] = {
+	{
+		.r	= 1076,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+			  RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+	}, {
+		.r	= 1091,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+			  RV3029_TRICKLE_20K,
+	}, {
+		.r	= 1137,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+			  RV3029_TRICKLE_80K,
+	}, {
+		.r	= 1154,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
+	}, {
+		.r	= 1371,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
+			  RV3029_TRICKLE_80K,
+	}, {
+		.r	= 1395,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
+	}, {
+		.r	= 1472,
+		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
+	}, {
+		.r	= 1500,
+		.conf	= RV3029_TRICKLE_1K,
+	}, {
+		.r	= 3810,
+		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
+			  RV3029_TRICKLE_80K,
+	}, {
+		.r	= 4000,
+		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
+	}, {
+		.r	= 4706,
+		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
+	}, {
+		.r	= 5000,
+		.conf	= RV3029_TRICKLE_5K,
+	}, {
+		.r	= 16000,
+		.conf	= RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+	}, {
+		.r	= 20000,
+		.conf	= RV3029_TRICKLE_20K,
+	}, {
+		.r	= 80000,
+		.conf	= RV3029_TRICKLE_80K,
+	},
 };
 
-static struct i2c_device_id rv3029c2_id[] = {
+static void rv3029_trickle_config(struct i2c_client *client)
+{
+	struct device_node *of_node = client->dev.of_node;
+	const struct rv3029_trickle_tab_elem *elem;
+	int i, err;
+	u32 ohms;
+	u8 trickle_set_bits;
+
+	if (!of_node)
+		return;
+
+	/* Configure the trickle charger. */
+	err = of_property_read_u32(of_node, "trickle-resistor-ohms", &ohms);
+	if (err) {
+		/* Disable trickle charger. */
+		trickle_set_bits = 0;
+	} else {
+		/* Enable trickle charger. */
+		for (i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++) {
+			elem = &rv3029_trickle_tab[i];
+			if (elem->r >= ohms)
+				break;
+		}
+		trickle_set_bits = elem->conf;
+		dev_info(&client->dev,
+			 "Trickle charger enabled at %d ohms resistance.\n",
+			 elem->r);
+	}
+	err = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+					RV3029_TRICKLE_MASK,
+					trickle_set_bits);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"Failed to update trickle charger config\n");
+	}
+}
+
+#ifdef CONFIG_RTC_DRV_RV3029_HWMON
+
+static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
+{
+	int ret;
+	u8 temp;
+
+	ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+	if (ret < 0)
+		return ret;
+
+	*temp_mC = ((int)temp - 60) * 1000;
+
+	return 0;
+}
+
+static ssize_t rv3029_hwmon_show_temp(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct i2c_client *client = dev_get_drvdata(dev);
+	int ret, temp_mC;
+
+	ret = rv3029_read_temp(client, &temp_mC);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", temp_mC);
+}
+
+static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf,
+						size_t count)
+{
+	struct i2c_client *client = dev_get_drvdata(dev);
+	unsigned long interval_ms;
+	int ret;
+	u8 th_set_bits = 0;
+
+	ret = kstrtoul(buf, 10, &interval_ms);
+	if (ret < 0)
+		return ret;
+
+	if (interval_ms != 0) {
+		th_set_bits |= RV3029_EECTRL_THE;
+		if (interval_ms >= 16000)
+			th_set_bits |= RV3029_EECTRL_THP;
+	}
+	ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+					RV3029_EECTRL_THE | RV3029_EECTRL_THP,
+					th_set_bits);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
+						 struct device_attribute *attr,
+						 char *buf)
+{
+	struct i2c_client *client = dev_get_drvdata(dev);
+	int ret, interval_ms;
+	u8 eectrl;
+
+	ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL,
+				 &eectrl, 1);
+	if (ret < 0)
+		return ret;
+
+	if (eectrl & RV3029_EECTRL_THE) {
+		if (eectrl & RV3029_EECTRL_THP)
+			interval_ms = 16000;
+		else
+			interval_ms = 1000;
+	} else {
+		interval_ms = 0;
+	}
+
+	return sprintf(buf, "%d\n", interval_ms);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, rv3029_hwmon_show_temp,
+			  NULL, 0);
+static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
+			  rv3029_hwmon_show_update_interval,
+			  rv3029_hwmon_set_update_interval, 0);
+
+static struct attribute *rv3029_hwmon_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_update_interval.dev_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(rv3029_hwmon);
+
+static void rv3029_hwmon_register(struct i2c_client *client)
+{
+	struct device *hwmon_dev;
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(
+		&client->dev, client->name, client, rv3029_hwmon_groups);
+	if (IS_ERR(hwmon_dev)) {
+		dev_warn(&client->dev,
+			"unable to register hwmon device %ld\n",
+			PTR_ERR(hwmon_dev));
+	}
+}
+
+#else /* CONFIG_RTC_DRV_RV3029_HWMON */
+
+static void rv3029_hwmon_register(struct i2c_client *client)
+{
+}
+
+#endif /* CONFIG_RTC_DRV_RV3029_HWMON */
+
+static const struct rtc_class_ops rv3029_rtc_ops = {
+	.read_time	= rv3029_rtc_read_time,
+	.set_time	= rv3029_rtc_set_time,
+	.read_alarm	= rv3029_rtc_read_alarm,
+	.set_alarm	= rv3029_rtc_set_alarm,
+};
+
+static struct i2c_device_id rv3029_id[] = {
+	{ "rv3029", 0 },
 	{ "rv3029c2", 0 },
 	{ }
 };
-MODULE_DEVICE_TABLE(i2c, rv3029c2_id);
+MODULE_DEVICE_TABLE(i2c, rv3029_id);
 
-static int rv3029c2_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id)
+static int rv3029_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
 	struct rtc_device *rtc;
 	int rc = 0;
@@ -395,14 +780,17 @@ static int rv3029c2_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
 		return -ENODEV;
 
-	rc = rv3029c2_i2c_get_sr(client, buf);
+	rc = rv3029_i2c_get_sr(client, buf);
 	if (rc < 0) {
 		dev_err(&client->dev, "reading status failed\n");
 		return rc;
 	}
 
+	rv3029_trickle_config(client);
+	rv3029_hwmon_register(client);
+
 	rtc = devm_rtc_device_register(&client->dev, client->name,
-					&rv3029c2_rtc_ops, THIS_MODULE);
+				       &rv3029_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
@@ -412,16 +800,17 @@ static int rv3029c2_probe(struct i2c_client *client,
 	return 0;
 }
 
-static struct i2c_driver rv3029c2_driver = {
+static struct i2c_driver rv3029_driver = {
 	.driver = {
 		.name = "rtc-rv3029c2",
 	},
-	.probe = rv3029c2_probe,
-	.id_table = rv3029c2_id,
+	.probe		= rv3029_probe,
+	.id_table	= rv3029_id,
 };
 
-module_i2c_driver(rv3029c2_driver);
+module_i2c_driver(rv3029_driver);
 
 MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>");
-MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver");
+MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
+MODULE_DESCRIPTION("Micro Crystal RV3029 RTC driver");
 MODULE_LICENSE("GPL");

+ 18 - 21
drivers/rtc/rtc-rv8803.c

@@ -52,7 +52,7 @@
 struct rv8803_data {
 	struct i2c_client *client;
 	struct rtc_device *rtc;
-	spinlock_t flags_lock;
+	struct mutex flags_lock;
 	u8 ctrl;
 };
 
@@ -63,11 +63,11 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
 	unsigned long events = 0;
 	int flags;
 
-	spin_lock(&rv8803->flags_lock);
+	mutex_lock(&rv8803->flags_lock);
 
 	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
 	if (flags <= 0) {
-		spin_unlock(&rv8803->flags_lock);
+		mutex_unlock(&rv8803->flags_lock);
 		return IRQ_NONE;
 	}
 
@@ -102,7 +102,7 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
 					  rv8803->ctrl);
 	}
 
-	spin_unlock(&rv8803->flags_lock);
+	mutex_unlock(&rv8803->flags_lock);
 
 	return IRQ_HANDLED;
 }
@@ -155,7 +155,6 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
 	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
 	u8 date[7];
 	int flags, ret;
-	unsigned long irqflags;
 
 	if ((tm->tm_year < 100) || (tm->tm_year > 199))
 		return -EINVAL;
@@ -173,18 +172,18 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
 	if (ret < 0)
 		return ret;
 
-	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+	mutex_lock(&rv8803->flags_lock);
 
 	flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
 	if (flags < 0) {
-		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		mutex_unlock(&rv8803->flags_lock);
 		return flags;
 	}
 
 	ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
 					flags & ~RV8803_FLAG_V2F);
 
-	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+	mutex_unlock(&rv8803->flags_lock);
 
 	return ret;
 }
@@ -226,7 +225,6 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	u8 alarmvals[3];
 	u8 ctrl[2];
 	int ret, err;
-	unsigned long irqflags;
 
 	/* The alarm has no seconds, round up to nearest minute */
 	if (alrm->time.tm_sec) {
@@ -236,11 +234,11 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 		rtc_time64_to_tm(alarm_time, &alrm->time);
 	}
 
-	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+	mutex_lock(&rv8803->flags_lock);
 
 	ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
 	if (ret != 2) {
-		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		mutex_unlock(&rv8803->flags_lock);
 		return ret < 0 ? ret : -EIO;
 	}
 
@@ -253,14 +251,14 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 		err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
 						rv8803->ctrl);
 		if (err) {
-			spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+			mutex_unlock(&rv8803->flags_lock);
 			return err;
 		}
 	}
 
 	ctrl[1] &= ~RV8803_FLAG_AF;
 	err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
-	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+	mutex_unlock(&rv8803->flags_lock);
 	if (err)
 		return err;
 
@@ -289,7 +287,6 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
 	int ctrl, flags, err;
-	unsigned long irqflags;
 
 	ctrl = rv8803->ctrl;
 
@@ -305,15 +302,15 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
 			ctrl &= ~RV8803_CTRL_AIE;
 	}
 
-	spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+	mutex_lock(&rv8803->flags_lock);
 	flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
 	if (flags < 0) {
-		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		mutex_unlock(&rv8803->flags_lock);
 		return flags;
 	}
 	flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
 	err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
-	spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+	mutex_unlock(&rv8803->flags_lock);
 	if (err)
 		return err;
 
@@ -333,7 +330,6 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct rv8803_data *rv8803 = dev_get_drvdata(dev);
 	int flags, ret = 0;
-	unsigned long irqflags;
 
 	switch (cmd) {
 	case RTC_VL_READ:
@@ -355,16 +351,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 		return 0;
 
 	case RTC_VL_CLR:
-		spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+		mutex_lock(&rv8803->flags_lock);
 		flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
 		if (flags < 0) {
-			spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+			mutex_unlock(&rv8803->flags_lock);
 			return flags;
 		}
 
 		flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
 		ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
-		spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+		mutex_unlock(&rv8803->flags_lock);
 		if (ret < 0)
 			return ret;
 
@@ -441,6 +437,7 @@ static int rv8803_probe(struct i2c_client *client,
 	if (!rv8803)
 		return -ENOMEM;
 
+	mutex_init(&rv8803->flags_lock);
 	rv8803->client = client;
 	i2c_set_clientdata(client, rv8803);
 

+ 402 - 0
drivers/rtc/rtc-rx6110.c

@@ -0,0 +1,402 @@
+/*
+ * Driver for the Epson RTC module RX-6110 SA
+ *
+ * Copyright(C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ * Copyright(C) SEIKO EPSON CORPORATION 2013. All rights reserved.
+ *
+ * This driver software is distributed as is, without any warranty of any kind,
+ * either express or implied as further specified in the GNU Public License.
+ * This software may be used and distributed according to the terms of the GNU
+ * Public License, version 2 as published by the Free Software Foundation.
+ * See the file COPYING in the main directory of this archive for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+
+/* RX-6110 Register definitions */
+#define RX6110_REG_SEC		0x10
+#define RX6110_REG_MIN		0x11
+#define RX6110_REG_HOUR		0x12
+#define RX6110_REG_WDAY		0x13
+#define RX6110_REG_MDAY		0x14
+#define RX6110_REG_MONTH	0x15
+#define RX6110_REG_YEAR		0x16
+#define RX6110_REG_RES1		0x17
+#define RX6110_REG_ALMIN	0x18
+#define RX6110_REG_ALHOUR	0x19
+#define RX6110_REG_ALWDAY	0x1A
+#define RX6110_REG_TCOUNT0	0x1B
+#define RX6110_REG_TCOUNT1	0x1C
+#define RX6110_REG_EXT		0x1D
+#define RX6110_REG_FLAG		0x1E
+#define RX6110_REG_CTRL		0x1F
+#define RX6110_REG_USER0	0x20
+#define RX6110_REG_USER1	0x21
+#define RX6110_REG_USER2	0x22
+#define RX6110_REG_USER3	0x23
+#define RX6110_REG_USER4	0x24
+#define RX6110_REG_USER5	0x25
+#define RX6110_REG_USER6	0x26
+#define RX6110_REG_USER7	0x27
+#define RX6110_REG_USER8	0x28
+#define RX6110_REG_USER9	0x29
+#define RX6110_REG_USERA	0x2A
+#define RX6110_REG_USERB	0x2B
+#define RX6110_REG_USERC	0x2C
+#define RX6110_REG_USERD	0x2D
+#define RX6110_REG_USERE	0x2E
+#define RX6110_REG_USERF	0x2F
+#define RX6110_REG_RES2		0x30
+#define RX6110_REG_RES3		0x31
+#define RX6110_REG_IRQ		0x32
+
+#define RX6110_BIT_ALARM_EN		BIT(7)
+
+/* Extension Register (1Dh) bit positions */
+#define RX6110_BIT_EXT_TSEL0		BIT(0)
+#define RX6110_BIT_EXT_TSEL1		BIT(1)
+#define RX6110_BIT_EXT_TSEL2		BIT(2)
+#define RX6110_BIT_EXT_WADA		BIT(3)
+#define RX6110_BIT_EXT_TE		BIT(4)
+#define RX6110_BIT_EXT_USEL		BIT(5)
+#define RX6110_BIT_EXT_FSEL0		BIT(6)
+#define RX6110_BIT_EXT_FSEL1		BIT(7)
+
+/* Flag Register (1Eh) bit positions */
+#define RX6110_BIT_FLAG_VLF		BIT(1)
+#define RX6110_BIT_FLAG_AF		BIT(3)
+#define RX6110_BIT_FLAG_TF		BIT(4)
+#define RX6110_BIT_FLAG_UF		BIT(5)
+
+/* Control Register (1Fh) bit positions */
+#define RX6110_BIT_CTRL_TBKE		BIT(0)
+#define RX6110_BIT_CTRL_TBKON		BIT(1)
+#define RX6110_BIT_CTRL_TSTP		BIT(2)
+#define RX6110_BIT_CTRL_AIE		BIT(3)
+#define RX6110_BIT_CTRL_TIE		BIT(4)
+#define RX6110_BIT_CTRL_UIE		BIT(5)
+#define RX6110_BIT_CTRL_STOP		BIT(6)
+#define RX6110_BIT_CTRL_TEST		BIT(7)
+
+enum {
+	RTC_SEC = 0,
+	RTC_MIN,
+	RTC_HOUR,
+	RTC_WDAY,
+	RTC_MDAY,
+	RTC_MONTH,
+	RTC_YEAR,
+	RTC_NR_TIME
+};
+
+#define RX6110_DRIVER_NAME		"rx6110"
+
+struct rx6110_data {
+	struct rtc_device *rtc;
+	struct regmap *regmap;
+};
+
+/**
+ * rx6110_rtc_tm_to_data - convert rtc_time to native time encoding
+ *
+ * @tm: holds date and time
+ * @data: holds the encoding in rx6110 native form
+ */
+static int rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+	pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+		 tm->tm_sec, tm->tm_min, tm->tm_hour,
+		 tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+	/*
+	 * The year in the RTC is a value between 0 and 99.
+	 * Assume that this represents the current century
+	 * and disregard all other values.
+	 */
+	if (tm->tm_year < 100 || tm->tm_year >= 200)
+		return -EINVAL;
+
+	data[RTC_SEC] = bin2bcd(tm->tm_sec);
+	data[RTC_MIN] = bin2bcd(tm->tm_min);
+	data[RTC_HOUR] = bin2bcd(tm->tm_hour);
+	data[RTC_WDAY] = BIT(bin2bcd(tm->tm_wday));
+	data[RTC_MDAY] = bin2bcd(tm->tm_mday);
+	data[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
+	data[RTC_YEAR] = bin2bcd(tm->tm_year % 100);
+
+	return 0;
+}
+
+/**
+ * rx6110_data_to_rtc_tm - convert native time encoding to rtc_time
+ *
+ * @data: holds the encoding in rx6110 native form
+ * @tm: holds date and time
+ */
+static int rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
+{
+	tm->tm_sec = bcd2bin(data[RTC_SEC] & 0x7f);
+	tm->tm_min = bcd2bin(data[RTC_MIN] & 0x7f);
+	/* only 24-hour clock */
+	tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
+	tm->tm_wday = ffs(data[RTC_WDAY] & 0x7f);
+	tm->tm_mday = bcd2bin(data[RTC_MDAY] & 0x3f);
+	tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
+	tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
+
+	pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+		 tm->tm_sec, tm->tm_min, tm->tm_hour,
+		 tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+	/*
+	 * The year in the RTC is a value between 0 and 99.
+	 * Assume that this represents the current century
+	 * and disregard all other values.
+	 */
+	if (tm->tm_year < 100 || tm->tm_year >= 200)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * rx6110_set_time - set the current time in the rx6110 registers
+ *
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ *
+ * BUG: The HW assumes every year that is a multiple of 4 to be a leap
+ * year. Next time this is wrong is 2100, which will not be a leap year
+ *
+ * Note: If STOP is not set/cleared, the clock will start when the seconds
+ *       register is written
+ *
+ */
+static int rx6110_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+	u8 data[RTC_NR_TIME];
+	int ret;
+
+	ret = rx6110_rtc_tm_to_data(tm, data);
+	if (ret < 0)
+		return ret;
+
+	/* set STOP bit before changing clock/calendar */
+	ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+				 RX6110_BIT_CTRL_STOP, RX6110_BIT_CTRL_STOP);
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_write(rx6110->regmap, RX6110_REG_SEC, data,
+				RTC_NR_TIME);
+	if (ret)
+		return ret;
+
+	/* The time in the RTC is valid. Be sure to have VLF cleared. */
+	ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+				 RX6110_BIT_FLAG_VLF, 0);
+	if (ret)
+		return ret;
+
+	/* clear STOP bit after changing clock/calendar */
+	ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+				 RX6110_BIT_CTRL_STOP, 0);
+
+	return ret;
+}
+
+/**
+ * rx6110_get_time - get the current time from the rx6110 registers
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ */
+static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
+{
+	struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+	u8 data[RTC_NR_TIME];
+	int flags;
+	int ret;
+
+	ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+	if (ret)
+		return -EINVAL;
+
+	/* check for VLF Flag (set at power-on) */
+	if ((flags & RX6110_BIT_FLAG_VLF)) {
+		dev_warn(dev, "Voltage low, data is invalid.\n");
+		return -EINVAL;
+	}
+
+	/* read registers to date */
+	ret = regmap_bulk_read(rx6110->regmap, RX6110_REG_SEC, data,
+			       RTC_NR_TIME);
+	if (ret)
+		return ret;
+
+	ret = rx6110_data_to_rtc_tm(data, tm);
+	if (ret)
+		return ret;
+
+	dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+	return rtc_valid_tm(tm);
+}
+
+static const struct reg_sequence rx6110_default_regs[] = {
+	{ RX6110_REG_RES1,   0xB8 },
+	{ RX6110_REG_RES2,   0x00 },
+	{ RX6110_REG_RES3,   0x10 },
+	{ RX6110_REG_IRQ,    0x00 },
+	{ RX6110_REG_ALMIN,  0x00 },
+	{ RX6110_REG_ALHOUR, 0x00 },
+	{ RX6110_REG_ALWDAY, 0x00 },
+};
+
+/**
+ * rx6110_init - initialize the rx6110 registers
+ *
+ * @rx6110: pointer to the rx6110 struct in use
+ *
+ */
+static int rx6110_init(struct rx6110_data *rx6110)
+{
+	struct rtc_device *rtc = rx6110->rtc;
+	int flags;
+	int ret;
+
+	ret = regmap_update_bits(rx6110->regmap, RX6110_REG_EXT,
+				 RX6110_BIT_EXT_TE, 0);
+	if (ret)
+		return ret;
+
+	ret = regmap_register_patch(rx6110->regmap, rx6110_default_regs,
+				    ARRAY_SIZE(rx6110_default_regs));
+	if (ret)
+		return ret;
+
+	ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+	if (ret)
+		return ret;
+
+	/* check for VLF Flag (set at power-on) */
+	if ((flags & RX6110_BIT_FLAG_VLF))
+		dev_warn(&rtc->dev, "Voltage low, data loss detected.\n");
+
+	/* check for Alarm Flag */
+	if (flags & RX6110_BIT_FLAG_AF)
+		dev_warn(&rtc->dev, "An alarm may have been missed.\n");
+
+	/* check for Periodic Timer Flag */
+	if (flags & RX6110_BIT_FLAG_TF)
+		dev_warn(&rtc->dev, "Periodic timer was detected\n");
+
+	/* check for Update Timer Flag */
+	if (flags & RX6110_BIT_FLAG_UF)
+		dev_warn(&rtc->dev, "Update timer was detected\n");
+
+	/* clear all flags BUT VLF */
+	ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+				 RX6110_BIT_FLAG_AF |
+				 RX6110_BIT_FLAG_UF |
+				 RX6110_BIT_FLAG_TF,
+				 0);
+
+	return ret;
+}
+
+static struct rtc_class_ops rx6110_rtc_ops = {
+	.read_time = rx6110_get_time,
+	.set_time = rx6110_set_time,
+};
+
+static struct regmap_config regmap_spi_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = RX6110_REG_IRQ,
+	.read_flag_mask = 0x80,
+};
+
+/**
+ * rx6110_probe - initialize rtc driver
+ * @spi: pointer to spi device
+ */
+static int rx6110_probe(struct spi_device *spi)
+{
+	struct rx6110_data *rx6110;
+	int err;
+
+	if ((spi->bits_per_word && spi->bits_per_word != 8) ||
+	    (spi->max_speed_hz > 2000000) ||
+	    (spi->mode != (SPI_CS_HIGH | SPI_CPOL | SPI_CPHA))) {
+		dev_warn(&spi->dev, "SPI settings: bits_per_word: %d, max_speed_hz: %d, mode: %xh\n",
+			 spi->bits_per_word, spi->max_speed_hz, spi->mode);
+		dev_warn(&spi->dev, "driving device in an unsupported mode");
+	}
+
+	rx6110 = devm_kzalloc(&spi->dev, sizeof(*rx6110), GFP_KERNEL);
+	if (!rx6110)
+		return -ENOMEM;
+
+	rx6110->regmap = devm_regmap_init_spi(spi, &regmap_spi_config);
+	if (IS_ERR(rx6110->regmap)) {
+		dev_err(&spi->dev, "regmap init failed for rtc rx6110\n");
+		return PTR_ERR(rx6110->regmap);
+	}
+
+	spi_set_drvdata(spi, rx6110);
+
+	rx6110->rtc = devm_rtc_device_register(&spi->dev,
+					       RX6110_DRIVER_NAME,
+					       &rx6110_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(rx6110->rtc))
+		return PTR_ERR(rx6110->rtc);
+
+	err = rx6110_init(rx6110);
+	if (err)
+		return err;
+
+	rx6110->rtc->max_user_freq = 1;
+
+	return 0;
+}
+
+static int rx6110_remove(struct spi_device *spi)
+{
+	return 0;
+}
+
+static const struct spi_device_id rx6110_id[] = {
+	{ "rx6110", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, rx6110_id);
+
+static struct spi_driver rx6110_driver = {
+	.driver = {
+		.name = RX6110_DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe		= rx6110_probe,
+	.remove		= rx6110_remove,
+	.id_table	= rx6110_id,
+};
+
+module_spi_driver(rx6110_driver);
+
+MODULE_AUTHOR("Val Krutov <val.krutov@erd.epson.com>");
+MODULE_DESCRIPTION("RX-6110 SA RTC driver");
+MODULE_LICENSE("GPL");

+ 21 - 4
drivers/rtc/rtc-rx8025.c

@@ -65,7 +65,6 @@
 
 static const struct i2c_device_id rx8025_id[] = {
 	{ "rx8025", 0 },
-	{ "rv8803", 1 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, rx8025_id);
@@ -147,8 +146,10 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
 {
 	struct i2c_client *client = dev_id;
 	struct rx8025_data *rx8025 = i2c_get_clientdata(client);
+	struct mutex *lock = &rx8025->rtc->ops_lock;
 	int status;
 
+	mutex_lock(lock);
 	status = rx8025_read_reg(client, RX8025_REG_CTRL2);
 	if (status < 0)
 		goto out;
@@ -173,6 +174,8 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
 	}
 
 out:
+	mutex_unlock(lock);
+
 	return IRQ_HANDLED;
 }
 
@@ -341,7 +344,17 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 	if (client->irq <= 0)
 		return -EINVAL;
 
-	/* Hardware alarm precision is 1 minute! */
+	/*
+	 * Hardware alarm precision is 1 minute!
+	 * round up to nearest minute
+	 */
+	if (t->time.tm_sec) {
+		time64_t alarm_time = rtc_tm_to_time64(&t->time);
+
+		alarm_time += 60 - t->time.tm_sec;
+		rtc_time64_to_tm(alarm_time, &t->time);
+	}
+
 	ald[0] = bin2bcd(t->time.tm_min);
 	if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
 		ald[1] = bin2bcd(t->time.tm_hour);
@@ -539,8 +552,9 @@ static int rx8025_probe(struct i2c_client *client,
 	if (client->irq > 0) {
 		dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
 		err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-						rx8025_handle_irq, 0, "rx8025",
-						client);
+						rx8025_handle_irq,
+						IRQF_ONESHOT,
+						"rx8025", client);
 		if (err) {
 			dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
 			client->irq = 0;
@@ -549,6 +563,9 @@ static int rx8025_probe(struct i2c_client *client,
 
 	rx8025->rtc->max_user_freq = 1;
 
+	/* the rx8025 alarm only supports a minute accuracy */
+	rx8025->rtc->uie_unsupported = 1;
+
 	err = rx8025_sysfs_register(&client->dev);
 	return err;
 }

+ 4 - 4
drivers/rtc/rtc-s5m.c

@@ -216,7 +216,7 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
  * Read RTC_UDR_CON register and wait till UDR field is cleared.
  * This indicates that time/alarm update ended.
  */
-static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
+static int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
 {
 	int ret, retry = UDR_READ_RETRY_CNT;
 	unsigned int data;
@@ -231,7 +231,7 @@ static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
 	return ret;
 }
 
-static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
+static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
 		struct rtc_wkalrm *alarm)
 {
 	int ret;
@@ -264,7 +264,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
 	return 0;
 }
 
-static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
+static int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 {
 	int ret;
 	unsigned int data;
@@ -288,7 +288,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 	return ret;
 }
 
-static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
+static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 {
 	int ret;
 	unsigned int data;

+ 34 - 1
drivers/rtc/rtc-sysfs.c

@@ -218,6 +218,34 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RW(wakealarm);
 
+static ssize_t
+offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	ssize_t retval;
+	long offset;
+
+	retval = rtc_read_offset(to_rtc_device(dev), &offset);
+	if (retval == 0)
+		retval = sprintf(buf, "%ld\n", offset);
+
+	return retval;
+}
+
+static ssize_t
+offset_store(struct device *dev, struct device_attribute *attr,
+	     const char *buf, size_t n)
+{
+	ssize_t retval;
+	long offset;
+
+	retval = kstrtol(buf, 10, &offset);
+	if (retval == 0)
+		retval = rtc_set_offset(to_rtc_device(dev), offset);
+
+	return (retval < 0) ? retval : n;
+}
+static DEVICE_ATTR_RW(offset);
+
 static struct attribute *rtc_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_date.attr,
@@ -226,6 +254,7 @@ static struct attribute *rtc_attrs[] = {
 	&dev_attr_max_user_freq.attr,
 	&dev_attr_hctosys.attr,
 	&dev_attr_wakealarm.attr,
+	&dev_attr_offset.attr,
 	NULL,
 };
 
@@ -249,9 +278,13 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj,
 	struct rtc_device *rtc = to_rtc_device(dev);
 	umode_t mode = attr->mode;
 
-	if (attr == &dev_attr_wakealarm.attr)
+	if (attr == &dev_attr_wakealarm.attr) {
 		if (!rtc_does_wakealarm(rtc))
 			mode = 0;
+	} else if (attr == &dev_attr_offset.attr) {
+		if (!rtc->ops->set_offset)
+			mode = 0;
+	}
 
 	return mode;
 }

+ 1 - 1
drivers/rtc/rtc-tps6586x.c

@@ -286,7 +286,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
 
 	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
 				tps6586x_rtc_irq,
-				IRQF_ONESHOT | IRQF_EARLY_RESUME,
+				IRQF_ONESHOT,
 				dev_name(&pdev->dev), rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",

+ 1 - 1
drivers/rtc/rtc-tps65910.c

@@ -268,7 +268,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME,
+		tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
 		dev_name(&pdev->dev), &pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "IRQ is not free.\n");

+ 1 - 1
drivers/rtc/rtc-tps80031.c

@@ -287,7 +287,7 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
 
 	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
 			tps80031_rtc_irq,
-			IRQF_ONESHOT | IRQF_EARLY_RESUME,
+			IRQF_ONESHOT,
 			dev_name(&pdev->dev), rtc);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n",

+ 7 - 6
drivers/rtc/rtc-vr41xx.c

@@ -272,12 +272,13 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
 }
 
 static const struct rtc_class_ops vr41xx_rtc_ops = {
-	.release	= vr41xx_rtc_release,
-	.ioctl		= vr41xx_rtc_ioctl,
-	.read_time	= vr41xx_rtc_read_time,
-	.set_time	= vr41xx_rtc_set_time,
-	.read_alarm	= vr41xx_rtc_read_alarm,
-	.set_alarm	= vr41xx_rtc_set_alarm,
+	.release		= vr41xx_rtc_release,
+	.ioctl			= vr41xx_rtc_ioctl,
+	.read_time		= vr41xx_rtc_read_time,
+	.set_time		= vr41xx_rtc_set_time,
+	.read_alarm		= vr41xx_rtc_read_alarm,
+	.set_alarm		= vr41xx_rtc_set_alarm,
+	.alarm_irq_enable	= vr41xx_rtc_alarm_irq_enable,
 };
 
 static int rtc_probe(struct platform_device *pdev)

+ 0 - 3
include/linux/mfd/max77686-private.h

@@ -437,14 +437,11 @@ enum max77686_irq {
 struct max77686_dev {
 	struct device *dev;
 	struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
-	struct i2c_client *rtc; /* slave addr 0x0c */
 
 	unsigned long type;
 
 	struct regmap *regmap;		/* regmap for mfd */
-	struct regmap *rtc_regmap;	/* regmap for rtc */
 	struct regmap_irq_chip_data *irq_data;
-	struct regmap_irq_chip_data *rtc_irq_data;
 
 	int irq;
 	struct mutex irqlock;

+ 4 - 0
include/linux/rtc.h

@@ -89,6 +89,8 @@ struct rtc_class_ops {
 	int (*set_mmss)(struct device *, unsigned long secs);
 	int (*read_callback)(struct device *, int data);
 	int (*alarm_irq_enable)(struct device *, unsigned int enabled);
+	int (*read_offset)(struct device *, long *offset);
+	int (*set_offset)(struct device *, long offset);
 };
 
 #define RTC_DEVICE_NAME_SIZE 20
@@ -208,6 +210,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data);
 int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
 		    ktime_t expires, ktime_t period);
 void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer);
+int rtc_read_offset(struct rtc_device *rtc, long *offset);
+int rtc_set_offset(struct rtc_device *rtc, long offset);
 void rtc_timer_do_work(struct work_struct *work);
 
 static inline bool is_leap_year(unsigned int year)