<p>Werner Zeh has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/20412">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">rx6110sa: Add a software reset sequence in case of power loss<br><br>According to the datasheet the RTC needs a power rising slope of no more<br>than 100µs/V to ensure a correct power-on reset. If the mainboard that<br>hosts the RTC cannot guarantee this, a software reset sequence is needed<br>in the case where the battery was drained completely.<br><br>As the rising slope of the power supply depends on so many parameters<br>and is highly mainboard specific, refactor the initialization code to<br>perform a software reset every time a power loss event is recognized by<br>the RTC.<br><br>Change-Id: If64d672e51667523058041bd00e1e50ac047143d<br>Signed-off-by: Werner Zeh <werner.zeh@siemens.com><br>---<br>M src/drivers/i2c/rx6110sa/rx6110sa.c<br>M src/drivers/i2c/rx6110sa/rx6110sa.h<br>2 files changed, 61 insertions(+), 36 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/12/20412/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/drivers/i2c/rx6110sa/rx6110sa.c b/src/drivers/i2c/rx6110sa/rx6110sa.c<br>index 06735a7..761d83d 100644<br>--- a/src/drivers/i2c/rx6110sa/rx6110sa.c<br>+++ b/src/drivers/i2c/rx6110sa/rx6110sa.c<br>@@ -19,6 +19,7 @@<br> #include <version.h><br> #include <console/console.h><br> #include <bcd.h><br>+#include <timer.h><br> #include "chip.h"<br> #include "rx6110sa.h"<br> <br>@@ -86,62 +87,84 @@<br> static void rx6110sa_init(struct device *dev)<br> {<br> struct drivers_i2c_rx6110sa_config *config = dev->chip_info;<br>- uint8_t reg;<br>+ uint8_t reg, flags;<br>+ struct stopwatch sw;<br> <br> /* Do a dummy read first as requested in the datasheet. */<br> rx6110sa_read(dev, SECOND_REG);<br>+ /* Check power loss status by reading the VLF-bit. */<br>+ flags = rx6110sa_read(dev, FLAG_REGISTER);<br>+ if (flags & VLF_BIT) {<br>+ /*<br>+ * Voltage low detected, perform RX6110 SA reset sequence as<br>+ * requested in the datasheet. The meaning of the registers 0x60<br>+ * and above is not documented in the datasheet, they have to be<br>+ * used as requested according to Epson.<br>+ */<br>+ rx6110sa_write(dev, BATTERY_BACKUP_REG, 0x00);<br>+ rx6110sa_write(dev, CTRL_REG, 0x00);<br>+ rx6110sa_write(dev, CTRL_REG, TEST_BIT);<br>+ rx6110sa_write(dev, 0x60, 0xd3);<br>+ rx6110sa_write(dev, 0x66, 0x03);<br>+ rx6110sa_write(dev, 0x6b, 0x02);<br>+ rx6110sa_write(dev, 0x6b, 0x01);<br>+ /* According to the datasheet one have to wait for at least 2 ms<br>+ * before the VLF bit can be cleared in the flag register after<br>+ * this reset sequence. As the other registers are still<br>+ * accessible use the stopwatch to parallel the flow.<br>+ */<br>+ stopwatch_init_msecs_expire(&sw, AFTER_RESET_DELAY_MS);<br>+ }<br> /*<br>- * Set battery backup mode and power monitor sampling time even if there<br>- * was no power loss to make sure that the right mode is used as it<br>- * directly influences the backup current consumption and therefore the<br>- * backup time.<br>+ * Set up important registers even if there was no power loss to make<br>+ * sure that the right mode is used as it directly influences the<br>+ * backup current consumption and therefore the backup time. These<br>+ * settings do not change current date and time and the RTC will not<br>+ * be stopped while the registers are set up.<br> */<br> reg = (config->pmon_sampling & PMON_SAMPL_MASK) |<br> (!!config->bks_off << 2) | (!!config->bks_on << 3) |<br> (!!config->iocut_en << 4);<br> rx6110sa_write(dev, BATTERY_BACKUP_REG, reg);<br>- /*<br>- * Check VLF-bit which indicates the RTC data loss, such as due to a<br>- * supply voltage drop.<br>- */<br>- reg = rx6110sa_read(dev, FLAG_REGISTER);<br>- if (!(reg & VLF_BIT))<br>- /* No voltage low detected, everything is well. */<br>- return;<br>- /*<br>- * Voltage low detected, initialize RX6110 SA again.<br>- * Set first some registers to known state.<br>- */<br>- rx6110sa_write(dev, RESERVED_BIT_REG, RTC_INIT_VALUE);<br>- rx6110sa_write(dev, DIGITAL_REG, 0x00);<br>- reg = (!!config->enable_1hz_out << 4) |<br>- (!!config->irq_output_pin << 2) |<br>- (config->fout_output_pin & FOUT_OUTPUT_PIN_MASK);<br>- rx6110sa_write(dev, IRQ_CONTROL_REG, reg);<br> <br> /* Clear timer enable bit and set frequency of clock output. */<br> reg = rx6110sa_read(dev, EXTENSION_REG);<br>- reg &= ~(FSEL_MASK | TE_BIT);<br>- reg |= (config->cof_selection << 6);<br>+ reg &= ~(FSEL_MASK);<br>+ reg |= ((config->cof_selection << 6) & FSEL_MASK);<br> if (config->timer_preset) {<br> /* Timer needs to be in stop mode prior to programming it. */<br>- rx6110sa_write(dev, EXTENSION_REG, reg);<br>- reg &= ~TSEL_MASK;<br>+ if (reg & TE_BIT) {<br>+ reg &= ~TE_BIT;<br>+ rx6110sa_write(dev, EXTENSION_REG, reg);<br>+ }<br> /* Program the timer preset value. */<br> rx6110sa_write(dev, TMR_COUNTER_0_REG,<br> config->timer_preset & 0xff);<br> rx6110sa_write(dev, TMR_COUNTER_1_REG,<br> (config->timer_preset >> 8) & 0xff);<br> /* Set Timer Enable bit and the timer clock value. */<br>+ reg &= ~TSEL_MASK;<br> reg |= ((!!config->timer_en << 4) |<br> (config->timer_clk & TSEL_MASK));<br> }<br> rx6110sa_write(dev, EXTENSION_REG, reg);<br>-<br>- /* Clear voltage low detect bit. */<br>- reg = rx6110sa_read(dev, FLAG_REGISTER);<br>- reg &= ~VLF_BIT;<br>- rx6110sa_write(dev, FLAG_REGISTER, reg);<br>+ rx6110sa_write(dev, CTRL_REG, 0x00);<br>+ rx6110sa_write(dev, DIGITAL_REG, 0x00);<br>+ rx6110sa_write(dev, RESERVED_BIT_REG, RTC_INIT_VALUE);<br>+ reg = (!!config->enable_1hz_out << 4) |<br>+ (!!config->irq_output_pin << 2) |<br>+ (config->fout_output_pin & FOUT_OUTPUT_PIN_MASK);<br>+ rx6110sa_write(dev, IRQ_CONTROL_REG, reg);<br>+ /* If there was no power loss event no further steps are needed. */<br>+ if (!(flags & VLF_BIT))<br>+ return;<br>+ /* There was a power loss event, clear voltage low detect bit.<br>+ * Take the needed delay after a reset sequence into account before the<br>+ * VLF-bit can be cleared.<br>+ */<br>+ while (!stopwatch_expired(&sw))<br>+ flags &= ~VLF_BIT;<br>+ rx6110sa_write(dev, FLAG_REGISTER, flags);<br> <br> /* Before setting the clock stop oscillator. */<br> rx6110sa_write(dev, CTRL_REG, STOP_BIT);<br>diff --git a/src/drivers/i2c/rx6110sa/rx6110sa.h b/src/drivers/i2c/rx6110sa/rx6110sa.h<br>index ebd75ea..7e71f24 100644<br>--- a/src/drivers/i2c/rx6110sa/rx6110sa.h<br>+++ b/src/drivers/i2c/rx6110sa/rx6110sa.h<br>@@ -29,7 +29,7 @@<br> #define MONTH_REG 0x15<br> #define YEAR_REG 0x16<br> #define RESERVED_BIT_REG 0x17<br>-#define RTC_INIT_VALUE 0x28<br>+#define RTC_INIT_VALUE 0xA8<br> #define ALARM_MINUTE_REG 0x18<br> #define ALARM_HOUR_REG 0x19<br> #define ALARM_WEEKDAY_REG 0x1A<br>@@ -81,8 +81,10 @@<br> #define PMON_SAMPL_256_MS 0x03<br> <br> /* Define on which pin of the RTC the generated square wave will be driven. */<br>-#define FOUT_IRQ2 0x00 /* IRQ2 pin used for Fout */<br>-#define FOUT_IRQ1 0x01 /* IRQ1 pin used for Fout */<br>-#define FOUT_DO_FOUT 0x02 /* DO/FOUT pin used for Fout */<br>+#define FOUT_IRQ2 0x00 /* IRQ2 pin used for Fout */<br>+#define FOUT_IRQ1 0x01 /* IRQ1 pin used for Fout */<br>+#define FOUT_DO_FOUT 0x02 /* DO/FOUT pin used for Fout */<br>+<br>+#define AFTER_RESET_DELAY_MS 2 /* Delay after reset sequence */<br> <br> #endif /* _I2C_RX6110SA_H_ */<br></pre><p>To view, visit <a href="https://review.coreboot.org/20412">change 20412</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/20412"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: If64d672e51667523058041bd00e1e50ac047143d </div>
<div style="display:none"> Gerrit-Change-Number: 20412 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Werner Zeh <werner.zeh@siemens.com> </div>