Files
OpenCellular/util/comm-dev.c
Bill Richardson f36a859e06 samus: new algorithm for tmp006 object temperature
The original algorithm is given in the TMP006 User's Guide
(SBOU107.pdf). The algorithm we previously implemented is that,
plus some additional and completely undocumented massaging of the
Tdie and Vobj registers. The original meaning of that hack is now
lost in the mists of time, thanks to our email retention policy.

This CL introduces a new algorithm variant, but at least this
time the details are in the bug report. It's essentially the same
as the User's Guide algorithm, except that we apply one-stage FIR
filters to the Tdie input and the Tobj output.

There are five new parameters: d0, d1, ds, e0, e1. Refer to
tmp006_read_object_temp_k() in ec/driver/temp_sensor/tmp006.c to
see how these new parameters are applied.

CAUTION: The tmp006 sensor algorithm is mostly math and magic
numbers. The spreadsheet attached to the bug report has six
sheets with wildly varying values for those parameters. Since the
correct parameter values haven't yet been determined for Samus,
all I can be sure of with this CL is that it seems to work and
isn't any worse than the old one.

Oh, and note that the EC's 't6cal' console command has been
disabled until/unless we add support for floating point IO. Use
ectool from the host to get and set the params instead.

BUG=chrome-os-partner:32260
BRANCH=ToT,Samus
TEST=manual

After booting, look at the sensor values using ectool:

  localhost ~ # ectool temps all
  0: 312
  1: 314
  2: 313
  Sensor 3 not calibrated
  4: 311
  Sensor 5 not calibrated
  6: 305
  Sensor 7 not calibrated
  8: 306
  Sensor 9 not calibrated
  10: 307
  Sensor 11 not calibrated
  12: 312
  Sensor 13 not calibrated
  localhost ~ #
  localhost ~ # ectool tempsinfo all
  0: 0 PECI
  1: 1 ECInternal
  2: 1 I2C-Charger-Die
  3: 2 I2C-Charger-Object
  4: 1 I2C-CPU-Die
  5: 2 I2C-CPU-Object
  6: 1 I2C-Left C-Die
  7: 2 I2C-Left C-Object
  8: 1 I2C-Right C-Die
  9: 2 I2C-Right C-Object
  10: 1 I2C-Right D-Die
  11: 2 I2C-Right D-Object
  12: 1 I2C-Left D-Die
  13: 2 I2C-Left D-Object
  EC result 2 (ERROR)
  ...
  localhost ~ #

There are six tmp006 object temps that need calibrating. The
index used for the calibration is for the tmp006 objects, not the
3,5,7,.. numbers reported for all temp sensors. See the current
values with tmp006cal:

  localhost ~ # /tmp/ectool tmp006cal 5
  algorithm:  1
  params:
    s0  0.000000e+00
    a1  1.750000e-03
    a2  -1.678000e-05
    b0  -2.940000e-05
    b1  -5.700000e-07
    b2  4.630000e-09
    c2  1.340000e+01
    d0  2.000000e-01
    d1  8.000000e-01
    ds  1.480000e-04
    e0  1.000000e-01
    e1  9.000000e-01
  localhost ~ #

If the s0 param is zero, this sensor is uncalibrated. The params
are entered in the order in which they're displayed You can
change any or all of the parameters. Skip the ones you don't want
to update by specifying '-' for its position. (Note: throw in an
extra '--' first so that ectool doesn't think that negative
numbers are command options).

For example, to change s0 and b0:

  localhost ~ # ectool -- tmp006cal 5 1.0 - - -3.0
  localhost ~ #
  localhost ~ # ectool tmp006cal 5
  algorithm:  1
  params:
    s0  1.000000e+00
    a1  1.750000e-03
    a2  -1.678000e-05
    b0  -3.000000e+00
    b1  -5.700000e-07
    b2  4.630000e-09
    c2  1.340000e+01
    d0  2.000000e-01
    d1  8.000000e-01
    ds  1.480000e-04
    e0  1.000000e-01
    e1  9.000000e-01
  localhost ~ #

Now sensor 13 (tmp006 object index 5) is calibrated:

  localhost ~ # ectool temps all
  0: 310
  1: 315
  2: 313
  Sensor 3 not calibrated
  4: 310
  Sensor 5 not calibrated
  6: 305
  Sensor 7 not calibrated
  8: 307
  Sensor 9 not calibrated
  10: 307
  Sensor 11 not calibrated
  12: 312
  13: 313

Change-Id: I61b5da486f5e053a028c533ca9e00b9a82a91615
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/224409
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2014-10-22 00:30:31 +00:00

158 lines
3.5 KiB
C

/* Copyright (c) 2013 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.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "cros_ec_dev.h"
#include "comm-host.h"
#include "ec_commands.h"
static int fd = -1;
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(t) (sizeof(t) / sizeof(t[0]))
#endif
static const char const *meanings[] = {
"SUCCESS",
"INVALID_COMMAND",
"ERROR",
"INVALID_PARAM",
"ACCESS_DENIED",
"INVALID_RESPONSE",
"INVALID_VERSION",
"INVALID_CHECKSUM",
"IN_PROGRESS",
"UNAVAILABLE",
"TIMEOUT",
"OVERFLOW",
"INVALID_HEADER",
"REQUEST_TRUNCATED",
"RESPONSE_TOO_BIG",
"BUS_ERROR"
};
static const char *strresult(int i)
{
if (i < 0 || i >= ARRAY_SIZE(meanings))
return "<unknown>";
return meanings[i];
}
static int ec_command_dev(int command, int version,
const void *outdata, int outsize,
void *indata, int insize)
{
struct cros_ec_command s_cmd;
int r;
s_cmd.command = command;
s_cmd.version = version;
s_cmd.result = 0xff;
s_cmd.outsize = outsize;
s_cmd.outdata = (uint8_t *)outdata;
s_cmd.insize = insize;
s_cmd.indata = indata;
r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd);
if (r < 0) {
fprintf(stderr, "ioctl %d, errno %d (%s), EC result %d (%s)\n",
r, errno, strerror(errno), s_cmd.result,
strresult(s_cmd.result));
if (errno == EAGAIN && s_cmd.result == EC_RES_IN_PROGRESS) {
s_cmd.command = EC_CMD_RESEND_RESPONSE;
r = ioctl(fd, CROS_EC_DEV_IOCXCMD, &s_cmd);
fprintf(stderr,
"ioctl %d, errno %d (%s), EC result %d (%s)\n",
r, errno, strerror(errno), s_cmd.result,
strresult(s_cmd.result));
}
} else if (s_cmd.result != EC_RES_SUCCESS) {
fprintf(stderr, "EC result %d (%s)\n", s_cmd.result,
strresult(s_cmd.result));
return -EECRESULT - s_cmd.result;
}
return r;
}
static int ec_readmem_dev(int offset, int bytes, void *dest)
{
struct cros_ec_readmem s_mem;
struct ec_params_read_memmap r_mem;
int r;
static int fake_it;
if (!fake_it) {
s_mem.offset = offset;
s_mem.bytes = bytes;
s_mem.buffer = dest;
r = ioctl(fd, CROS_EC_DEV_IOCRDMEM, &s_mem);
if (r < 0 && errno == ENOTTY)
fake_it = 1;
else
return r;
}
r_mem.offset = offset;
r_mem.size = bytes;
return ec_command_dev(EC_CMD_READ_MEMMAP, 0,
&r_mem, sizeof(r_mem),
dest, bytes);
}
int comm_init_dev(const char *device_name)
{
char version[80];
char device[80] = "/dev/";
int r;
char *s;
strncat(device, (device_name ? device_name : CROS_EC_DEV_NAME), 40);
fd = open(device, O_RDWR);
if (fd < 0)
return 1;
r = read(fd, version, sizeof(version)-1);
if (r <= 0) {
close(fd);
return 2;
}
version[r] = '\0';
s = strchr(version, '\n');
if (s)
*s = '\0';
if (strcmp(version, CROS_EC_DEV_VERSION)) {
close(fd);
return 3;
}
ec_command_proto = ec_command_dev;
if (ec_readmem_dev(EC_MEMMAP_ID, 2, version) == 2 &&
version[0] == 'E' && version[1] == 'C')
ec_readmem = ec_readmem_dev;
/*
* TODO(crosbug.com/p/23823): Need a way to get this from the driver
* and EC. For now, pick a magic lowest common denominator value. The
* ec_max_outsize is set to handle v3 EC protocol. The ec_max_insize
* needs to be set to the largest value that can be returned from the
* EC, EC_PROTO2_MAX_PARAM_SIZE.
*/
ec_max_outsize = EC_PROTO2_MAX_PARAM_SIZE - 8;
ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE;
return 0;
}