[coreboot-gerrit] Change in coreboot[master]: rx6110sa: Add a software reset sequence in case of power loss

Werner Zeh (Code Review) gerrit at coreboot.org
Thu Jun 29 11:14:05 CEST 2017


Werner Zeh has uploaded this change for review. ( https://review.coreboot.org/20412


Change subject: rx6110sa: Add a software reset sequence in case of power loss
......................................................................

rx6110sa: Add a software reset sequence in case of power loss

According to the datasheet the RTC needs a power rising slope of no more
than 100µs/V to ensure a correct power-on reset. If the mainboard that
hosts the RTC cannot guarantee this, a software reset sequence is needed
in the case where the battery was drained completely.

As the rising slope of the power supply depends on so many parameters
and is highly mainboard specific, refactor the initialization code to
perform a software reset every time a power loss event is recognized by
the RTC.

Change-Id: If64d672e51667523058041bd00e1e50ac047143d
Signed-off-by: Werner Zeh <werner.zeh at siemens.com>
---
M src/drivers/i2c/rx6110sa/rx6110sa.c
M src/drivers/i2c/rx6110sa/rx6110sa.h
2 files changed, 61 insertions(+), 36 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/12/20412/1

diff --git a/src/drivers/i2c/rx6110sa/rx6110sa.c b/src/drivers/i2c/rx6110sa/rx6110sa.c
index 06735a7..761d83d 100644
--- a/src/drivers/i2c/rx6110sa/rx6110sa.c
+++ b/src/drivers/i2c/rx6110sa/rx6110sa.c
@@ -19,6 +19,7 @@
 #include <version.h>
 #include <console/console.h>
 #include <bcd.h>
+#include <timer.h>
 #include "chip.h"
 #include "rx6110sa.h"
 
@@ -86,62 +87,84 @@
 static void rx6110sa_init(struct device *dev)
 {
 	struct drivers_i2c_rx6110sa_config *config = dev->chip_info;
-	uint8_t reg;
+	uint8_t reg, flags;
+	struct stopwatch sw;
 
 	/* Do a dummy read first as requested in the datasheet. */
 	rx6110sa_read(dev, SECOND_REG);
+	/* Check power loss status by reading the VLF-bit. */
+	flags = rx6110sa_read(dev, FLAG_REGISTER);
+	if (flags & VLF_BIT) {
+		/*
+		 * Voltage low detected, perform RX6110 SA reset sequence as
+		 * requested in the datasheet. The meaning of the registers 0x60
+		 * and above is not documented in the datasheet, they have to be
+		 * used as requested according to Epson.
+		 */
+		rx6110sa_write(dev, BATTERY_BACKUP_REG, 0x00);
+		rx6110sa_write(dev, CTRL_REG, 0x00);
+		rx6110sa_write(dev, CTRL_REG, TEST_BIT);
+		rx6110sa_write(dev, 0x60, 0xd3);
+		rx6110sa_write(dev, 0x66, 0x03);
+		rx6110sa_write(dev, 0x6b, 0x02);
+		rx6110sa_write(dev, 0x6b, 0x01);
+		/* According to the datasheet one have to wait for at least 2 ms
+		 * before the VLF bit can be cleared in the flag register after
+		 * this reset sequence. As the other registers are still
+		 * accessible use the stopwatch to parallel the flow.
+		 */
+		stopwatch_init_msecs_expire(&sw, AFTER_RESET_DELAY_MS);
+	}
 	/*
-	 * Set battery backup mode and power monitor sampling time even if there
-	 * was no power loss to make sure that the right mode is used as it
-	 * directly influences the backup current consumption and therefore the
-	 * backup time.
+	 * Set up important registers even if there was no power loss to make
+	 * sure that the right mode is used as it directly influences the
+	 * backup current consumption and therefore the backup time. These
+	 * settings do not change current date and time and the RTC will not
+	 * be stopped while the registers are set up.
 	 */
 	reg = (config->pmon_sampling & PMON_SAMPL_MASK) |
 		(!!config->bks_off << 2) | (!!config->bks_on << 3) |
 		(!!config->iocut_en << 4);
 	rx6110sa_write(dev, BATTERY_BACKUP_REG, reg);
-	/*
-	 * Check VLF-bit which indicates the RTC data loss, such as due to a
-	 * supply voltage drop.
-	 */
-	reg = rx6110sa_read(dev, FLAG_REGISTER);
-	if (!(reg & VLF_BIT))
-		/* No voltage low detected, everything is well. */
-		return;
-	/*
-	 * Voltage low detected, initialize RX6110 SA again.
-	 * Set first some registers to known state.
-	 */
-	rx6110sa_write(dev, RESERVED_BIT_REG, RTC_INIT_VALUE);
-	rx6110sa_write(dev, DIGITAL_REG, 0x00);
-	reg = (!!config->enable_1hz_out << 4) |
-		(!!config->irq_output_pin << 2) |
-		(config->fout_output_pin & FOUT_OUTPUT_PIN_MASK);
-	rx6110sa_write(dev, IRQ_CONTROL_REG, reg);
 
 	/* Clear timer enable bit and set frequency of clock output. */
 	reg = rx6110sa_read(dev, EXTENSION_REG);
-	reg &= ~(FSEL_MASK | TE_BIT);
-	reg |= (config->cof_selection << 6);
+	reg &= ~(FSEL_MASK);
+	reg |= ((config->cof_selection << 6) & FSEL_MASK);
 	if (config->timer_preset) {
 		/* Timer needs to be in stop mode prior to programming it. */
-		rx6110sa_write(dev, EXTENSION_REG, reg);
-		reg &= ~TSEL_MASK;
+		if (reg & TE_BIT) {
+			reg &= ~TE_BIT;
+			rx6110sa_write(dev, EXTENSION_REG, reg);
+		}
 		/* Program the timer preset value. */
 		rx6110sa_write(dev, TMR_COUNTER_0_REG,
 				config->timer_preset & 0xff);
 		rx6110sa_write(dev, TMR_COUNTER_1_REG,
 				(config->timer_preset >> 8) & 0xff);
 		/* Set Timer Enable bit and the timer clock value. */
+		reg &= ~TSEL_MASK;
 		reg |= ((!!config->timer_en << 4) |
 			(config->timer_clk & TSEL_MASK));
 	}
 	rx6110sa_write(dev, EXTENSION_REG, reg);
-
-	/* Clear voltage low detect bit. */
-	reg = rx6110sa_read(dev, FLAG_REGISTER);
-	reg &= ~VLF_BIT;
-	rx6110sa_write(dev, FLAG_REGISTER, reg);
+	rx6110sa_write(dev, CTRL_REG, 0x00);
+	rx6110sa_write(dev, DIGITAL_REG, 0x00);
+	rx6110sa_write(dev, RESERVED_BIT_REG, RTC_INIT_VALUE);
+	reg = (!!config->enable_1hz_out << 4) |
+		(!!config->irq_output_pin << 2) |
+		(config->fout_output_pin & FOUT_OUTPUT_PIN_MASK);
+	rx6110sa_write(dev, IRQ_CONTROL_REG, reg);
+	/* If there was no power loss event no further steps are needed. */
+	if (!(flags & VLF_BIT))
+		return;
+	/* There was a power loss event, clear voltage low detect bit.
+	 * Take the needed delay after a reset sequence into account before the
+	 * VLF-bit can be cleared.
+	 */
+	while (!stopwatch_expired(&sw))
+		flags &= ~VLF_BIT;
+	rx6110sa_write(dev, FLAG_REGISTER, flags);
 
 	/* Before setting the clock stop oscillator. */
 	rx6110sa_write(dev, CTRL_REG, STOP_BIT);
diff --git a/src/drivers/i2c/rx6110sa/rx6110sa.h b/src/drivers/i2c/rx6110sa/rx6110sa.h
index ebd75ea..7e71f24 100644
--- a/src/drivers/i2c/rx6110sa/rx6110sa.h
+++ b/src/drivers/i2c/rx6110sa/rx6110sa.h
@@ -29,7 +29,7 @@
 #define MONTH_REG			0x15
 #define YEAR_REG			0x16
 #define RESERVED_BIT_REG		0x17
-#define  RTC_INIT_VALUE			0x28
+#define  RTC_INIT_VALUE			0xA8
 #define ALARM_MINUTE_REG		0x18
 #define ALARM_HOUR_REG			0x19
 #define ALARM_WEEKDAY_REG		0x1A
@@ -81,8 +81,10 @@
 #define PMON_SAMPL_256_MS		0x03
 
 /* Define on which pin of the RTC the generated square wave will be driven. */
-#define  FOUT_IRQ2			0x00	/* IRQ2 pin used for Fout */
-#define  FOUT_IRQ1			0x01	/* IRQ1 pin used for Fout */
-#define  FOUT_DO_FOUT			0x02	/* DO/FOUT pin used for Fout */
+#define FOUT_IRQ2			0x00	/* IRQ2 pin used for Fout */
+#define FOUT_IRQ1			0x01	/* IRQ1 pin used for Fout */
+#define FOUT_DO_FOUT			0x02	/* DO/FOUT pin used for Fout */
+
+#define AFTER_RESET_DELAY_MS		2	/* Delay after reset sequence */
 
 #endif /* _I2C_RX6110SA_H_ */

-- 
To view, visit https://review.coreboot.org/20412
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: If64d672e51667523058041bd00e1e50ac047143d
Gerrit-Change-Number: 20412
Gerrit-PatchSet: 1
Gerrit-Owner: Werner Zeh <werner.zeh at siemens.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20170629/b1f0be40/attachment-0001.html>


More information about the coreboot-gerrit mailing list