<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>