r4502 - in developers/werner: . greg greg/tests
werner at docs.openmoko.org
werner at docs.openmoko.org
Thu Jun 26 07:01:11 CEST 2008
Author: werner
Date: 2008-06-26 07:01:10 +0200 (Thu, 26 Jun 2008)
New Revision: 4502
Added:
developers/werner/greg/
developers/werner/greg/Makefile
developers/werner/greg/README
developers/werner/greg/cpp.c
developers/werner/greg/cpp.h
developers/werner/greg/dr.pl
developers/werner/greg/greg.c
developers/werner/greg/greg.h
developers/werner/greg/lang.l
developers/werner/greg/lang.y
developers/werner/greg/pcf50633.greg
developers/werner/greg/reg.h
developers/werner/greg/tests/
developers/werner/greg/tests/Common
developers/werner/greg/tests/Makefile
developers/werner/greg/tests/field
developers/werner/greg/tests/reg
developers/werner/greg/tests/value
developers/werner/greg/tests/width
Log:
greg is a processor for register definitions. It can be used to pretty-print
register dumps. Work in progress.
Added: developers/werner/greg/Makefile
===================================================================
--- developers/werner/greg/Makefile (rev 0)
+++ developers/werner/greg/Makefile 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,52 @@
+CFLAGS_WARN=-Wall -Wshadow -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations
+CFLAGS=-g -DCPP='"cpp"' $(CFLAGS_WARN)
+SLOPPY=-Wno-unused -Wno-implicit-function-declaration -Wno-missing-prototypes \
+ -Wno-missing-declarations
+LDLIBS=-lfl
+
+OBJS=greg.o lex.yy.o y.tab.o cpp.o
+
+.PHONY: all dep depend clean spotless test tests
+
+# ----- Build -----------------------------------------------------------------
+
+all: greg
+
+greg: $(OBJS)
+
+lex.yy.c: lang.l y.tab.h
+ $(LEX) lang.l
+
+lex.yy.o: lex.yy.c y.tab.h
+ $(CC) -c $(CFLAGS) $(SLOPPY) lex.yy.c
+
+y.tab.c y.tab.h: lang.y
+ $(YACC) $(YYFLAGS) -d lang.y
+
+y.tab.o: y.tab.c
+ $(CC) -c $(CFLAGS) $(SLOPPY) y.tab.c
+
+# ----- Dependencies ----------------------------------------------------------
+
+dep depend .depend: lex.yy.c y.tab.h y.tab.c
+ $(CPP) $(CFLAGS) -MM -MG *.c >.depend || \
+ { rm -f .depend; exit 1; }
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+# ----- Cleanup ---------------------------------------------------------------
+
+clean:
+ rm -f lex.yy.c y.tab.h y.tab.c
+ rm -f $(OBJS) .depend
+
+spotless: clean
+ rm -f greg
+
+# ----- Tests -----------------------------------------------------------------
+
+test tests: greg
+ $(MAKE) -C tests
Added: developers/werner/greg/README
===================================================================
--- developers/werner/greg/README (rev 0)
+++ developers/werner/greg/README 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,109 @@
+"greg" reads a general register description and can then produce output based
+on this description, or answer queries.
+
+Example: it can pretty-print a register dump.
+
+./greg pcf50633.greg reg_id reg_value ...
+
+Where reg_id is the identifier of the register, e.g., "13" for GPIOCTL,
+and reg_value is the value of that register. Note that reg_id is a
+case-sensitive string, while reg_value is a number in the usual C
+syntax.
+
+
+Known issues
+------------
+
+- output format should be easier to read
+- value names in pcf50633.greg are often unsuitable for identifier generation
+ (should align them properly with what we use in u-boot and kernel)
+- "pretty-print" is hard to read
+- unique() should use rb-trees
+- greg.c should use unique(), to accelerate lookups
+
+
+dr.pl
+-----
+
+dr.pl is a wrapper for "greg". It processes dumps like the one produced by
+the following function (in u-boot):
+
+
+static void dump_pmu(void)
+{
+ int i, j;
+
+ for (i = 0; i != 0x70; i += 16) {
+ printf("%02x:", i);
+ for (j = 0; j != 16; j++)
+ printf(" %02x", pcf50633_reg_read(i+j));
+ printf("\n");
+ }
+}
+
+
+Example register dump (with titles):
+
+
+in LED loop, with battery.
+
+00: 13 84 00 00 00 00 00 00 f0 40 00 00 00 d3 aa 4a
+10: 15 44 ff 01 00 00 00 00 02 08 6b 01 00 0a 1b 02
+20: 00 22 2f 01 00 22 00 00 2f 00 05 20 11 18 00 18
+30: 00 00 00 00 00 15 00 15 00 18 00 00 00 ff 3f 00
+40: 00 07 00 00 28 19 ff ff 00 01 10 33 20 50 19 00
+50: 00 08 00 00 00 0b 00 f0 00 13 14 17 04 19 05 08
+60: 7f 7f 3f 07 3f 1f ff 00 00 00 00 00 00 00 00 00
+
+in LED loop, no battery. (LED on)
+
+00: 13 84 00 00 00 00 00 00 f0 40 00 00 00 d3 aa 4a
+10: 15 44 bf 01 00 00 00 00 03 08 6b 01 00 0a 1b 02
+20: 00 22 2f 01 00 22 00 00 2f 00 05 20 11 18 00 18
+30: 00 00 00 00 00 15 00 15 00 18 00 00 00 ff 3f 00
+40: 00 07 00 00 28 19 ff ff 00 01 10 33 20 d0 19 00
+50: 00 08 00 00 00 0b 00 f0 00 41 14 17 04 19 05 08
+60: 7f 7f 3f 07 3f 1f ff 00 00 00 00 00 00 00 00 00
+
+
+If these two dumps are sent to the standard input of dr.pl, it will
+output the difference between them:
+
+
+----- in LED loop, no battery. (LED on) ---------------------------------------
+--- _a 2008-06-26 01:52:33.000000000 -0300
++++ _b 2008-06-26 01:52:33.000000000 -0300
+@@ -1,11 +1,11 @@
+-18 BVMCTL = 0x02 -- BVM control
++18 BVMCTL = 0x03 -- BVM control
+ bvmlow -- BAT voltage is lower than Vth(batok)
+- 0 (0x0)
++ 1 (0x1)
+ bvmlvl -- Vth(batok)
+ 001 (0x1): 2_80V
+ bvmdisdb -- 62ms debounce filter
+ 0 (0x0): enabled
+-4d MBCS3 = 0x50 -- MBC charger status 3
++4d MBCS3 = 0xd0 -- MBC charger status 3
+ usblim_play -- USB current limiting in USB-to-SYS path
+ 0 (0x0)
+ usblim_chg -- USB current limiting in USB-to-BAT path
+@@ -21,7 +21,7 @@
+ vbatstat -- battery voltage > Vbatcond
+ 1 (0x1)
+ vres -- battery voltage > Vth(RES)
+- 0 (0x0)
+-59 RTCSC = 0x13 -- RTC second value
++ 1 (0x1)
++59 RTCSC = 0x41 -- RTC second value
+ sec -- current seconds, BCD
+- 001.0011 (0x13)
++ 100.0001 (0x41)
+
+
+If more than two dumps are input to dr.pl, it will produce the
+difference between the first and the second, then the second and
+the third, and so on.
+
+If only one dump is input to dr.pl, it will pretty-print all
+registers.
Added: developers/werner/greg/cpp.c
===================================================================
--- developers/werner/greg/cpp.c (rev 0)
+++ developers/werner/greg/cpp.c 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,214 @@
+/*
+ * cpp.c - CPP subprocess
+ *
+ * Written 2002-2004, 2006, 2008 by Werner Almesberger
+ * Copyright 2002,2003 California Institute of Technology
+ * Copyright 2004, 2006 Werner Almesberger
+ * Copyright 2008 by OpenMoko, Inc.
+ *
+ * Distributed under GPLv2, or any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "cpp.h"
+
+
+const char *cpp_command = CPP;
+
+static pid_t cpp_pid;
+static int cpp_argc = 0;
+static const char **cpp_argv = NULL;
+static int real_stdin = -1;
+
+
+void add_cpp_arg(const char *arg)
+{
+ if (!cpp_argc)
+ cpp_argc = 1;
+ cpp_argv = realloc(cpp_argv,sizeof(const char *)*(cpp_argc+1));
+ if (!cpp_argv) {
+ perror("realloc");
+ exit(1);
+ }
+ if (cpp_argc == 1)
+ cpp_argv[0] = cpp_command;
+ if (arg) {
+ arg = strdup(arg);
+ if (!arg) {
+ perror("strdup");
+ exit(1);
+ }
+ }
+ cpp_argv[cpp_argc++] = arg;
+}
+
+
+void add_cpp_Wp(const char *arg)
+{
+ char *tmp = strdup(arg);
+ char *curr,*end;
+
+ if (!tmp) {
+ perror("strdup");
+ exit(1);
+ }
+ curr = tmp;
+ do {
+ end = strchr(curr,',');
+ if (end)
+ *end++ = 0;
+ add_cpp_arg(curr);
+ curr = end;
+ }
+ while (end);
+ free(tmp);
+}
+
+
+static void kill_cpp(void)
+{
+ if (cpp_pid)
+ (void) kill(cpp_pid,SIGTERM);
+}
+
+
+static void run_cpp(const char *name,int fd,int close_fd)
+{
+ char **arg;
+ int fds[2];
+
+ if (pipe(fds) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+ if (name)
+ add_cpp_arg(name);
+ add_cpp_arg(NULL);
+ cpp_pid = fork();
+ if (cpp_pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+ if (!cpp_pid) {
+ if (close(fds[0]) < 0) {
+ perror("close");
+ exit(1);
+ }
+ if (close_fd != -1 && close(close_fd) < 0) {
+ perror("close");
+ exit(1);
+ }
+ if (fd != -1 && dup2(fd,0) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ if (dup2(fds[1],1) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ if (execvp(cpp_command,(char **) cpp_argv) < 0) {
+ /* prototype is weird */
+ perror(cpp_command);
+ exit(1);
+ }
+ /* not reached */
+ }
+ if (close(fds[1]) < 0) {
+ perror("close");
+ exit(1);
+ }
+ real_stdin = dup(0);
+ if (real_stdin < 0) {
+ perror("dup");
+ exit(1);
+ }
+ if (fd != -1 && close(fd) < 0) {
+ perror("close");
+ exit(1);
+ }
+ if (dup2(fds[0],0) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ for (arg = (char **) cpp_argv+1; *arg; arg++)
+ free(*arg);
+ free(cpp_argv);
+ cpp_argv = NULL;
+ cpp_argc = 0;
+}
+
+
+void run_cpp_on_file(const char *name)
+{
+ run_cpp(name,name ? -1 : 0,-1);
+ atexit(kill_cpp);
+}
+
+
+void run_cpp_on_string(const char *str)
+{
+ int fds[2];
+ pid_t pid;
+ int left,wrote;
+
+ if (pipe(fds) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+ run_cpp(NULL,fds[0],fds[1]);
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+ if (!pid) {
+ for (left = strlen(str); left; left -= wrote) {
+ wrote = write(fds[1],str,left);
+ if (wrote < 0)
+ break; /* die silently */
+ str += wrote;
+ }
+ exit(0);
+ }
+ if (close(fds[1]) < 0) {
+ perror("close");
+ exit(1);
+ }
+ atexit(kill_cpp);
+}
+
+
+void reap_cpp(void)
+{
+ int status;
+
+ cpp_pid = 0;
+ if (waitpid(cpp_pid,&status,0) < 0) {
+ perror("waitpid");
+ exit(1);
+ }
+ if (!status) {
+ if (dup2(real_stdin,0) < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ return;
+ }
+ if (WIFEXITED(status))
+ exit(WEXITSTATUS(status));
+ if (WIFSIGNALED(status))
+ fprintf(stderr,"cpp terminated with signal %d\n",WTERMSIG(status));
+ else
+ fprintf(stderr,"cpp terminated with incomprehensible status %d\n",
+ status);
+ exit(1);
+}
Added: developers/werner/greg/cpp.h
===================================================================
--- developers/werner/greg/cpp.h (rev 0)
+++ developers/werner/greg/cpp.h 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,24 @@
+/*
+ * cpp.h - CPP subprocess
+ *
+ * Written 2002,2003,2008 by Werner Almesberger
+ * Copyright 2002,2003 Caltech Netlab FAST project
+ * Copyright 2008 by OpenMoko, Inc.
+ *
+ * Distributed under GPLv2, or any later version.
+ *
+ */
+
+#ifndef CPP_H
+#define CPP_H
+
+
+extern const char *cpp_command;
+
+void add_cpp_arg(const char *arg);
+void add_cpp_Wp(const char *arg);
+void run_cpp_on_file(const char *name); /* NULL for stdin */
+void run_cpp_on_string(const char *str);
+void reap_cpp(void);
+
+#endif /* CPP_H */
Added: developers/werner/greg/dr.pl
===================================================================
--- developers/werner/greg/dr.pl (rev 0)
+++ developers/werner/greg/dr.pl 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+
+$run = 0;
+
+
+sub flush
+{
+ local ($single) = @_;
+ if (++$run > 2) {
+ undef @a;
+ undef @b;
+ for ($i = 0; $i != 0x70; $i++) {
+ next if $i == 0x2c || $i == 0x51 || $i == 0x58 || $i == 0x6f;
+ if ($l[$i] != $v[$i]) {
+ push(@a, sprintf("%02x", $i), "0x".$l[$i]);
+ push(@b, sprintf("%02x", $i), "0x".$v[$i]);
+ }
+ }
+ print "----- ".$title." ".("-" x (72-length $title))."\n";
+ if ($single) {
+ system("./greg pcf50633.greg ".join(" ", @a));
+ } else {
+ system("./greg pcf50633.greg >_a ".join(" ", @a));
+ system("./greg pcf50633.greg >_b ".join(" ", @b));
+ system("diff -u _a _b");
+ }
+ }
+ @l = @v;
+ undef @v;
+}
+
+
+while (<>) {
+ chop;
+ next if /^\s*$/;
+ &flush(0) if /^00:/;
+ if (!/^..:/) {
+ $title = $_;
+ next;
+ }
+ @r = split " ";
+ $b = hex shift @r;
+ for ($i = 0; $i != 16; $i++) {
+ die unless defined $r[$i];
+ $v[$b+$i] = $r[$i];
+ }
+}
+&flush(0);
+
+&flush(1) if $run == 2;
Property changes on: developers/werner/greg/dr.pl
___________________________________________________________________
Name: svn:executable
+ *
Added: developers/werner/greg/greg.c
===================================================================
--- developers/werner/greg/greg.c (rev 0)
+++ developers/werner/greg/greg.c 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,123 @@
+/*
+ * greg.c - Generalized register processor
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "reg.h"
+#include "cpp.h"
+#include "greg.h"
+
+
+static int show_reserved = 0;
+
+
+static const char *num_to_binary(unsigned long long num, int bits)
+{
+ static char buf[32+8+1];
+ char *p = buf;
+ int i;
+
+ for (i = bits-1; i >= 0; i--) {
+ *p++ = (num >> i) & 1 ? '1' : '0';
+ if (i && !(i & 3))
+ *p++ = '.';
+ }
+ *p = 0;
+ return buf;
+}
+
+
+static void print_value(const struct value *v, unsigned long long n)
+{
+ switch (v->type) {
+ case vt_none:
+ break;
+ case vt_list:
+ printf(": %s",
+ v->u.list[n].name ? v->u.list[n].name : "RESERVED");
+ if (v->u.list[n].comment)
+ printf(" -- %s", v->u.list[n].comment);
+ break;
+ case vt_formula:
+ printf(": %d+%d*%llu = %llu", v->u.formula.b, v->u.formula.a, n,
+ v->u.formula.b+(unsigned long long) v->u.formula.a*n);
+ if (v->u.formula.unit)
+ printf(" %s", v->u.formula.unit);
+ break;
+ default:
+ abort();
+ }
+}
+
+
+static void print_field(const struct field *field, unsigned long long value)
+{
+ printf(" %s", field->name ? field->name : "(reserved)");
+ if (field->comment)
+ printf(" -- %s", field->comment);
+ putchar('\n');
+ printf("\t%s (0x%0*llx)", num_to_binary(value, field->bits),
+ (field->bits+3) >> 2, value);
+ print_value(&field->value, value);
+ putchar('\n');
+}
+
+
+static void print(const char *id, unsigned long long value)
+{
+ const struct reg *reg;
+ const struct field *field;
+
+ for (reg = regs; reg; reg = reg->next)
+ if (!strcmp(reg->id, id))
+ break;
+ if (!reg) {
+ fprintf(stderr, "register \"%s\" not found\n", id);
+ exit(1);
+ }
+ printf("%s %s = 0x%0*llx",
+ reg->id, reg->name, (reg->bits+3) >> 2, value);
+ if (reg->comment)
+ printf(" -- %s", reg->comment);
+ putchar('\n');
+ for (field = reg->fields; field; field = field->next) {
+ if (field->name || show_reserved)
+ print_field(field, value & ((1ULL << field->bits)-1));
+ value >>= field->bits;
+ }
+}
+
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s regdef-file [reg value ...]\n", name);
+ exit(1);
+}
+
+
+int main(int argc,char **argv)
+{
+ int i;
+
+ if (argc < 2 || (argc & 1))
+ usage(*argv);
+ run_cpp_on_file(argv[1]);
+ (void) yyparse();
+ for (i = 2; i != argc; i += 2)
+ print(argv[i], strtoull(argv[i+1], NULL, 0));
+ return 0;
+
+}
Added: developers/werner/greg/greg.h
===================================================================
--- developers/werner/greg/greg.h (rev 0)
+++ developers/werner/greg/greg.h 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,23 @@
+/*
+ * greg.h - Generalized register processor
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef GREG_H
+#define GREG_H
+
+int yyparse(void);
+
+void __attribute__((noreturn)) yyerrorf(const char *fmt,...)
+ __attribute__((format(printf,1,2)));
+void __attribute__((noreturn)) yyerror(const char *s);
+
+#endif /* !GREG_H */
Added: developers/werner/greg/lang.l
===================================================================
--- developers/werner/greg/lang.l (rev 0)
+++ developers/werner/greg/lang.l 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,115 @@
+%{
+/*
+ * lang.l - Input language of the generalized register processor
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "y.tab.h"
+
+#include "greg.h"
+
+
+static int lineno = 1;
+static int col0 = 1; /* token starts in the first column */
+
+
+static char *unique(const char *s)
+{
+ static struct node {
+ char *s;
+ struct node *left, *right;
+ } *root = NULL;
+ struct node **n = &root;
+ int cmp;
+
+ while (*n) {
+ cmp = strcmp((*n)->s, s);
+ if (!cmp)
+ return (*n)->s;
+ n = cmp < 0 ? &(*n)->left : &(*n)->right;
+ }
+ *n = malloc(sizeof(struct node));
+ if (!*n) {
+ perror("malloc");
+ exit(1);
+ }
+ (*n)->s = strdup(s);
+ if (!(*n)->s) {
+ perror("strdup");
+ exit(1);
+ }
+ (*n)->left = (*n)->right = NULL;
+ return (*n)->s;
+}
+
+%}
+
+%%
+
+"%"[0-9]+ { yylval.num = strtoul(yytext+1, NULL, 10);
+ col0 = 0;
+ return TOK_BITS; }
+
+_ return '_';
+
+[A-Za-z0-9_]+ { int token = col0 ? TOK_REG : TOK_ID;
+ col0 = 0;
+ yylval.s = unique(yytext);
+ return token; }
+
+\"[^\"\n\t]*\" { yylval.s = strdup(yytext+1);
+ if (!yylval.s) {
+ perror("strdup");
+ exit(1);
+ }
+ *strrchr(yylval.s,'"') = 0;
+ return STRING; }
+
+[\t ]* col0 = 0;
+
+((;|"//")[^\n]*)?\n { col0 = 1;
+ lineno++; }
+
+^#\ [0-9]+\ \"[^"]*\"(\ [0-9]+)*\n {
+ lineno = strtol(yytext+2, NULL, 0);
+ col0 = 1; }
+
+
+. { col0 = 0;
+ return *yytext; }
+
+
+%%
+
+
+void __attribute__((noreturn)) yyerrorf(const char *fmt,...)
+{
+ va_list ap;
+
+ //if (!isatty(fileno(yyin)))
+ fprintf(stderr,"%d: ", lineno);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, " near \"%s\"\n", yytext);
+ exit(1);
+}
+
+
+void __attribute__((noreturn)) yyerror(const char *s)
+{
+ yyerrorf("%s", s);
+}
Added: developers/werner/greg/lang.y
===================================================================
--- developers/werner/greg/lang.y (rev 0)
+++ developers/werner/greg/lang.y 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,261 @@
+%{
+/*
+ * lang.y - Input language of the generalized register processor
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "reg.h"
+#include "greg.h"
+
+
+struct reg *regs = NULL;
+
+static int bits = 8; /* bits per register */
+static int bit; /* current bit */
+
+static struct reg *reg; /* current register */
+static struct field *field; /* current field */
+static struct value_list *list; /* current value list slot */
+
+
+#define alloc_type(t) ((t *) alloc(sizeof(t)))
+
+
+static void *alloc(size_t size)
+{
+ void *tmp = malloc(size);
+
+ if (tmp)
+ return tmp;
+ perror("malloc");
+ exit(1);
+}
+
+
+static int number(char *s)
+{
+ char *end;
+ int tmp;
+
+ tmp = strtol(s, &end, 0);
+ if (*end || tmp < 0)
+ yyerrorf("bad number \"%s\"", s);
+ return tmp;
+}
+
+
+static void add_field(const char *name, int size, const char *comment)
+{
+ struct field *tmp = alloc_type(struct field);
+ const struct field *f;
+
+ if (name)
+ for (f = reg->fields; f; f= f->next)
+ if (f->name == name)
+ yyerrorf("duplicate field name \"%s\"", name);
+ if (bit)
+ field->next = tmp;
+ else
+ reg->fields = tmp;
+ field = tmp;
+ field->name = name;
+ field->comment = comment;
+ field->bits = size;
+ field->next = NULL;
+ bit += size;
+ if (bit > bits)
+ yyerrorf("too many bits (%d > %d)", bit, bits);
+}
+
+
+static void add_value(const char *name, const char *comment)
+{
+ const struct value_list *l;
+
+ if (name)
+ for (l = field->value.u.list; l != list; l++)
+ if (l->name == name)
+ yyerrorf("duplicate value name \"%s\"", name);
+ list->name = name;
+ list->comment = comment;
+ list++;
+}
+
+
+%}
+
+%union {
+ unsigned num;
+ char *s;
+};
+
+
+%token <num> TOK_BITS
+%token <s> TOK_REG TOK_ID STRING
+
+%type <s> opt_string opt_id
+
+%%
+
+all:
+ | all item
+ ;
+
+item:
+ TOK_BITS
+ {
+ bits = $1;
+ }
+ | register
+ ;
+
+register:
+ TOK_REG TOK_ID opt_string
+ {
+ struct reg **next;
+
+ for (next = ®s; *next; next = &(*next)->next) {
+ if ((*next)->id == $1)
+ yyerrorf(
+ "duplicate register ID \"%s\"", $1);
+ if ((*next)->name == $2)
+ yyerrorf(
+ "duplicate register name \"%s\"",
+ $2);
+ }
+ *next = reg = alloc_type(struct reg);
+ reg->id = $1;
+ reg->name = $2;
+ reg->comment = $3;
+ reg->bits = bits;
+ reg->fields = NULL;
+ reg->next = NULL;
+ bit = 0;
+ }
+ fields
+ {
+ if (bit && bit < bits)
+ yyerrorf("not enough bits (%d < %d)",
+ bit, bits);
+ reg++;
+ }
+ ;
+
+fields:
+ | fields field
+ ;
+
+field:
+ '_'
+ {
+ add_field(NULL, 1, NULL);
+ }
+ | '_' '[' TOK_ID ']'
+ {
+ add_field(NULL, number($3), NULL);
+ }
+ | TOK_ID opt_string
+ {
+ add_field($1, 1, $2);
+ }
+ opt_values
+ | TOK_ID '[' TOK_ID ']' opt_string
+ {
+ add_field($1, number($3), $5);
+ }
+ opt_values
+ ;
+
+opt_values:
+ {
+ field->value.type = vt_none;
+ }
+ | '{'
+ {
+ field->value.type = vt_list;
+ field->value.u.list = list =
+ alloc(sizeof(*list)*(1 << field->bits));
+ }
+ values '}'
+ {
+ int want = 1 << field->bits;
+
+ if (list != field->value.u.list+want)
+ yyerrorf("not enough values (%d < %d)",
+ (int) (list-field->value.u.list), want);
+ }
+ | '<' TOK_ID '+' TOK_ID '*' opt_id '>'
+ {
+ field->value.type = vt_formula;
+ field->value.u.formula.b = number($2);
+ field->value.u.formula.a = number($4);
+ field->value.u.formula.unit = $6;
+ }
+ ;
+
+opt_id:
+ {
+ $$ = NULL;
+ }
+ | TOK_ID
+ {
+ $$ = $1;
+ }
+ ;
+
+values:
+ | values
+ {
+ int want = 1 << field->bits;
+
+ if (list == field->value.u.list+want)
+ yyerrorf("too many values (expected %d)", want);
+ }
+ value
+ ;
+
+value:
+ '_'
+ {
+ add_value(NULL, NULL);
+ }
+ | TOK_ID opt_string
+ {
+ add_value($1, $2);
+ }
+ ;
+
+opt_string:
+ {
+ $$ = NULL;
+ }
+ | opt_string STRING
+ {
+ if (!$1)
+ $$ = $2;
+ else {
+ size_t len1 = strlen($1);
+ size_t len2 = strlen($2);
+
+ $$ = alloc(len1+len2+1);
+ memcpy($$, $1, len1);
+ memcpy($$+len1, $2, len2+1);
+ free($1);
+ free($2);
+ }
+ }
+ ;
Added: developers/werner/greg/pcf50633.greg
===================================================================
--- developers/werner/greg/pcf50633.greg (rev 0)
+++ developers/werner/greg/pcf50633.greg 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,735 @@
+/*
+ * NXP PCF50633 register definitions
+ */
+
+
+#define S(s) #s
+
+
+/* ----- Identification ---------------------------------------------------- */
+
+
+00 VERSION "Version ID"
+01 VARIANT "Version ID"
+
+
+/* ----- On/Off Control (OOC) ---------------------------------------------- */
+
+
+0c OOCSHDWN "OOC shutdown"
+ go_stby { no_action transition_to_Standby }
+ _
+ totrst { no_action reset_timeout }
+ coldboot { no_coldboot coldboot }
+ _[4]
+
+0d OOCWAKE "OOC wake-up"
+ onkey_wake
+ exton1_wake
+ exton2_wake
+ exton3_wake
+ rtc_wake
+ _
+ usb_wake
+ adp_wake
+
+#define DEBOUNCE { none 5ms 14ms 62ms }
+
+0e OOCTIM1 "OOC debounce 1"
+ exton1_deb[2] DEBOUNCE
+ exton2_deb[2] DEBOUNCE
+ exton3_deb[2] DEBOUNCE
+ shdwn_deb[2] DEBOUNCE
+
+0f OOCTIM2 "OOC debounce 2 (STANDBY)"
+ onkey_deb[3] "debounce time for nONKEY"
+ { none 5ms 14ms 62ms 200ms 500ms 1000ms 2000ms }
+ actphdel[2] "delay between activation phases"
+ { 5ms 10ms 15ms 20ms }
+ hcrstdel[2] "delay between selected activation phase and host "
+ "controller reset"
+ { 3ms 6ms 13ms 26ms }
+ almon "ambient light monitor"
+
+#define EXTON_MODE { wake_on_falling_edge wake_on_rising_edge \
+ wake_on_falling_8s_timeout_on_rising \
+ wake_on_rising_8s_timeout_on_falling }
+
+10 OOCMODE "OOC mode"
+ exton1_mode[2] "EXTON1 mode selection" EXTON_MODE
+ exton2_mode[2] "EXTON2 mode selection" EXTON_MODE
+ exton3_mode[2] "EXTON3 mode selection" EXTON_MODE
+ onkey_mode[2] "ONKEY mode selection"
+ { wake_on_falling_edge
+ wake_on_falling_8s_timeout_if_low_1s
+ wake_on_falling_8s_timeout_on_rising
+ _ }
+
+11 OOCCTL "OOC control"
+ actphrst[2] "selects activity phase to which host controller "
+ "reset is related"
+ { phase_1 phase_2 phase_3 phase_4 }
+ actclk32on "CLK32K output in Active state"
+ heatbeat { KEEPACT_required_DC_high
+ KEEPACT_requires_toggling }
+ usbbatchk { disabled "Vbat status has no effect on state machine"
+ enabled "Vbat > Vth(batok) to go to Standby state" }
+ _
+ stbclk32on "CLK32K output in Standby state"
+ _
+
+12 OOCSTAT "OOC status"
+ onkey "ONKEY above threshold"
+ exton1 "EXTON1 above threshold"
+ exton2 "EXTON2 above threshold"
+ exton3 "EXTON3 above threshold"
+ bubpres "Vbubat above Vth(bubpres)"
+ sysok "Vsys above Vth(sysok)"
+ batok "Vbat above Vth(batok)"
+ tmpok "die_below_Tth_die"
+
+
+/* ----- Interrupt Controller (INT) ---------------------------------------- */
+
+
+02 INT1 "Interrupt 1"
+ adpins "ADAPTSNS has risen above Vth(adaptpres)"
+ adprem "ADAPTSNS has dropped below Vth(adaptpres)"
+ usbins "USBx has risen above Vth(usbpres)"
+ usbrem "USBx has dropped below Vth(usbpres)"
+ _[2]
+ rtcalarm "RTC alarm time expired"
+ second "RTC periodic one second interrupt"
+
+03 INT2 "Interrupt 2"
+ onkeyr "rising edge on nONKEY"
+ onkeyf "falling edge on nONKEY"
+ exton1r "rising edge on EXTON1"
+ exton1f "falling edge on EXTON1"
+ exton2r "rising edge on EXTON2"
+ exton2f "falling edge on EXTON2"
+ exton3r "rising edge on EXTON3"
+ exton3f "falling edge on EXTON3"
+
+04 INT3 "Interrupt 3"
+ batfull "battery is fully charged"
+ chghalt "charger has entered HALT mode"
+ thlimon "charger has activated thermal-loop current limiting "
+ "in the USB-to-SYS path"
+ thlimoff "charger has deactivated thermal-loop current "
+ "limiting in the USB-to-SYS path"
+ usblimon "charger has activated USB current limiting "
+ "in the USB-to-SYS path"
+ usblimoff "charger has deactivated USB current limiting "
+ "in the USB-to-SYS path"
+ adcrdy "ADC conversion completed"
+ onkey1s "nONKEY low for at least 1 second"
+
+05 INT4 "Interrupt 4"
+ lowsys "SYS voltage fallen below Vth(sysok)"
+ lowbat "BAT voltage fallen below Vth(batok)"
+ hightmp "Tth(die) exceeded"
+ autopwrfail "AUTO output voltage below 90% of target"
+ dwn1pwrfail "DOWN1 output voltage below 90% of target"
+ dwn2pwrfail "DOWN2 output voltage below 90% of target"
+ ledpwrfail "LED output current below 90% of target"
+ ledovp "overvoltage detected at output of LED converter"
+
+06 INT5 "Interrupt 5"
+ ldo1pwrfail "LDO1 output voltage below 90% of target"
+ ldo2pwrfail "LDO2 output voltage below 90% of target"
+ ldo3pwrfail "LDO3 output voltage below 90% of target"
+ ldo4pwrfail "LDO4 output voltage below 90% of target"
+ ldo5pwrfail "LDO5 output voltage below 90% of target"
+ ldo6pwrfail "LDO6 output voltage below 90% of target"
+ hcldopwrfail "HCLDO output voltage below 90% of target"
+ hcldoovl "overload (Io > 350mA) detected in HCLDO regulator"
+
+07 INT1MASK "Interrupt mask 1"
+ adpinsm
+ adpremm
+ usbinsm
+ usbremm
+ _[2]
+ rtcalarmm
+ secondm
+
+08 INT2MASK "Interrupt mask 2"
+ onkeyrm
+ onkeyfm
+ exton1rm
+ exton1fm
+ exton2rm
+ exton2fm
+ exton3rm
+ exton3fm
+
+09 INT3MASK "Interrupt mask 3"
+ batfullm
+ chghaltm
+ thlimonm
+ thlimoffm
+ usblimonm
+ usblimoffm
+ adcrdym
+ onkey1sm
+
+0a INT4MASK "Interrupt mask 4"
+ lowsysm
+ lowbatm
+ hightmpm
+ autopwrfailm
+ dwn1pwrfailm
+ dwn2pwrfailm
+ ledpwrfailm
+ ledovpm
+
+0b INT5MASK "Interrupt mask 5"
+ ldo1pwrfailm
+ ldo2pwrfailm
+ ldo3pwrfailm
+ ldo4pwrfailm
+ ldo5pwrfailm
+ ldo6pwrfailm
+ hcldopwrfailm
+ hcldoovlm
+
+
+/* ----- General Purpose Input/Output (GPIO/GPO) --------------------------- */
+
+
+13 GPIOCTL "GPIO I/O mode control"
+ gpio1dir "GPIO1 I/O mode"
+ { output input }
+ gpio2dir "GPIO2 I/O mode"
+ { output input }
+ gpio3dir "GPIO3 I/O mode"
+ { output input }
+ _[5]
+
+#define GPIOxCFG(x) \
+ GPIO##x##CFG "GPIO" S(x) " signal selection" \
+ gpio##x##sel[3] "GPIO" S(x) " output signal selection" \
+ { fixed_0 _ sysok battery_charging mobile_mode \
+ usbpres actph##x fixed_1 } \
+ gpio##x##pol "GPIO" S(x) " output signal polarity" \
+ { no_inversion inversion } \
+ _[4]
+
+14 GPIOxCFG(1)
+15 GPIOxCFG(2)
+16 GPIOxCFG(3)
+
+17 GPOCFG "GPO signal selection"
+ gposel[3] "GPO output signal selection"
+ { fixed_0 led_nfet sysok clk32k mobile_mode
+ usbpres actph4 fixed_1 }
+ gpopol "GPO output signal polarity"
+ { no_inversion inversion }
+ _[4]
+
+
+/* ----- System Voltage Monitor (SVM) -------------------------------------- */
+
+
+19 SVMCTL "SVM control"
+ svmlow "SYS voltage is lower than Vth(sysok)"
+ svmlvl[3] "Vth(sysok)"
+ { _ 2_80V 2_90V 3_00V 3_10V 3_20V 3_30V 3_40V }
+ svmdisdb "62ms debounce filter"
+ { enabled disabled }
+ _[3]
+
+
+/* ----- Battery Voltage Monitor (BVM) ------------------------------------- */
+
+
+18 BVMCTL "BVM control"
+ bvmlow "BAT voltage is lower than Vth(batok)"
+ bvmlvl[3] "Vth(batok)"
+ { _ 2_80V 2_90V 3_00V 3_10V 3_20V 3_30V 3_40V }
+ bvmdisdb "62ms debounce filter"
+ { enabled disabled }
+ _[3]
+
+
+/* ----- Power Supply Module (PSM) ----------------------------------------- */
+
+
+3b STBYCTL1 "LDO Standby control"
+ ldo1_ena_stb "LDO1 in ON in Standby"
+ _
+ ldo2_ena_stb "LDO2 in ON in Standby"
+ _
+ ldo3_ena_stb "LDO3 in ON in Standby"
+ _
+ ldo4_ena_stb "LDO4 in ON in Standby"
+ _
+
+3c STBYCTL2 "LDO Standby control"
+ ldo5_ena_stb "LDO5 in ON in Standby"
+ _
+ ldo6_ena_stb "LDO6 in ON in Standby"
+ _
+ hcldo_ena_stb "HCLDO in ON in Standby"
+ _
+ memldo_ena_stb "MEMLDO in ON in Standby"
+ _
+
+#define DEBPF(REG, reg) \
+ reg##_debpf[2] S(REG) " power failure debounce time" \
+ { none 1ms 10ms 100ms }
+
+#define STAT(REG, reg) \
+ reg##_pwrok S(REG) " > 90% of target"
+
+3d DEBPF1 "Power fail debounce 1"
+ DEBPF(AUTO, auto)
+ DEBPF(DOWN1, down1)
+ DEBPF(DOWN2, down2)
+ DEBPF(LED, led)
+
+3e DEBPF2 "Power fail debounce 2"
+ DEBPF(LDO1, ldo1)
+ DEBPF(LDO2, ldo2)
+ DEBPF(LDO3, ldo3)
+ DEBPF(LDO4, ldo4)
+
+3f DEBPF3 "Power fail debounce 3"
+ DEBPF(LDO5, ldo5)
+ DEBPF(LDO6, ldo6)
+ DEBPF(HCLDO, hcldo)
+ _[2]
+
+41 DCDCSTAT "DC-to-DC converter status"
+ STAT(AUTO, auto)
+ STAT(DOWN1, down1)
+ STAT(DOWN2, down2)
+ STAT(LED, led)
+ _[4]
+
+42 LDOSTAT "LDO status"
+ STAT(LDO1, ldo1)
+ STAT(LDO2, ldo2)
+ STAT(LDO3, ldo3)
+ STAT(LDO4, ldo4)
+ STAT(LDO5, ldo5)
+ STAT(LDO6, ldo6)
+ STAT(HCLDO, hcldo)
+ hcldo_ovl "HCLDO is in overload mode"
+
+
+/* ----- AUTO, DOWN1 and DOWN2 converters ---------------------------------- */
+
+
+#define DC_OUT(reg) \
+ reg##_out[8] "Vo(prog) [1800mV,3800mV]" \
+ <625+25* mV>
+
+#define ENA(reg) \
+ reg##_on { off on } \
+ reg##_p1c { off on_gpio1 "ON when GPIO1 = 1" } \
+ reg##_p2c { off on_gpio2 "ON when GPIO2 = 1" } \
+ reg##_p3c { off on_gpio3 "ON when GPIO3 = 1" } \
+ reg##_ena_act[2] "selects activation phase" \
+ { actph1 actph2 actph3 actph4 } \
+ _[2]
+
+#define MXC(reg) \
+ reg##_maxc[6] "Ii(max)" \
+ <0+40* mA> \
+ reg##_maxcmod "current limit mode" \
+ { start_up always } \
+ _
+
+#define DOWNxCTL(x) \
+ down##x##pwmonly { pfm_pwm "automatic PFM-PWM selection" \
+ pwm "converter operates in PWM mode" } \
+ down##x##_dvmstep[4] \
+ "DVM step time, 32768 Hz" \
+ <0+30* us> \
+ _[3]
+
+#define LDO_OUT(reg) \
+ reg##_out[5] "Vo(prog)" \
+ <900+100* mV> \
+ reg##_swmod { linear_reg switch } \
+ _[2]
+
+
+1a AUTOOUT "AUTO output voltage select (STANDBY)"
+ DC_OUT(auto)
+
+1b AUTOENA "AUTO output enable (STANDBY)"
+ ENA(auto)
+
+1c AUTOCTL "AUTO control register (STANDBY)"
+ autopwmonly { pfm_pwm "automatic PFM-PWM selection"
+ pwm "converter operates in PWM mode" }
+ auto_mod { auto_up_down down_only }
+ _[6]
+
+1d AUTOMXC "AUTO maximum current (STANDBY)"
+ MXC(auto)
+
+1e DOWN1OUT "DOWN1 output voltage select (STANDBY)"
+ DC_OUT(down1)
+
+1f DOWN1ENA "DOWN1 output enable (STANDBY)"
+ ENA(down1)
+
+20 DOWN1CTL "DOWN1 control (STANDBY)"
+ DOWNxCTL(1)
+
+21 DOWN1MXC "DOWN1 maximum current (STANDBY)"
+ MXC(down1)
+
+22 DOWN2OUT "DOWN2 output voltage select (STANDBY)"
+ DC_OUT(down2)
+
+23 DOWN2ENA "DOWN2 output enable (STANDBY)"
+ ENA(down2)
+
+24 DOWN2CTL "DOWN2 control (STANDBY)"
+ DOWNxCTL(2)
+
+25 DOWN2MXC "DOWN2 maximum current (STANDBY)"
+ MXC(down2)
+
+26 MEMLDOOUT "MEMLDO output voltage select (STANDBY)"
+ LDO_OUT(memldo)
+
+27 MEMLDOENA "MEMLDO output enable (STANDBY)"
+ ENA(memldo)
+
+84 DCDCPFM "DCDC force PFM control (NOPOWER)"
+ autopfm "force AUTO temporarily to PFM mode"
+ down1pfm "force DOWN1 temporarily to PFM mode"
+ down2pfm "force DOWN2 temporarily to PFM mode"
+ _[5]
+
+
+/* ----- LED boost converter & Ambient Light Monitor (ALM) ----------------- */
+
+
+28 LEDOUT "LED output voltage select (STANDBY)"
+ led_out[6] "Iled = Vledfb/Rsense"
+ // x000 x001 x010 x011 x100 x101 x110 x111
+ { _ 2mV _ 10mV _ _ _ _ // 000x
+ 27mV _ 37mV _ _ _ 56mV _ // 001x
+ _ _ 81mV _ _ _ 113mV _ // 010x
+ _ _ 149mV _ _ _ 196mV _ // 011x
+ _ _ 250mV _ _ _ 318mV _ // 100x
+ _ _ 401mV _ _ _ 501mV _ // 101x
+ _ _ 626mV _ _ _ 778mV _ // 110x
+ _ _ 961mV _ _ _ _ 1250mV } // 111x
+ _[2]
+// TODO: complete the table
+// TODO: find a way to programatically generate tables
+// maybe do it like tcsim does, { code }
+
+29 LEDENA "LED output enable (STANDBY)"
+ ENA(led)
+
+2a LEDCTL "LED control (STANDBY)"
+ led_ovpon "overvoltage protection"
+ led_ovprs "reset overvoltage protection"
+ led_ocp "OCP limit"
+ { 1000mA 500mA }
+ _[5]
+
+2b LEDDIM "LED ramp control (STANDBY)"
+ led_dimstep[8] "tdimstep=16*led_dimstep/32768s"
+ <0+488* us>
+
+4f ALMGAIN "Ambient lighting gain factor (STANDBY)"
+ alm_gain[5] "ambient light processing gain factor"
+ _[3]
+
+50 ALMDATA "Ambient light intensity data (STANDBY)"
+ alm_data[8]
+
+
+/* ----- Linear regulators ------------------------------------------------- */
+
+
+#define LDOxOUT(LDO, ldo) \
+ LDO##OUT S(LDO) " output voltage select (STANDBY)" \
+ LDO_OUT(reg)
+
+#define LDOxENA(LDO, ldo) \
+ LDO##ENA S(LDO) " output enable (STANDBY)" \
+ ENA(ldo)
+
+
+2d LDOxOUT(LDO1, ldo1)
+2e LDOxENA(LDO1, ldo1)
+
+2f LDOxOUT(LDO2, ldo2)
+30 LDOxENA(LDO2, ldo2)
+
+31 LDOxOUT(LDO3, ldo3)
+32 LDOxENA(LDO3, ldo3)
+
+33 LDOxOUT(LDO4, ldo4)
+34 LDOxENA(LDO4, ldo4)
+
+35 LDOxOUT(LDO5, ldo5)
+36 LDOxENA(LDO5, ldo5)
+
+37 LDOxOUT(LDO6, ldo6)
+38 LDOxENA(LDO6, ldo6)
+
+39 LDOxOUT(HCLDO, hcldo)
+3a LDOxENA(HCLDO, hcldo)
+
+40 HCLDOOVL "HCLDO overload protection"
+ hcldo_debovl[2] "overload detecton debounce time"
+ { none 1ms 10ms 100ms }
+ _[6]
+
+
+/* ----- Main Battery Charger (MBC) ---------------------------------------- */
+
+
+43 MBCC1 "MBC charger control 1"
+ chgena "charger enabled"
+ autostop "stop charging when current falls below cutoffcur"
+ autores "resume charging then Vbat < Vth(RES), 96% of vmax"
+ resume "resume if in Battery Full"
+ restart "restart if in Halt"
+ prewdtime "maximum charging time during Precharge phase"
+ { 30min 60min }
+ wdtime[2] "maximum charging time after Precharge phase"
+ { 1h 2h 4h 6h }
+
+44 MBCC2 "MBC charger control 2"
+ vbatcond[2] { 2_7V 2_85V 3_0V 3_15V }
+ vmax[4] "Vbat(float)prog"
+ <4000+20* mV>
+ _
+ vresdebtime "debounce time for Vth(RES)"
+ { 32s 64s }
+
+45 MBCC3 "MBC charger control 3"
+ prechgcur[8] "pre-charge current level, N/255*Ich(ref)"
+
+46 MBCC4 "MBC charger control 4"
+ fstchgcur1[8] "fast charge current level in adapter Fast Charge "
+ "phase, N/255*Ich(ref)"
+
+47 MBCC5 "MBC charger control 5"
+ fstchgcur2[8] "fast charge current level in USB Fast Charge "
+ "phase, N/255*Ich(ref)"
+
+48 MBCC6 "MBC charger control 6"
+ cutoffcur[5] "cutoff current level (full in CV), 1/32*Ichg"
+ _[3]
+
+49 MBCC7 "MBC charger control 7"
+ usbdevstat[2] "USB device status setting (STANDBY)"
+ { 100mA 500mA 1000mA suspend }
+ batttempena "battery temperature is measured and impacts the "
+ "MBC state machine"
+ _[3]
+ batsysimax[2] "maximum BAT-SYS current when ideal diode is conducting"
+ { 1_6A 1_8A 2_0A 2_2A }
+
+4a MBCC8 "MBC charger control 8"
+ ntclvt[4] "NTC voltage level for battery high temperature "
+ "threshold"
+ <600+50* mV>
+ usbenasus "USB-SYS switch enabled in USB suspend, "
+ "ideal diode disabled"
+ _[3]
+
+4b MBCS1 "MBC charger status 1"
+ usbpres "Vusb > Vth(usbpres)"
+ usbok "Vusb > Vbat+dVusbok"
+ adaptpres "Vadaptsns > Vth(adaptpres)"
+ adaptok "Vsys > Vbat+dVadaptok"
+ tbatstat[2] "battery temperature status indication"
+ { within_window above_window below_window undefined }
+ prewdtexp "watchdog timer expired during pre-charging"
+ wdtexp "watchdog timer expired after pre-charging"
+
+4c MBCS2 "MBC charger status 2"
+ mbcmod[4] "main MBC operating modes and charge phases"
+ { play_only usb_precharge usb_precharge_wait
+ usb_fast_charge usb_fast_charge_wait usb_suspend
+ adapter_precharge adapter_precharge_wait
+ adapter_fast_charge adapter_fast_charge_wait
+ battery_full halt _ _ _ _ }
+ chgstat[2] "charger connection status"
+ { no_charger adapter usb adapter_and_usb }
+ resstat "charging has resumed automatically"
+ _
+
+4d MBCS3 "MBC charger status 3"
+ usblim_play "USB current limiting in USB-to-SYS path"
+ usblim_chg "USB current limiting in USB-to-BAT path"
+ tlim_play "temperature limiting in USB-to-SYS path"
+ tlim_chg "temperature limiting in USB-to-BAT or SYS-BAT path"
+ ilim "battery charge current > cutoffcur level"
+ vlim "battery voltage equals vmax level"
+ vbatstat "battery voltage > Vbatcond"
+ vres "battery voltage > Vth(RES)"
+
+
+/* ----- Backup Battery Charger (BBC) -------------------------------------- */
+
+
+4e BBCCTL "Backup battery charger control"
+ bbce "enable backup battery charger (STANDBY)"
+ bbcr "bypass output resistor"
+ bbcc[2] "backup battery charge current, Ich(BUBAT)"
+ { 50uA 100uA 200uA 400uA }
+ bbcv "limiting voltage for backup battery charger Vlim(BUBAT)"
+ { 2_5V 3_0V }
+ _[3]
+
+
+/* ----- 10-bit Analog-to-Digital Converter (ADC) -------------------------- */
+
+
+54 ADCC1 "A/D converter control 1"
+ adcstart "ADC conversion start command"
+ adcres "ADC resolution"
+ { 10bit 8bit }
+ adc_av[2] "measurement averaging"
+ { none 4_samples 8_samples 16_samples }
+ adcinmux[4] "ADC input selection"
+ { batsns_r "BATSNS via resistive divider"
+ batsns_sub "BATSNS via subtractor"
+ adcin2_r "ADCIN2 via resistive divider"
+ adcin2_sub "ADCIN2 via subtractor"
+ _
+ _
+ battemp "BATTEMP"
+ adcin1 "ADCIN1"
+ _ _ _ _ _ _ _ _ }
+
+53 ADCC2 "A/C converter control 2"
+ adcratioen[2] "ratiometric measurement"
+ { none "no ratiometric mode measurement"
+ battemp "BATTEMP only"
+ adcin1 "ADCIN1 only"
+ battemp_adcin "BATTEMP and ADCIN1" }
+ adcratioset "ratiometric settling time"
+ { 10us 100us }
+ _[5]
+
+52 ADCC3 "A/C converter control 3"
+ accswen "enable biasing for ratiometric measurement on ADCIN1"
+ _
+ ntcswen "enable biasing for ratiometric measurement on BATTEMP"
+ _
+ adcdivsel "resistive divider type"
+ { by_3 by_2 }
+ _[3]
+
+55 ADCS1 "A/D converter status 1"
+ adcdat1h[8] "8 most significant bits of the (first) ADC result"
+
+56 ADCS2 "A/D converter status 2"
+ adcdat2h[8] "8 most significant bits of the second ADC result"
+
+57 ADCS3 "A/D converter status 3"
+ adcdat1l[2] "2 least significant bits of the (first) ADC result"
+ adcdat2l[2] "2 least significant bits of the second ADC result"
+ adcrefmux[3] "ADC reference selection"
+ { ntcsw accws 2_0V visa
+ _ _ _ 2_0V_again }
+ adcrdy "ADC conversion is completed"
+
+
+/* ----- Real-time clock (RTC) --------------------------------------------- */
+
+
+#define WEEKDAYS { sun mon tue wed thu fri sat _ }
+
+#define MONTHS \
+ { _ jan feb mar apr may jun jul \
+ aug sep _ _ _ _ _ _ \
+ oct nov dec _ _ _ _ _ \
+ _ _ _ _ _ _ _ _ }
+
+
+59 RTCSC "RTC second value"
+ sec[7] "current seconds, BCD"
+ _
+
+5a RTCMN "RTC minute value"
+ min[7] "current minutes, BCD"
+ _
+
+5b RTCHR "RTC hour value"
+ hour[6] "current hours, BCD"
+ _[2]
+
+5c RTCWD "RTC day-of-week value"
+ wkday[3] "current day-of-week"
+ WEEKDAYS
+ _[5]
+
+5d RTCDT "RTC day value"
+ day[5] "current day value, BCD, 01-based"
+ _[3]
+
+5e RTCMT "RTC month value"
+ month[5] "current month value"
+ MONTHS
+ _[3]
+
+5f RTCYR "RTC year value"
+ year[8] "current year, BCD"
+
+60 RTCSCA "RTC second alarm value"
+ seca[7] "alarm seconds, BCD"
+ _
+
+61 RTCMNA "RTC minute alarm value"
+ mina[7] "alarm minutes, BCD"
+ _
+
+62 RTCHRA "RTC hour alarm value"
+ houra[6] "alarm hours, BCD"
+ _[2]
+
+63 RTCWDA "RTC weekday alarm value"
+ wkdaya[3] "alarm day-of-week"
+ WEEKDAYS
+ _[5]
+
+64 RTCDTA "RTC day alarm value"
+ daya[5] "alarm day value, BCD, 01-based"
+ _[3]
+
+65 RTCMTA "RTC month alarm value"
+ montha[5] "alarm month value"
+ MONTHS
+ _[3]
+
+66 RTCYRA "RTC year alarm value"
+ yeara[8] "alarm year, BCD"
+
+
+/* ----- General Purpose Memory (GPM) -------------------------------------- */
+
+
+#define MEMBYTE(n) \
+ MEMBYTE##n "General purpose memory byte " S(n) \
+ membyte##n[8]
+
+
+67 MEMBYTE(0)
+68 MEMBYTE(1)
+69 MEMBYTE(2)
+6a MEMBYTE(3)
+6b MEMBYTE(4)
+6c MEMBYTE(5)
+6d MEMBYTE(6)
+6e MEMBYTE(7)
+
+
+/* ------------------------------------------------------------------------- */
Added: developers/werner/greg/reg.h
===================================================================
--- developers/werner/greg/reg.h (rev 0)
+++ developers/werner/greg/reg.h 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,55 @@
+/*
+ * lang.y - Input language of the generalized register pretty-printer
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef REG_H
+#define REG_H
+
+
+struct reg {
+ const char *id; /* technical register ID */
+ const char *name; /* human-readable register name */
+ const char *comment; /* description or NULL */
+ int bits; /* register width in bits */
+ struct field *fields; /* list of fields, always non-NULL */
+ struct reg *next; /* next register */
+};
+
+struct value {
+ enum { vt_none, vt_list, vt_formula } type;
+ union {
+ struct value_list {
+ const char *name;
+ const char *comment;
+ } *list;
+ struct {
+ int a; /* aX+b */
+ int b;
+ const char *unit; /* unit name, may be NULL */
+ } formula;
+ } u;
+};
+
+struct field {
+ const char *name; /* human-readable field name */
+ const char *comment; /* description or NULL */
+ int bits; /* field size in bits */
+ struct value value;
+ struct field *next; /* next field */
+};
+
+
+extern struct reg *regs;
+
+
+#endif /* !REG_H */
Added: developers/werner/greg/tests/Common
===================================================================
--- developers/werner/greg/tests/Common (rev 0)
+++ developers/werner/greg/tests/Common 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+
+fail()
+{
+ echo FAILED "($SCRIPT)" 1>&2
+ cat _out 1>&2
+ exit 1
+}
+
+
+process()
+{
+ echo -n "$1: " 1>&2
+ shift
+ ../greg - "$@" >_out 2>&1
+}
+
+
+greg()
+{
+ process "$@" || fail
+}
+
+
+greg_fail()
+{
+ process "$@" && fail
+}
+
+
+expect()
+{
+ if ! diff -u - _out >_tmp; then
+ echo FAILED "($SCRIPT)" 1>&2
+ cat _tmp
+ exit
+ fi
+ rm -f _out _tmp
+ echo PASSED 1>&2
+ passed=`expr ${passed:-0} + 1`
+}
Added: developers/werner/greg/tests/Makefile
===================================================================
--- developers/werner/greg/tests/Makefile (rev 0)
+++ developers/werner/greg/tests/Makefile 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,11 @@
+.PHONY: tests clean
+
+# Explicitly enumerate the lower case letters to escape localization weirdness.
+
+tests:
+ for n in [abcdefghijklmnopqrstuvwxyz]*; do \
+ SCRIPT=$$n PATH=.:$$PATH . ./$$n; done; \
+ echo "Passed all $$passed tests" 2>&1
+
+clean:
+ rm -f _*
Added: developers/werner/greg/tests/field
===================================================================
--- developers/werner/greg/tests/field (rev 0)
+++ developers/werner/greg/tests/field 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,93 @@
+#!/bin/sh
+. ./Common
+
+# -----------------------------------------------------------------------------
+
+greg "named field without comment" foo 0x12 <<EOF
+foo bar
+ blah[8]
+EOF
+
+expect <<EOF
+foo bar = 0x12
+ blah
+ 0001.0010 (0x12)
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "named field with comment" bar 52 <<EOF
+bar blah
+ foo[8] "field blah"
+EOF
+
+expect <<EOF
+bar blah = 0x34
+ foo -- field blah
+ 0011.0100 (0x34)
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "anonymous field without comment" bar 0x55 <<EOF
+bar foo
+ _[5]
+ bar[3]
+EOF
+
+expect <<EOF
+bar foo = 0x55
+ bar
+ 010 (0x2)
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "anonymous field with comment" foo 0xaa <<EOF
+foo blah
+ bar[5]
+ _[3]
+EOF
+
+expect <<EOF
+foo blah = 0xaa
+ bar
+ 0.1010 (0x0a)
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "fields don't fill register" <<EOF
+foo bar
+ blah[4]
+ _[3]
+EOF
+
+expect <<EOF
+4: not enough bits (7 < 8) near ""
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "fields exceed register" <<EOF
+foo bar
+ _[3]
+ blah[7]
+EOF
+
+expect <<EOF
+4: too many bits (10 > 8) near ""
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "duplicate field name" <<EOF
+bar blah
+ foo
+ _[6]
+ foo
+EOF
+
+expect <<EOF
+5: duplicate field name "foo" near ""
+EOF
Property changes on: developers/werner/greg/tests/field
___________________________________________________________________
Name: svn:executable
+ *
Added: developers/werner/greg/tests/reg
===================================================================
--- developers/werner/greg/tests/reg (rev 0)
+++ developers/werner/greg/tests/reg 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,54 @@
+#!/bin/sh
+. ./Common
+
+# -----------------------------------------------------------------------------
+
+greg "8 bit register, no comment" foo 0x12 <<EOF
+foo bar
+EOF
+
+expect <<EOF
+foo bar = 0x12
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "8 bit register, with comment" bar 52 <<EOF
+bar blah "hello"
+EOF
+
+expect <<EOF
+bar blah = 0x34 -- hello
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "duplicate register ID" <<EOF
+foo bar
+foo blah
+EOF
+
+expect <<EOF
+3: duplicate register ID "foo" near ""
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "duplicate register name" <<EOF
+foo blah
+bar blah
+EOF
+
+expect <<EOF
+3: duplicate register name "blah" near ""
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "duplicate register comment" <<EOF
+foo bar "blah"
+bar foo "blah"
+EOF
+
+expect <<EOF
+EOF
Property changes on: developers/werner/greg/tests/reg
___________________________________________________________________
Name: svn:executable
+ *
Added: developers/werner/greg/tests/value
===================================================================
--- developers/werner/greg/tests/value (rev 0)
+++ developers/werner/greg/tests/value 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,88 @@
+#!/bin/sh
+. ./Common
+
+# -----------------------------------------------------------------------------
+
+greg "named value without comment" foo 2 <<EOF
+foo bar
+ blah[2] { zero one two three }
+ _[6]
+EOF
+
+expect <<EOF
+foo bar = 0x02
+ blah
+ 10 (0x2): two
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "named value with comment" foo 0x40 <<EOF
+foo bar
+ _[6]
+ blah[2] { zero "null" one "eins" two "zwei" three "drei" }
+EOF
+
+expect <<EOF
+foo bar = 0x40
+ blah
+ 01 (0x1): one -- eins
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "anonymus value without comment" foo 3 <<EOF
+foo bar
+ blah[2] { zero one two _ }
+ _[6]
+EOF
+
+expect <<EOF
+foo bar = 0x03
+ blah
+ 11 (0x3): RESERVED
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "anonymus value with comment (error)" foo 0 <<EOF
+foo bar
+ _[5]
+ blah[3] { _ "zero" one two _ _ _ _ _ }
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "not enough values" <<EOF
+foo bar
+ blah[3] { a b c d e f }
+ _[5]
+EOF
+
+expect <<EOF
+2: not enough values (6 < 8) near "}"
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "too many values" <<EOF
+foo bar
+ _[6]
+ blah[2] { 1 2 3 4 5 }
+EOF
+
+expect <<EOF
+3: too many values (expected 4) near "5"
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg_fail "duplicate value name" <<EOF
+bar blah
+ _[6]
+ foo[2] { a b a c }
+EOF
+
+expect <<EOF
+3: duplicate value name "a" near "c"
+EOF
Property changes on: developers/werner/greg/tests/value
___________________________________________________________________
Name: svn:executable
+ *
Added: developers/werner/greg/tests/width
===================================================================
--- developers/werner/greg/tests/width (rev 0)
+++ developers/werner/greg/tests/width 2008-06-26 05:01:10 UTC (rev 4502)
@@ -0,0 +1,68 @@
+#!/bin/sh
+. ./Common
+
+# -----------------------------------------------------------------------------
+
+greg "4 bit register" foo 0x8 <<EOF
+%4
+foo bar
+EOF
+
+expect <<EOF
+foo bar = 0x8
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "5 bit register" foo 8 <<EOF
+%5
+foo bar
+EOF
+
+expect <<EOF
+foo bar = 0x08
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "8 bit register" foo 9 <<EOF
+%8
+foo bar
+EOF
+
+expect <<EOF
+foo bar = 0x09
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "16 bit register" foo 0x8765 <<EOF
+%16
+foo foo
+EOF
+
+expect <<EOF
+foo foo = 0x8765
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "32 bit register" bar 0x87654321 <<EOF
+%32
+bar bar
+EOF
+
+expect <<EOF
+bar bar = 0x87654321
+EOF
+
+# -----------------------------------------------------------------------------
+
+greg "64 bit register" foo 0x123456789abcdef0 <<EOF
+%64
+foo bar
+EOF
+
+expect <<EOF
+foo bar = 0x123456789abcdef0
+EOF
Property changes on: developers/werner/greg/tests/width
___________________________________________________________________
Name: svn:executable
+ *
More information about the commitlog
mailing list