uboot/post/board/lwmon5/sysmon.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com
   3 *
   4 * Developed for DENX Software Engineering GmbH
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <post.h>
  10#include <common.h>
  11
  12/*
  13 * SYSMON test
  14 *
  15 * This test performs the system hardware monitoring.
  16 * The test passes when all the following voltages and temperatures
  17 * are within allowed ranges:
  18 *
  19 * Temperature            -40 .. +90 C
  20 * +5V                  +4.50 .. +5.50 V
  21 * +5V standby          +3.50 .. +5.50 V
  22 *
  23 * LCD backlight is not enabled if temperature values are not within
  24 * allowed ranges (-30 .. + 80). The brightness of backlite can be
  25 * controlled by setting "brightness" environment variable. Default value is 50%
  26 *
  27 * See the list of all parameters in the sysmon_table below
  28 */
  29
  30#include <post.h>
  31#include <watchdog.h>
  32#include <i2c.h>
  33
  34#if defined(CONFIG_VIDEO)
  35#include <mb862xx.h>
  36#endif
  37
  38#if CONFIG_POST & CONFIG_SYS_POST_SYSMON
  39
  40DECLARE_GLOBAL_DATA_PTR;
  41
  42/* from dspic.c */
  43extern int dspic_read(ushort reg, ushort *data);
  44
  45#define REG_TEMPERATURE                 0x12BC
  46#define REG_VOLTAGE_5V                  0x12CA
  47#define REG_VOLTAGE_5V_STANDBY          0x12C6
  48
  49#define TEMPERATURE_MIN                 (-40)   /* degr. C */
  50#define TEMPERATURE_MAX                 (+90)   /* degr. C */
  51#define TEMPERATURE_DISPLAY_MIN         (-35)   /* degr. C */
  52#define TEMPERATURE_DISPLAY_MAX         (+85)   /* degr. C */
  53
  54#define VOLTAGE_5V_MIN                  (+4500) /* mV */
  55#define VOLTAGE_5V_MAX                  (+5500) /* mV */
  56
  57#define VOLTAGE_5V_STANDBY_MIN          (+3500) /* mV */
  58#define VOLTAGE_5V_STANDBY_MAX          (+5500) /* mV */
  59
  60typedef struct sysmon_s sysmon_t;
  61typedef struct sysmon_table_s sysmon_table_t;
  62
  63static void sysmon_dspic_init(sysmon_t *this);
  64static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val);
  65static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr,  int *val);
  66static void sysmon_backlight_disable(sysmon_table_t *this);
  67
  68struct sysmon_s {
  69        uchar   chip;
  70        void    (*init)(sysmon_t *);
  71        int     (*read)(sysmon_t *, uint, int *);
  72};
  73
  74static sysmon_t sysmon_dspic = {
  75        CONFIG_SYS_I2C_DSPIC_IO_ADDR,
  76        sysmon_dspic_init,
  77        sysmon_dspic_read
  78};
  79
  80static sysmon_t sysmon_dspic_sgn = {
  81        CONFIG_SYS_I2C_DSPIC_IO_ADDR,
  82        sysmon_dspic_init,
  83        sysmon_dspic_read_sgn
  84};
  85
  86static sysmon_t *sysmon_list[] = {
  87        &sysmon_dspic,
  88        NULL
  89};
  90
  91struct sysmon_table_s {
  92        char            *name;
  93        char            *unit_name;
  94        sysmon_t        *sysmon;
  95        void            (*exec_before)(sysmon_table_t *);
  96        void            (*exec_after)(sysmon_table_t *);
  97
  98        int             unit_precision;
  99        int             unit_div;
 100        int             unit_min;
 101        int             unit_max;
 102        uint            val_mask;
 103        uint            val_min;
 104        uint            val_max;
 105        int             val_valid;
 106        uint            val_min_alt;
 107        uint            val_max_alt;
 108        int             val_valid_alt;
 109        uint            addr;
 110};
 111
 112static sysmon_table_t sysmon_table[] = {
 113        {
 114                "Temperature", " C", &sysmon_dspic, NULL, sysmon_backlight_disable,
 115                1, 1, -32768, 32767, 0xFFFF,
 116                0x8000 + TEMPERATURE_MIN,         0x8000 + TEMPERATURE_MAX,         0,
 117                0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0,
 118                REG_TEMPERATURE,
 119        },
 120
 121        {
 122                "+ 5 V", "V", &sysmon_dspic, NULL, NULL,
 123                100, 1000, -0x8000, 0x7FFF, 0xFFFF,
 124                0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0,
 125                0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0,
 126                REG_VOLTAGE_5V,
 127        },
 128
 129        {
 130                "+ 5 V standby", "V", &sysmon_dspic, NULL, NULL,
 131                100, 1000, -0x8000, 0x7FFF, 0xFFFF,
 132                0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0,
 133                0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0,
 134                REG_VOLTAGE_5V_STANDBY,
 135        },
 136
 137        {
 138                "Temperature", "°C", &sysmon_dspic_sgn, NULL, sysmon_backlight_disable,
 139                1, 1, -32768, 32767, 0xFFFF,
 140                0x8000 + TEMPERATURE_MIN,         0x8000 + TEMPERATURE_MAX,         0,
 141                0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0,
 142                REG_TEMPERATURE,
 143        },
 144};
 145
 146int sysmon_init_f(void)
 147{
 148        sysmon_t **l;
 149
 150        for (l = sysmon_list; *l; l++)
 151                (*l)->init(*l);
 152
 153        return 0;
 154}
 155
 156void sysmon_reloc(void)
 157{
 158        /* Do nothing for now, sysmon_reloc() is required by the sysmon post */
 159}
 160
 161static char *sysmon_unit_value(sysmon_table_t *s, uint val)
 162{
 163        static char buf[32];
 164        char *p, sign;
 165        int decimal, frac;
 166        int unit_val;
 167
 168        unit_val = s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask;
 169
 170        if (val == -1)
 171                return "I/O ERROR";
 172
 173        if (unit_val < 0) {
 174                sign = '-';
 175                unit_val = -unit_val;
 176        } else {
 177                sign = '+';
 178        }
 179
 180        p = buf + sprintf(buf, "%c%2d", sign, unit_val / s->unit_div);
 181
 182        frac = unit_val % s->unit_div;
 183        frac /= (s->unit_div / s->unit_precision);
 184
 185        decimal = s->unit_precision;
 186
 187        if (decimal != 1)
 188                *p++ = '.';
 189        for (decimal /= 10; decimal != 0; decimal /= 10)
 190                *p++ = '0' + (frac / decimal) % 10;
 191        strcpy(p, s->unit_name);
 192
 193        return buf;
 194}
 195
 196static void sysmon_dspic_init(sysmon_t *this)
 197{
 198}
 199
 200static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val)
 201{
 202        ushort data;
 203
 204        if (dspic_read(addr, &data) == 0){
 205                /* To fit into the table range we should add 0x8000 */
 206                *val = data + 0x8000;
 207                return 0;
 208        }
 209
 210        return -1;
 211}
 212
 213static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr, int *val)
 214{
 215        ushort data;
 216
 217        if (dspic_read(addr, &data) == 0){
 218                /* To fit into the table range we should add 0x8000 */
 219                *val = (signed short)data + 0x8000;
 220                return 0;
 221        }
 222
 223        return -1;
 224}
 225
 226static void sysmon_backlight_disable(sysmon_table_t *this)
 227{
 228#if defined(CONFIG_VIDEO)
 229        board_backlight_switch(this->val_valid_alt);
 230#endif
 231}
 232
 233int sysmon_post_test(int flags)
 234{
 235        int res = 0;
 236        sysmon_table_t * t;
 237        int val;
 238
 239        for (t = sysmon_table; t < sysmon_table + ARRAY_SIZE(sysmon_table); t++) {
 240                t->val_valid = 1;
 241                if (t->exec_before)
 242                        t->exec_before(t);
 243
 244                if (t->sysmon->read(t->sysmon, t->addr, &val) != 0) {
 245                        t->val_valid = 0;
 246                        t->val_valid_alt = 0;
 247                        post_log(": read failed\n");
 248                        res = 1;
 249                        break;
 250                }
 251
 252                if (t->val_valid != 0) {
 253                        t->val_valid = val >= t->val_min && val <= t->val_max;
 254                        t->val_valid_alt = val >= t->val_min_alt && val <= t->val_max_alt;
 255                }
 256
 257                if (t->exec_after)
 258                        t->exec_after(t);
 259
 260                if ((!t->val_valid) || (flags)) {
 261                        post_log("\n\t%-17s = %-10s ", t->name, sysmon_unit_value(t, val));
 262                        post_log("allowed range");
 263                        post_log(" %-8s ..", sysmon_unit_value(t, t->val_min));
 264                        post_log(" %-8s", sysmon_unit_value(t, t->val_max));
 265                        post_log("     %s", t->val_valid ? "OK" : "FAIL");
 266                }
 267
 268                if (!t->val_valid) {
 269                        res = 1;
 270                        break;
 271                }
 272        }
 273        post_log("\n");
 274
 275        return res;
 276}
 277#endif /* CONFIG_POST & CONFIG_SYS_POST_SYSMON */
 278