summaryrefslogtreecommitdiff
path: root/driver/temp_sensor
diff options
context:
space:
mode:
Diffstat (limited to 'driver/temp_sensor')
-rw-r--r--driver/temp_sensor/g781.c85
-rw-r--r--driver/temp_sensor/g781.h8
2 files changed, 92 insertions, 1 deletions
diff --git a/driver/temp_sensor/g781.c b/driver/temp_sensor/g781.c
index c178a37ace..33df02a7b5 100644
--- a/driver/temp_sensor/g781.c
+++ b/driver/temp_sensor/g781.c
@@ -11,11 +11,15 @@
#include "gpio.h"
#include "i2c.h"
#include "hooks.h"
+#include "system.h"
#include "util.h"
static int temp_val_local;
static int temp_val_remote;
-
+#ifdef CONFIG_TEMP_SENSOR_G781_INIT
+static int temp_val_local_high_limit = 0xFF;
+static int g781_reg_init = 1;
+#endif
/**
* Determine whether the sensor is powered.
*
@@ -40,6 +44,25 @@ static int raw_write8(const int offset, int data)
return i2c_write8(I2C_PORT_THERMAL, G781_I2C_ADDR, offset, data);
}
+#ifdef CONFIG_TEMP_SENSOR_G781_INIT
+static int status_read8(int *data)
+{
+ int rv;
+ /* We use buf[1] here so it's aligned for DMA on STM32 */
+ uint8_t buf[1];
+
+ i2c_lock(I2C_PORT_THERMAL, 1);
+ rv = i2c_xfer(I2C_PORT_THERMAL, G781_I2C_ALERT_ADDR,
+ 0, 0, buf, 1, I2C_XFER_SINGLE);
+ i2c_lock(I2C_PORT_THERMAL, 0);
+
+ if (!rv)
+ *data = buf[0];
+
+ return rv;
+}
+#endif
+
static int get_temp(const int offset, int *temp_ptr)
{
int rv;
@@ -80,8 +103,68 @@ int g781_get_val(int idx, int *temp_ptr)
return EC_SUCCESS;
}
+static void temp_sensor_g781_init_deferred(void)
+{
+#ifdef CONFIG_TEMP_SENSOR_G781_INIT
+ int alert_status, rv;
+ if (!g781_reg_init)
+ return;
+
+ /* Make sure this init all alert status is clear */
+ ccprintf("[%T Start G781 register init]\n");
+ rv = status_read8(&alert_status);
+ if (rv < 0)
+ return;
+
+ if (temp_val_local_high_limit == 0xFF) {
+ rv = get_temp(G781_LOCAL_TEMP_HIGH_LIMIT_R,
+ &temp_val_local_high_limit);
+ if ((rv == EC_SUCCESS) && (temp_val_local_high_limit
+ != G781_LOCAL_TEMP_HIGH_LIMIT_VALUE)) {
+ rv = set_temp(G781_LOCAL_TEMP_HIGH_LIMIT_W,
+ G781_LOCAL_TEMP_HIGH_LIMIT_VALUE);
+ if (rv < 0)
+ return;
+ }
+ }
+ g781_reg_init = EC_SUCCESS;
+
+ ccprintf("[%T Enable G781 ALERT# interrupt\n");
+ gpio_enable_interrupt(GPIO_FAN_ALERT_L);
+#endif
+}
+DECLARE_DEFERRED(temp_sensor_g781_init_deferred);
+
+static void temp_sensor_g781_init(void)
+{
+ hook_call_deferred(temp_sensor_g781_init_deferred, 0);
+}
+DECLARE_HOOK(HOOK_INIT, temp_sensor_g781_init, HOOK_PRIO_TEMP_SENSOR);
+
+static void fan_alert_deferred(void)
+{
+#ifdef CONFIG_TEMP_SENSOR_G781_INIT
+ ccprintf("[%T Fan alert force EC enter hibernate]\n");
+ system_hibernate(0, 0);
+#endif
+}
+DECLARE_DEFERRED(fan_alert_deferred);
+
+void fan_alert_interrupt(enum gpio_signal signal)
+{
+ hook_call_deferred(fan_alert_deferred, 0);
+ gpio_disable_interrupt(GPIO_FAN_ALERT_L);
+}
+
static void temp_sensor_poll(void)
{
+#ifdef CONFIG_TEMP_SENSOR_G781_INIT
+ if (g781_reg_init) {
+ ccprintf("[%T Retry to init G781 register]\n");
+ hook_call_deferred(temp_sensor_g781_init_deferred, 0);
+ }
+#endif
+
if (!has_power())
return;
diff --git a/driver/temp_sensor/g781.h b/driver/temp_sensor/g781.h
index 6463155659..2909de5c23 100644
--- a/driver/temp_sensor/g781.h
+++ b/driver/temp_sensor/g781.h
@@ -9,6 +9,7 @@
#define __CROS_EC_TEMP_SENSOR_G781_H
#define G781_I2C_ADDR 0x98 /* 7-bit address is 0x4C */
+#define G781_I2C_ALERT_ADDR 0x19
#define G781_IDX_INTERNAL 0
#define G781_IDX_EXTERNAL 1
@@ -67,4 +68,11 @@
*/
int g781_get_val(int idx, int *temp_ptr);
+/**
+ * Interrupt handler for fan alert.
+ *
+ * @param signal Signal which triggered the interrupt.
+ */
+void fan_alert_interrupt(enum gpio_signal signal);
+
#endif /* __CROS_EC_TEMP_SENSOR_G781_H */