Refactor temperature sensor code and add support of Link I2C temp sensor.

Refactor board/chip-specific code into corresponding directories.
Add support of the four I2C temp sensor in Link.
Use table lookup to handle different types of temperature sensors.

BUG=chrome-os-partner:7527
TEST=Correctly read EC internal temperature on bds.
Compile for link succeeded.

Change-Id: I694cfa54e1545798d877fafdf18c5585ab5f03e2
This commit is contained in:
Vic Yang
2012-01-12 17:02:10 +08:00
parent 249467b9f2
commit 000a6d5742
17 changed files with 440 additions and 29 deletions

View File

@@ -117,6 +117,13 @@ enum gpio_signal {
GPIO_COUNT
};
enum temp_sensor_id {
TEMP_SENSOR_EC_INTERNAL = 0, /* EC internal temperature sensor */
TEMP_SENSOR_CASE_DIE,
TEMP_SENSOR_COUNT
};
void configure_board(void);
#endif /* __BOARD_H */

View File

@@ -0,0 +1,22 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* BDS-specific temp sensor module for Chrome EC */
#include "temp_sensor.h"
#include "chip_temp_sensor.h"
#include "board.h"
#include "i2c.h"
#define TEMP_CASE_DIE_REG_ADDR ((0x40 << 1) | I2C_FLAG_BIG_ENDIAN)
#define TEMP_CASE_DIE_ADDR \
TMP006_ADDR(I2C_PORT_THERMAL, TEMP_CASE_DIE_REG_ADDR)
const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
{"ECInternal", TEMP_SENSOR_EC_INTERNAL, TEMP_SENSOR_NO_ADDR,
chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT},
{"CaseDie", TEMP_SENSOR_CASE_DIE, TEMP_CASE_DIE_ADDR,
temp_sensor_tmp006_read, temp_sensor_tmp006_print}
};

View File

@@ -5,3 +5,4 @@
CHIP:=lm4
board-y=board.o
board-$(CONFIG_TEMP_SENSOR)+=board_temp_sensor.o

View File

@@ -138,6 +138,23 @@ enum gpio_signal {
GPIO_COUNT
};
enum temp_sensor_id {
/* I2C die temperature sensor near CPU */
TEMP_SENSOR_I2C_DIE_NEAR_CPU = 0,
/* PCH temperature sensor */
TEMP_SENSOR_I2C_DIE_NEAR_PCH,
/* DDR memory temperature sensor */
TEMP_SENSOR_I2C_DIE_NEAR_DDR,
/* Battery charger temperature sensor */
TEMP_SENSOR_I2C_DIE_NEAR_CHARGER,
/* EC internal temperature sensor */
TEMP_SENSOR_EC_INTERNAL,
/* TODO: I2C temperature sensors. */
TEMP_SENSOR_COUNT
};
void configure_board(void);
#endif /* __BOARD_H */

View File

@@ -0,0 +1,37 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Link-specific temp sensor module for Chrome EC */
#include "temp_sensor.h"
#include "chip_temp_sensor.h"
#include "board.h"
#include "i2c.h"
#define TEMP_CPU_REG_ADDR ((0x40 << 1) | I2C_FLAG_BIG_ENDIAN)
#define TEMP_PCH_REG_ADDR ((0x41 << 1) | I2C_FLAG_BIG_ENDIAN)
#define TEMP_DDR_REG_ADDR ((0x43 << 1) | I2C_FLAG_BIG_ENDIAN)
#define TEMP_CHARGER_REG_ADDR ((0x45 << 1) | I2C_FLAG_BIG_ENDIAN)
#define TEMP_CPU_ADDR TMP006_ADDR(I2C_PORT_THERMAL, TEMP_CPU_REG_ADDR)
#define TEMP_PCH_ADDR TMP006_ADDR(I2C_PORT_THERMAL, TEMP_PCH_REG_ADDR)
#define TEMP_DDR_ADDR TMP006_ADDR(I2C_PORT_THERMAL, TEMP_DDR_REG_ADDR)
#define TEMP_CHARGER_ADDR TMP006_ADDR(I2C_PORT_THERMAL, TEMP_CHARGER_REG_ADDR)
/* Temperature sensors data. Must be in the same order as enum
* temp_sensor_id.
*/
const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
{"CPU", TEMP_SENSOR_I2C_DIE_NEAR_CPU, TEMP_CPU_ADDR,
temp_sensor_tmp006_read, temp_sensor_tmp006_print},
{"PCH", TEMP_SENSOR_I2C_DIE_NEAR_PCH, TEMP_PCH_ADDR,
temp_sensor_tmp006_read, temp_sensor_tmp006_print},
{"DDR", TEMP_SENSOR_I2C_DIE_NEAR_DDR, TEMP_DDR_ADDR,
temp_sensor_tmp006_read, temp_sensor_tmp006_print},
{"Charger", TEMP_SENSOR_I2C_DIE_NEAR_CHARGER, TEMP_CHARGER_ADDR,
temp_sensor_tmp006_read, temp_sensor_tmp006_print},
{"ECInternal", TEMP_SENSOR_EC_INTERNAL, TEMP_SENSOR_NO_ADDR,
chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT},
};

View File

@@ -9,3 +9,4 @@
CHIP:=lm4
board-y=board.o
board-$(CONFIG_TEMP_SENSOR)+=board_temp_sensor.o

View File

@@ -14,5 +14,6 @@ chip-y+=watchdog.o eeprom.o hwtimer.o
chip-$(CONFIG_FLASH)+=flash.o
chip-$(CONFIG_LPC)+=lpc.o
chip-$(CONFIG_PWM)+=pwm.o
chip-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o
chip-$(CONFIG_TEMP_SENSOR)+=chip_temp_sensor.o
chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o
chip-$(CONFIG_CHARGER)+=charger.o

96
chip/lm4/charger.c Normal file
View File

@@ -0,0 +1,96 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Charger/battery debug command module for Chrome EC */
/* TODO: remove this or merge into charger/battery modules
* once charger and battery modules are ready.
*/
#include "charger.h"
#include "board.h"
#include "i2c.h"
#include "console.h"
#include "uart.h"
#include "util.h"
/* Address of battery charger */
#define CHARGER_ADDR 0x12
/* Address of battery */
#define BATTERY_ADDR 0x16
/*****************************************************************************/
/* Console commands */
static int command_charger(int argc, char **argv)
{
int rv;
int d;
uart_puts("Reading battery charger...\n");
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0xfe, &d);
if (rv)
return rv;
uart_printf(" Manufacturer ID: 0x%04x\n", d);
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0xff, &d);
uart_printf(" Device ID: 0x%04x\n", d);
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0x12, &d);
uart_printf(" Option: 0x%04x\n", d);
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0x14, &d);
uart_printf(" Charge current: 0x%04x\n", d);
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0x15, &d);
uart_printf(" Charge voltage: 0x%04x\n", d);
rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, 0x3f, &d);
uart_printf(" Input current: 0x%04x\n", d);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(charger, command_charger);
static int command_battery(int argc, char **argv)
{
int rv;
int d;
uart_puts("Reading battery...\n");
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x08, &d);
if (rv)
return rv;
uart_printf(" Temperature: 0x%04x = %d C\n",
d, (d-2731)/10);
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x09, &d);
uart_printf(" Voltage: 0x%04x = %d mV\n", d, d);
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x0f, &d);
uart_printf(" Remaining capacity: 0x%04x = %d mAh\n", d, d);
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x10, &d);
uart_printf(" Full charge capacity: 0x%04x = %d mAh\n", d, d);
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x14, &d);
uart_printf(" Desired charge current: 0x%04x = %d mA\n", d, d);
rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, 0x15, &d);
uart_printf(" Desired charge voltage: 0x%04x = %d mV\n", d, d);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(battery, command_battery);
/*****************************************************************************/
/* Initialization */
int charger_init(void)
{
return EC_SUCCESS;
}

View File

@@ -0,0 +1,24 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Temperature sensor module for Chrome EC */
#include "adc.h"
#include "board.h"
#include "temp_sensor.h"
int chip_temp_sensor_read(const struct temp_sensor_t* sensor)
{
/* LM4 only has internal temperature sensor */
if (sensor->id != TEMP_SENSOR_EC_INTERNAL)
return EC_ERROR_INVAL;
return adc_read_channel(ADC_CH_EC_TEMP);
}
int chip_temp_sensor_init(void)
{
return EC_SUCCESS;
}

View File

@@ -36,6 +36,7 @@
#define CONFIG_LPC
#define CONFIG_PWM
#define CONFIG_TEMP_SENSOR
#define CONFIG_CHARGER
/* Compile for running from RAM instead of flash */
/* #define COMPILE_FOR_RAM */

View File

@@ -14,4 +14,4 @@ common-$(CONFIG_TASK_I8042CMD)+=i8042.o keyboard.o
common-$(CONFIG_TASK_X86POWER)+=x86_power.o
common-$(CONFIG_FLASH)+=flash_commands.o
common-$(CONFIG_PWM)+=pwm_commands.o
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor_commands.o
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o temp_sensor_commands.o

View File

@@ -31,7 +31,8 @@
#include "vboot.h"
#include "watchdog.h"
#include "usb_charge.h"
#include "chip_temp_sensor.h"
#include "charger.h"
int main(void)
{
@@ -75,10 +76,12 @@ int main(void)
i2c_init();
#ifdef CONFIG_TEMP_SENSOR
temp_sensor_init();
chip_temp_sensor_init();
#endif
power_button_init();
adc_init();
usb_charge_init();
charger_init();
/* Print the reset cause */
uart_printf("\n\n--- Chrome EC initialized! ---\n");

142
common/temp_sensor.c Normal file
View File

@@ -0,0 +1,142 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Temperature sensor module for Chrome EC */
#include "i2c.h"
#include "temp_sensor.h"
#include "uart.h"
#include "util.h"
#include "console.h"
#include "board.h"
/* Defined in board_temp_sensor.c. Must be in the same order as
* in enum temp_sensor_id.
*/
extern const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT];
int temp_sensor_read(enum temp_sensor_id id)
{
const struct temp_sensor_t *sensor;
if (id < 0 || id >= TEMP_SENSOR_COUNT)
return -1;
sensor = temp_sensors + id;
return sensor->read(sensor);
}
int temp_sensor_tmp006_read(const struct temp_sensor_t* sensor)
{
int traw, t;
int rv;
int addr = sensor->addr;
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x01, &traw);
if (rv)
return -1;
t = (int)(int16_t)traw / 128;
return t + 273;
}
void temp_sensor_tmp006_config(const struct temp_sensor_t* sensor)
{
int addr = sensor->addr;
/* Configure the sensor:
* 0x7000 = bits 14:12 = continuous conversion
* 0x0400 = bits 11:9 = ADC conversion rate (1/sec)
* 0x0100 = bit 8 = DRDY pin enabled */
/* TODO: support shutdown mode for power-saving? */
i2c_write16(TMP006_PORT(addr), TMP006_REG(addr), 0x02, 0x7500);
}
int temp_sensor_tmp006_print(const struct temp_sensor_t* sensor)
{
int vraw, v;
int traw, t;
int rv;
int d;
int addr = sensor->addr;
uart_printf("Debug data from %s:\n", sensor->name);
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0xfe, &d);
if (rv)
return rv;
uart_printf(" Manufacturer ID: 0x%04x\n", d);
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0xff, &d);
uart_printf(" Device ID: 0x%04x\n", d);
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x02, &d);
uart_printf(" Config: 0x%04x\n", d);
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x00, &vraw);
v = ((int)(int16_t)vraw * 15625) / 100;
uart_printf(" Voltage: 0x%04x = %d nV\n", vraw, v);
rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x01, &traw);
t = ((int)(int16_t)traw * 100) / 128;
uart_printf(" Temperature: 0x%04x = %d.%02d C\n",
traw, t / 100, t > 0 ? t % 100 : 100 - (t % 100));
return EC_SUCCESS;
}
/*****************************************************************************/
/* Console commands */
static int command_temps(int argc, char **argv)
{
int i;
int rv = 0;
int t;
uart_puts("Reading temperature sensors...\n");
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
uart_printf(" Temp from %s: ", temp_sensors[i].name);
t = temp_sensor_read(temp_sensors[i].id);
if (t < 0) {
uart_printf("Error.\n\n");
rv = -1;
}
else
uart_printf("%d K\n\n", t);
}
if (rv == -1)
return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(temps, command_temps);
static int command_sensor_info(int argc, char ** argv)
{
int i;
int rv;
const struct temp_sensor_t* sensor;
for (i = 0; i < TEMP_SENSOR_COUNT; ++i) {
sensor = temp_sensors + i;
if (sensor->print == TEMP_SENSOR_NO_PRINT)
continue;
rv = sensor->print(sensor);
if (rv != EC_SUCCESS)
return rv;
}
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(tempsinfo, command_sensor_info);
/*****************************************************************************/
/* Initialization */
int temp_sensor_init(void)
{
return EC_SUCCESS;
}

13
include/charger.h Normal file
View File

@@ -0,0 +1,13 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Charger/battery debug command module for Chrome EC */
#ifndef __CROS_EC_CHARGER_H
#define __CROS_EC_CHARGER_H
int charger_init(void);
#endif /* __CROS_EC_CHARGER_H */

View File

@@ -0,0 +1,20 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Temperature sensor module for LM4 chip */
#ifndef __CHIP_TEMP_SENSOR_H
#define __CHIP_TEMP_SENSOR_H
struct temp_sensor_t;
/* Temperature reading function. Input pointer to a sensor in temp_sensors.
* Return temperature in K.
*/
int chip_temp_sensor_read(const struct temp_sensor_t* sensor);
int chip_temp_sensor_init(void);
#endif /* __CHIP_TEMP_SENSOR_H */

View File

@@ -9,13 +9,30 @@
#define __CROS_EC_TEMP_SENSOR_H
#include "common.h"
#include "board.h"
enum temp_sensor_id {
TEMP_SENSOR_CASE = 0, /* Case temperature */
TEMP_SENSOR_CASE_DIE, /* Case temperature sensor die */
TEMP_SENSOR_EC_INTERNAL, /* EC internal temperature sensor */
/* "enum temp_sensor_id" must be defined for each board in board.h. */
struct temp_sensor_t {
const char* name;
enum temp_sensor_id id;
/* Sensor address. Used by read and print functions. */
int addr;
/* Read sensor value and return temperature in K. */
int (*read)(const struct temp_sensor_t* self);
/* Print debug info on console. */
int (*print)(const struct temp_sensor_t* self);
};
/* Dummy value to put in "addr" field in temp_sensor_t if we don't need to
* specify address.
*/
#define TEMP_SENSOR_NO_ADDR 0
/* Dummy value to put in "print" field in temp_sensor_t if we don't have debug
* function for a sensor.
*/
#define TEMP_SENSOR_NO_PRINT 0
/* Initializes the module. */
int temp_sensor_init(void);
@@ -23,4 +40,18 @@ int temp_sensor_init(void);
* or -1 if error. */
int temp_sensor_read(enum temp_sensor_id id);
#define TMP006_ADDR(PORT,REG) ((PORT << 16) + REG)
#define TMP006_PORT(ADDR) (ADDR >> 16)
#define TMP006_REG(ADDR) (ADDR & 0xffff)
/* Read TI TMP006 temperature sensor. Return temperature in K. */
int temp_sensor_tmp006_read(const struct temp_sensor_t* sensor);
/* Configure TMP006 DRDY pin. */
void temp_sensor_tmp006_config(const struct temp_sensor_t* sensor);
/* Print debug messages for TMP006. */
int temp_sensor_tmp006_print(const struct temp_sensor_t* sensor);
#endif /* __CROS_EC_TEMP_SENSOR_H */

View File

@@ -10,7 +10,6 @@
#include <unistd.h>
#include "lpc_commands.h"
#include "temp_sensor.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/* Don't use a macro where an inline will do... */
@@ -35,9 +34,8 @@ const char help_str[] =
" Serial output test for COM2\n"
" version\n"
" Prints EC version\n"
" temps [sensorname]\n"
" temps <sensorid>\n"
" Print temperature.\n"
" If sensorname is omitted, print temperature from all sensor.\n"
" pwmgetfanrpm\n"
" Prints current fan RPM\n"
" pwmsetfanrpm <targetrpm>\n"
@@ -438,14 +436,27 @@ int cmd_serial_test(int argc, char *argv[])
return 0;
}
int get_temperature(int sensor_id, const char* name)
int cmd_temperature(int argc, char *argv[])
{
struct lpc_params_temp_sensor_get_readings p;
struct lpc_response_temp_sensor_get_readings r;
int rv;
int id;
char *e;
p.temp_sensor_id = sensor_id;
printf("Reading %s...", name);
if (argc != 1) {
fprintf(stderr, "Usage: temps <sensorid>\n");
return -1;
}
id = strtol(argv[0], &e, 0);
if (e && *e) {
fprintf(stderr, "Bad sensor ID.\n");
return -1;
}
p.temp_sensor_id = id;
printf("Reading temperature...");
rv = ec_command(EC_LPC_COMMAND_TEMP_SENSOR_GET_READINGS,
&p, sizeof(p), &r, sizeof(r));
if (rv)
@@ -455,22 +466,6 @@ int get_temperature(int sensor_id, const char* name)
return rv;
}
int cmd_temperature(int argc, char *argv[])
{
int rv1 = 0, rv2 = 0, rv3 = 0;
if (argc == 0 || strcasecmp(argv[0], "TEMP_SENSOR_CASE") == 0)
rv1 = get_temperature(TEMP_SENSOR_CASE, "TEMP_SENSOR_CASE");
if (argc == 0 || strcasecmp(argv[0], "TEMP_SENSOR_CASE_DIE") == 0)
rv2 = get_temperature(TEMP_SENSOR_CASE_DIE,
"TEMP_SENSOR_CASE_DIE");
if (argc == 0 || strcasecmp(argv[0], "TEMP_SENSOR_EC_INTERNAL") == 0)
rv3 = get_temperature(TEMP_SENSOR_EC_INTERNAL,
"TEMP_SENSOR_EC_INTERNAL");
if (rv1 || rv2 || rv3)
return -1;
return 0;
}
int cmd_pwm_get_fan_rpm(void)
{
struct lpc_response_pwm_get_fan_rpm r;