From 47cff2e833604ecf7e8f2742911efb444e2b912e Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Thu, 2 Jun 2022 16:51:55 +0000 Subject: [PATCH 01/58] auth(8): bugs have been squashed --- sys/man/8/auth | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/man/8/auth b/sys/man/8/auth index 1d7eca1cf..e6c3c343d 100644 --- a/sys/man/8/auth +++ b/sys/man/8/auth @@ -299,5 +299,3 @@ in .IR authsrv (2), .IR keyfs (4), .IR securenet (8) -.SH BUGS -Only CPU kernels permit changing userid. From 761bf6c3477b2bef675c20aad954acae02b923ed Mon Sep 17 00:00:00 2001 From: Amavect <amavect@gmail.com> Date: Sun, 22 May 2022 22:38:11 +0000 Subject: [PATCH 02/58] shorten strchr and runestrchr --- sys/src/libc/port/runestrchr.c | 17 +++++++---------- sys/src/libc/port/strchr.c | 17 +++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/sys/src/libc/port/runestrchr.c b/sys/src/libc/port/runestrchr.c index af7fc4e88..e4c757dff 100644 --- a/sys/src/libc/port/runestrchr.c +++ b/sys/src/libc/port/runestrchr.c @@ -4,17 +4,14 @@ Rune* runestrchr(Rune *s, Rune c) { - Rune c0 = c; - Rune c1; + Rune r; - if(c == 0) { + if(c == 0) while(*s++) ; - return s-1; - } - - while(c1 = *s++) - if(c1 == c0) - return s-1; - return 0; + else + while((r = *s++) != c) + if(r == 0) + return 0; + return s-1; } diff --git a/sys/src/libc/port/strchr.c b/sys/src/libc/port/strchr.c index 1e9aab597..72a8f1627 100644 --- a/sys/src/libc/port/strchr.c +++ b/sys/src/libc/port/strchr.c @@ -4,17 +4,14 @@ char* strchr(char *s, int c) { - char c0 = c; - char c1; + char r; - if(c == 0) { + if(c == 0) while(*s++) ; - return s-1; - } - - while(c1 = *s++) - if(c1 == c0) - return s-1; - return 0; + else + while((r = *s++) != c) + if(r == 0) + return 0; + return s-1; } From 07e162091149adcd7b8ed39d97e07018159ffda0 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 4 Jun 2022 01:56:01 +0000 Subject: [PATCH 03/58] patch: implement a new, simpler patch program to replace ape/patch ape/patch is a giant, ugly ball of code from almost 25 years ago, which has not and will likely never been updated or maintained. the world has since settled on unified diffs, and we just need a simple program that can parse and apply them. --- sys/src/cmd/patch.c | 611 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 sys/src/cmd/patch.c diff --git a/sys/src/cmd/patch.c b/sys/src/cmd/patch.c new file mode 100644 index 000000000..3da0674ff --- /dev/null +++ b/sys/src/cmd/patch.c @@ -0,0 +1,611 @@ +#include <u.h> +#include <libc.h> +#include <ctype.h> +#include <bio.h> + +typedef struct Patch Patch; +typedef struct Hunk Hunk; +typedef struct Fbuf Fbuf; + +struct Patch { + char *name; + Hunk *hunk; + usize nhunk; +}; + +struct Hunk { + int lnum; + + char *oldpath; + int oldln; + int oldcnt; + int oldlen; + int oldsz; + char *old; + + char *newpath; + int newln; + int newcnt; + int newlen; + int newsz; + char *new; +}; + +struct Fbuf { + int *lines; + int nlines; + int lastln; + char *buf; + int len; +}; + +int strip; +int reverse; +void (*addnew)(Hunk*, char*); +void (*addold)(Hunk*, char*); + +char* +readline(Biobuf *f, int *lnum) +{ + char *ln; + + if((ln = Brdstr(f, '\n', 0)) == nil) + return nil; + *lnum += 1; + return ln; +} + +void * +emalloc(ulong n) +{ + void *v; + + v = mallocz(n, 1); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +void * +erealloc(void *v, ulong n) +{ + if(n == 0) + n++; + v = realloc(v, n); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +int +fileheader(char *s, char *pfx, char **name) +{ + int len, n, nnull; + char *e; + + if((strncmp(s, pfx, strlen(pfx))) != 0) + return -1; + for(s += strlen(pfx); *s; s++) + if(!isspace(*s)) + break; + for(e = s; *e; e++) + if(isspace(*e)) + break; + if(s == e) + return -1; + nnull = strlen("/dev/null"); + if((e - s) != nnull || strncmp(s, "/dev/null", nnull) != 0){ + n = strip; + while(s != e && n > 0){ + while(s != e && *s == '/') + s++; + while(s != e && *s != '/') + s++; + n--; + } + while(*s == '/') + s++; + if(*s == '\0') + sysfatal("too many components stripped"); + } + len = (e - s) + 1; + *name = emalloc(len); + strecpy(*name, *name + len, s); + return 0; +} + +int +hunkheader(Hunk *h, char *s, char *oldpath, char *newpath, int lnum) +{ + char *e; + + memset(h, 0, sizeof(*h)); + h->lnum = lnum; + h->oldpath = strdup(oldpath); + h->newpath = strdup(newpath); + h->oldlen = 0; + h->oldsz = 32; + h->old = emalloc(h->oldsz); + h->newlen = 0; + h->newsz = 32; + h->new = emalloc(h->newsz); + if(strncmp(s, "@@ -", 4) != 0) + return -1; + e = s + 4; + h->oldln = strtol(e, &e, 10); + h->oldcnt = 1; + if(*e == ','){ + e++; + h->oldcnt = strtol(e, &e, 10); + } + while(*e == ' ' || *e == '\t') + e++; + if(*e != '+') + return -1; + e++; + h->newln = strtol(e, &e, 10); + if(e == s) + return -1; + h->newcnt = 1; + if(*e == ','){ + e++; + h->newcnt = strtol(e, &e, 10); + } + if(e == s || *e != ' ') + return -1; + if(strncmp(e, " @@", 3) != 0) + return -1; + /* + * empty files have line number 0: keep that, + * otherwise adjust down. + */ + if(h->oldln > 0) + h->oldln--; + if(h->newln > 0) + h->newln--; + if(h->oldln < 0 || h->newln < 0 || h->oldcnt < 0 || h->newcnt < 0) + sysfatal("malformed hunk %s", s); + return 0; +} + +void +addnewfn(Hunk *h, char *ln) +{ + int n; + + ln++; + n = strlen(ln); + while(h->newlen + n >= h->newsz){ + h->newsz *= 2; + h->new = erealloc(h->new, h->newsz); + } + memcpy(h->new + h->newlen, ln, n); + h->newlen += n; +} + +void +addoldfn(Hunk *h, char *ln) +{ + int n; + + ln++; + n = strlen(ln); + while(h->oldlen + n >= h->oldsz){ + h->oldsz *= 2; + h->old = erealloc(h->old, h->oldsz); + } + memcpy(h->old + h->oldlen, ln, n); + h->oldlen += n; +} + +int +addmiss(Hunk *h, char *ln, int *nold, int *nnew) +{ + if(ln == nil) + return 1; + else if(ln[0] != '-' && ln[0] != '+') + return 0; + if(ln[0] == '-'){ + addold(h, ln); + *nold += 1; + }else{ + addnew(h, ln); + *nnew += 1; + } + return 1; +} + +void +addhunk(Patch *p, Hunk *h) +{ + p->hunk = erealloc(p->hunk, ++p->nhunk*sizeof(Hunk)); + p->hunk[p->nhunk-1] = *h; +} + +int +hunkcmp(void *a, void *b) +{ + int c; + + c = strcmp(((Hunk*)a)->oldpath, ((Hunk*)b)->oldpath); + if(c != 0) + return c; + return ((Hunk*)a)->oldln - ((Hunk*)b)->oldln; +} + +Patch* +parse(Biobuf *f, char *name) +{ + char *ln, *old, *new, **oldp, **newp; + int oldcnt, newcnt, lnum; + Patch *p; + Hunk h; + + ln = nil; + lnum = 0; + p = emalloc(sizeof(Patch)); + if(!reverse){ + oldp = &old; + newp = &new; + }else{ + oldp = &new; + newp = &old; + } +comment: + free(ln); + while((ln = readline(f, &lnum)) != nil){ + if(strncmp(ln, "--- ", 4) == 0) + goto patch; + free(ln); + } + if(p->nhunk == 0) + sysfatal("%s: could not find start of patch", name); + goto out; + +patch: + if(fileheader(ln, "--- ", oldp) == -1) + goto comment; + free(ln); + + if((ln = readline(f, &lnum)) == nil) + goto out; + if(fileheader(ln, "+++ ", newp) == -1) + goto comment; + free(ln); + + if((ln = readline(f, &lnum)) == nil) + goto out; +hunk: + oldcnt = 0; + newcnt = 0; + if(hunkheader(&h, ln, old, new, lnum) == -1) + goto comment; + free(ln); + + while(1){ + if((ln = readline(f, &lnum)) == nil){ + if(oldcnt != h.oldcnt || newcnt != h.newcnt) + sysfatal("%s:%d: malformed hunk", name, lnum); + addhunk(p, &h); + break; + } + switch(ln[0]){ + default: + sysfatal("%s:%d: malformed hunk2", name, lnum); + goto out; + case '-': + addold(&h, ln); + oldcnt++; + break; + case '+': + addnew(&h, ln); + newcnt++; + break; + case ' ': + addold(&h, ln); + addnew(&h, ln); + oldcnt++; + newcnt++; + break; + } + free(ln); + if(oldcnt > h.oldcnt || newcnt > h.newcnt) + sysfatal("%s:%d: malformed hunk", name, lnum); + if(oldcnt < h.oldcnt || newcnt < h.newcnt) + continue; + + addhunk(p, &h); + if((ln = readline(f, &lnum)) == nil) + goto out; + if(strncmp(ln, "--- ", 4) == 0) + goto patch; + if(strncmp(ln, "@@ ", 3) == 0) + goto hunk; + goto comment; + } + +out: + qsort(p->hunk, p->nhunk, sizeof(Hunk), hunkcmp); + free(old); + free(new); + free(ln); + return p; +} + +int +rename(int fd, char *name) +{ + Dir st; + char *p; + + nulldir(&st); + if((p = strrchr(name, '/')) == nil) + st.name = name; + else + st.name = p + 1; + return dirfwstat(fd, &st); +} + +int +mkpath(char *path) +{ + char *p, buf[ERRMAX]; + int f; + + if(*path == '\0') + return 0; + for(p = strchr(path+1, '/'); p != nil; p = strchr(p+1, '/')){ + *p = '\0'; + if(access(path, AEXIST) != 0){ + if((f = create(path, OREAD, DMDIR | 0777)) == -1){ + rerrstr(buf, sizeof(buf)); + if(strstr(buf, "exist") == nil) + return -1; + } + close(f); + } + *p = '/'; + } + return 0; +} + +void +blat(char *old, char *new, char *o, usize len) +{ + char *tmp; + int fd; + + if(strcmp(new, "/dev/null") == 0){ + if(len != 0) + sysfatal("diff modifies removed file"); + if(remove(old) == -1) + sysfatal("removeold %s: %r", old); + return; + } + if(mkpath(new) == -1) + sysfatal("mkpath %s: %r", new); + if((tmp = smprint("%s.tmp%d", new, getpid())) == nil) + sysfatal("smprint: %r"); + if((fd = create(tmp, OWRITE, 0666)) == -1) + sysfatal("open %s: %r", tmp); + if(write(fd, o, len) != len) + sysfatal("write %s: %r", tmp); + if(strcmp(old, new) == 0 && remove(old) == -1) + sysfatal("remove %s: %r", old); + if(rename(fd, new) == -1) + sysfatal("create %s: %r", new); + if(close(fd) == -1) + sysfatal("close %s: %r", tmp); + free(tmp); +} + +int +slurp(Fbuf *f, char *path) +{ + int n, i, fd, sz, len, nlines, linesz; + char *buf; + int *lines; + + if((fd = open(path, OREAD)) == -1) + sysfatal("open %s: %r", path); + sz = 8192; + len = 0; + buf = emalloc(sz); + while(1){ + if(len == sz){ + sz *= 2; + buf = erealloc(buf, sz); + } + n = read(fd, buf + len, sz - len); + if(n == 0) + break; + if(n == -1) + sysfatal("read %s: %r", path); + len += n; + } + + nlines = 0; + linesz = 32; + lines = emalloc(linesz*sizeof(int)); + lines[nlines++] = 0; + for(i = 0; i < len; i++){ + if(buf[i] != '\n') + continue; + if(nlines+1 == linesz){ + linesz *= 2; + lines = erealloc(lines, linesz*sizeof(int)); + } + lines[nlines++] = i+1; + } + f->len = len; + f->buf = buf; + f->lines = lines; + f->nlines = nlines; + f->lastln = -1; + return 0; +} + +char* +search(Fbuf *f, Hunk *h, char *fname) +{ + int ln, len, off, fuzz, nfuzz, scanning; + + scanning = 1; + len = h->oldlen; + nfuzz = (f->nlines < 250) ? f->nlines : 250; + for(fuzz = 0; scanning && fuzz <= nfuzz; fuzz++){ + scanning = 0; + ln = h->oldln - fuzz; + if(ln > f->lastln){ + off = f->lines[ln]; + if(off + len > f->len) + continue; + scanning = 1; + if(memcmp(f->buf + off, h->old, h->oldlen) == 0){ + f->lastln = ln; + return f->buf + off; + } + } + ln = h->oldln + fuzz - 1; + if(ln <= f->nlines){ + off = f->lines[ln]; + if(off + len >= f->len) + continue; + scanning = 1; + if(memcmp(f->buf + off, h->old, h->oldlen) == 0){ + f->lastln = ln; + return f->buf + off; + } + } + } + sysfatal("%s:%d: unable to find hunk offset in %s", fname, h->lnum, h->oldpath); + return nil; +} + +char* +append(char *o, int *sz, char *s, char *e) +{ + int n; + + n = (e - s); + o = erealloc(o, *sz + n); + memcpy(o + *sz, s, n); + *sz += n; + return o; +} + +int +apply(Patch *p, char *fname) +{ + char *o, *s, *e, *curfile; + int i, osz; + Hunk *h; + Fbuf f; + + e = nil; + o = nil; + osz = 0; + curfile = nil; + for(i = 0; i < p->nhunk; i++){ + h = &p->hunk[i]; + if(curfile == nil || strcmp(curfile, h->newpath) != 0){ + if(slurp(&f, h->oldpath) == -1) + sysfatal("slurp %s: %r", h->oldpath); + curfile = h->newpath; + e = f.buf; + } + s = e; + e = search(&f, h, fname); + o = append(o, &osz, s, e); + o = append(o, &osz, h->new, h->new + h->newlen); + e += h->oldlen; + if(i+1 == p->nhunk || strcmp(curfile, p->hunk[i+1].newpath) != 0){ + o = append(o, &osz, e, f.buf + f.len); + blat(h->oldpath, h->newpath, o, osz); + if(strcmp(h->newpath, "/dev/null") == 0) + print("%s\n", h->oldpath); + else + print("%s\n", h->newpath); + osz = 0; + } + } + free(o); + return 0; +} + +void +freepatch(Patch *p) +{ + Hunk *h; + int i; + + for(i = 0; i < p->nhunk; i++){ + h = &p->hunk[i]; + free(h->oldpath); + free(h->newpath); + free(h->old); + free(h->new); + } + free(p->hunk); + free(p->name); + free(p); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-R] [-p nstrip] [patch...]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Biobuf *f; + Patch *p; + int i; + + ARGBEGIN{ + case 'p': + strip = atoi(EARGF(usage())); + break; + case 'R': + reverse++; + break; + default: + usage(); + break; + }ARGEND; + + if(reverse){ + addnew = addoldfn; + addold = addnewfn; + }else{ + addnew = addnewfn; + addold = addoldfn; + } + if(argc == 0){ + if((f = Bfdopen(0, OREAD)) == nil) + sysfatal("open stdin: %r"); + if((p = parse(f, "stdin")) == nil) + sysfatal("parse patch: %r"); + if(apply(p, "stdin") == -1) + sysfatal("apply stdin: %r"); + freepatch(p); + Bterm(f); + }else{ + for(i = 0; i < argc; i++){ + if((f = Bopen(argv[i], OREAD)) == nil) + sysfatal("open %s: %r", argv[i]); + if((p = parse(f, argv[i])) == nil) + sysfatal("parse patch: %r"); + if(apply(p, argv[i]) == -1) + sysfatal("apply %s: %r", argv[i]); + freepatch(p); + Bterm(f); + } + } + exits(nil); +} From 9e547f50d19b6f24bc59ccb38dfeb5ea46003907 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 4 Jun 2022 02:12:12 +0000 Subject: [PATCH 04/58] patch(1): add the manpage forgot it in the last commit --- sys/man/1/patch | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 sys/man/1/patch diff --git a/sys/man/1/patch b/sys/man/1/patch new file mode 100644 index 000000000..e3ebb70d1 --- /dev/null +++ b/sys/man/1/patch @@ -0,0 +1,90 @@ +.TH PATCH 1 +.SH NAME +patch \- apply diffs +.SH SYNOPSIS +.B patch +[ +.B -lR +] +[ +.B -p +.I nstrip +] +[ +.B -f +.I maxfuzz +] +[ +.I patch ... +] +.SH DESCRIPTION +.I Patch +scans its input for a sequence of patches, and applies them, printing the list of changed files. +When an applied patch does not match precisely, +.I patch +will scan the input file for matching context, applying the patch up to 250 lines away from +its original location. +If a hunk does not apply, then the file is left untouched. +.PP +The following options are supported: +.TP +.B -R +Reverse direction of the patch. Additions become removals, +and the new and old file names are swapped. +.TP +.BI -p \ nstrip +Remove the prefix containing +.I nstrip +leading slashes from each file path in the diff file. +.SH INPUT FORMAT +A patch begins with a patch header, and is followed by a sequence of one or more hunks. +All lines before a patch header or after the last hunk of a patch are comments, +and are ignored by patch. A patch header is a sequence of 2 lines in the following +format: +.IP +.EX +--- oldfile [trailing text] ++++ newfile [trailing text] +.EE +.PP +A hunk must immediately follow a patch header or another hunk. +It begins with a header line in the following format: +.IP +.EX +@@ -count,addr +count,addr @@ +.EE +.PP +And contains a sequence of lines beginning with a +.LR - , +.LR + , +or space characters. +A +.L - +indicates that the line is to be removed from the old file. +A +.L + +indicates that the line is to be inserted into the new file. +A space indicates that the line is context. +It will be copied unchanged from the old file to the new file. +.PP +If the old file is +.LR /dev/null , +the patch indicates a file creation. +If the new file is +.LR /dev/null , +the patch indicates a file deletion. +In this case, the file printed is the file being removed. +.SH SEE ALSO +.IR diff (1), +.IR git/export (1) +.SH BUGS +.PP +The output of +.B diff -c +is not handled. +.PP +Reject files and backups are not supported. +.PP +All files are processed in memory, limiting the maximum file size to available RAM. + + From 9eb9c9e56064d41f45f2db22a8cc8a1a797f4a53 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 4 Jun 2022 02:13:58 +0000 Subject: [PATCH 05/58] patch(1): remove options that don't exist the summary mentions options that existed during development, but no longer do. --- sys/man/1/patch | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/man/1/patch b/sys/man/1/patch index e3ebb70d1..9178d0c02 100644 --- a/sys/man/1/patch +++ b/sys/man/1/patch @@ -1,20 +1,16 @@ .TH PATCH 1 .SH NAME -patch \- apply diffs +patch \- apply patches .SH SYNOPSIS .B patch [ -.B -lR +.B -R ] [ .B -p .I nstrip ] [ -.B -f -.I maxfuzz -] -[ .I patch ... ] .SH DESCRIPTION From 5d37407e3c98b41f64c20a3d03125d3ea6299a2d Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 4 Jun 2022 02:21:19 +0000 Subject: [PATCH 06/58] diff: avoid empty hunks when there are no changes Currently, diff outputs a file header, even if there are no changes to the file. This is wonky. It means that the header chunks are ambiguous, since not all header chunks are followed by '@@ hunk', and '--- file', '+++ file' lines can be generated from file content. This changes the way that we decide to print the file header, so we only print it when outputting the first hunk on flushchanges. Flushchanges is called once per regular file, at the end of `diffreg`, so we output a hunk header once per file. --- sys/src/cmd/diff/diff.h | 1 - sys/src/cmd/diff/diffio.c | 19 ++++++++----------- sys/src/cmd/diff/diffreg.c | 1 - 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/sys/src/cmd/diff/diff.h b/sys/src/cmd/diff/diff.h index 8aca0439f..e1c8263d6 100644 --- a/sys/src/cmd/diff/diff.h +++ b/sys/src/cmd/diff/diff.h @@ -28,6 +28,5 @@ Biobuf *prepare(int, char *, char *); void panic(int, char *, ...); void check(Biobuf *, Biobuf *); void change(int, int, int, int); -void fileheader(void); void flushchanges(void); diff --git a/sys/src/cmd/diff/diffio.c b/sys/src/cmd/diff/diffio.c index b577b6d2a..1d4d4d6bb 100644 --- a/sys/src/cmd/diff/diffio.c +++ b/sys/src/cmd/diff/diffio.c @@ -329,24 +329,16 @@ changeset(int i) return nchanges; } -void -fileheader(void) -{ - if(mode != 'u') - return; - Bprint(&stdout, "--- %s\n", file1); - Bprint(&stdout, "+++ %s\n", file2); -} - void flushchanges(void) { - int a, b, c, d, at; + int a, b, c, d, at, hdr; int i, j; if(nchanges == 0) return; - + + hdr = 0; for(i=0; i<nchanges; ){ j = changeset(i); a = changes[i].a-Lines; @@ -369,6 +361,11 @@ flushchanges(void) j = nchanges; } if(mode == 'u'){ + if(!hdr){ + Bprint(&stdout, "--- %s\n", file1); + Bprint(&stdout, "+++ %s\n", file2); + hdr = 1; + } Bprint(&stdout, "@@ -%d,%d +%d,%d @@\n", a, b-a+1, c, d-c+1); }else{ Bprint(&stdout, "%s:", file1); diff --git a/sys/src/cmd/diff/diffreg.c b/sys/src/cmd/diff/diffreg.c index f773a4edf..e37ffa7a3 100644 --- a/sys/src/cmd/diff/diffreg.c +++ b/sys/src/cmd/diff/diffreg.c @@ -284,7 +284,6 @@ output(void) m = len[0]; J[0] = 0; J[m+1] = len[1]+1; - fileheader(); if (mode != 'e') { for (i0 = 1; i0 <= m; i0 = i1+1) { while (i0 <= m && J[i0] == J[i0-1]+1) From 926be5e34eb633bc3e22b013705f5474d21aa735 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 4 Jun 2022 23:35:49 +0000 Subject: [PATCH 07/58] git/import: use patch(1) we have a new, pretty patch(1), lets use it. --- sys/src/cmd/git/import | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import index 7ba7d0e48..0cc450bf8 100755 --- a/sys/src/cmd/git/import +++ b/sys/src/cmd/git/import @@ -78,7 +78,7 @@ fn apply @{ rc -c ' echo applying $msg | sed 1q date=`{seconds $date} - if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep ''^patching file'' | sed ''s/^patching file `(.*)''''/\1/''}) + if(! files=`$nl{patch -p1 < $diffpath}) die ''patch failed'' for(f in $files){ if(test -e $f) From d8d433894a706ec65384bd8a18630d18912f0f78 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Sun, 5 Jun 2022 12:29:50 +0000 Subject: [PATCH 08/58] kernel: cleanup unused fields from devpipe We don't need to multiply session path by 2, the definition for NETQID is: Meaning we don't need to save room between session paths for individual Qid paths. This doubles the amount of pipe sessions we can have before a wrap. --- sys/src/9/port/devpipe.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/src/9/port/devpipe.c b/sys/src/9/port/devpipe.c index 60c6edd13..8611681a4 100644 --- a/sys/src/9/port/devpipe.c +++ b/sys/src/9/port/devpipe.c @@ -11,9 +11,7 @@ typedef struct Pipe Pipe; struct Pipe { QLock; - Pipe *next; int ref; - ulong path; Queue *q[2]; int qref[2]; }; @@ -57,6 +55,7 @@ pipeattach(char *spec) { Pipe *p; Chan *c; + ulong path; c = devattach('|', spec); if(waserror()){ @@ -82,10 +81,10 @@ pipeattach(char *spec) poperror(); lock(&pipealloc); - p->path = ++pipealloc.path; + path = ++pipealloc.path; unlock(&pipealloc); - mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); + mkqid(&c->qid, NETQID(path, Qdir), 0, QTDIR); c->aux = p; c->dev = 0; return c; From 207d124dfeb141a7ed9333a3666970752a83db40 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Sun, 5 Jun 2022 18:02:58 +0000 Subject: [PATCH 09/58] ip/dhcpd: properly skip past ipv6 addresses in addrsopt If the first address passed happened to be an ipv6 address we would send a malformed option by never including a ipv4 address. --- sys/src/cmd/ip/dhcpd/dhcpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/src/cmd/ip/dhcpd/dhcpd.c b/sys/src/cmd/ip/dhcpd/dhcpd.c index 93b83c8f8..c5b708aa9 100644 --- a/sys/src/cmd/ip/dhcpd/dhcpd.c +++ b/sys/src/cmd/ip/dhcpd/dhcpd.c @@ -1477,6 +1477,7 @@ addrsopt(Req *rp, int t, uchar **ip, int i) while(i-- > 0){ if (!isv4(*ip)) { op = seprint(op, oe, " skipping %I ", *ip); + ip++; continue; } v6tov4(rp->p, *ip); From df92301d8fc8310fbfdf3de91b97a156ca0504d4 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Sun, 5 Jun 2022 20:56:57 +0000 Subject: [PATCH 10/58] ip/ipconfig: refactor plan9 vendor parsing Unless ip/dhcpd is started with the -6 option, we only receive v4 addresses. If we do see the v6 options we should prefer them but should also make sure we grab the v4 addresses as a fallback. None of the v6 options should overwrite valid overrides given at the command line. Add our custom types to logging. --- sys/src/cmd/ip/ipconfig/dhcp.c | 70 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/sys/src/cmd/ip/ipconfig/dhcp.c b/sys/src/cmd/ip/ipconfig/dhcp.c index 44badcf8a..554a3e1a1 100644 --- a/sys/src/cmd/ip/ipconfig/dhcp.c +++ b/sys/src/cmd/ip/ipconfig/dhcp.c @@ -18,6 +18,7 @@ enum Tulong, Tvec, Tnames, + Tp9addrs, }; typedef struct Option Option; @@ -93,6 +94,7 @@ static Option option[256] = [OBircserver] { "irc", Taddrs }, [OBstserver] { "st", Taddrs }, [OBstdaserver] { "stdar", Taddrs }, +[OBvendorinfo] { "vendorinfo", Tvec }, [ODipaddr] { "ipaddr", Taddr }, [ODlease] { "lease", Tulong }, @@ -109,6 +111,14 @@ static Option option[256] = [ODtftpserver] { "tftp", Tstr }, [ODbootfile] { "bootfile", Tstr }, [ODdnsdomain] { "dnsdomain", Tnames }, + +[OP9authv4] { "p9authv4", Taddrs }, +[OP9fsv4] { "p9fsv4", Taddrs }, +[OP9fs] { "p9fs", Tp9addrs }, +[OP9auth] { "p9auth", Tp9addrs }, +[OP9ipaddr] { "p9ipaddr", Tp9addrs }, +[OP9ipmask] { "p9ipmask", Tp9addrs }, +[OP9ipgw] { "p9ipgw", Tp9addrs }, }; static uchar defrequested[] = { @@ -414,7 +424,7 @@ dhcprecv(void) int i, n, type; ulong lease; char err[ERRMAX]; - uchar buf[8000], vopts[256], taddr[IPaddrlen]; + uchar buf[8000], vopts[256], taddr[IPaddrlen*2]; Bootp *bp; memset(buf, 0, sizeof buf); @@ -544,39 +554,33 @@ dhcprecv(void) /* get plan9-specific options */ n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1); if(n > 0 && parseoptions(vopts, n) == 0){ - if(validip(conf.fs) && Oflag) - n = 1; - else { - n = optgetp9addrs(vopts, OP9fs, conf.fs, 2); - if (n == 0) - n = optgetaddrs(vopts, OP9fsv4, - conf.fs, 2); + if(!(Oflag && validip(conf.fs))){ + n = optgetp9addrs(vopts, OP9fs, taddr, 2); + if(n < 2) + n += optgetaddrs(vopts, OP9fsv4, taddr + (n * IPaddrlen), 2 - n); + memmove(conf.fs, taddr, n * IPaddrlen); } - for(i = 0; i < n; i++) - DEBUG("fs=%I ", conf.fs + i*IPaddrlen); - - if(validip(conf.auth) && Oflag) - n = 1; - else { - n = optgetp9addrs(vopts, OP9auth, conf.auth, 2); - if (n == 0) - n = optgetaddrs(vopts, OP9authv4, - conf.auth, 2); + if(!(Oflag && validip(conf.auth))){ + n = optgetp9addrs(vopts, OP9auth, taddr, 2); + if(n < 2) + n += optgetaddrs(vopts, OP9authv4, taddr + (n * IPaddrlen), 2 - n); + memmove(conf.auth, taddr, n * IPaddrlen); } - for(i = 0; i < n; i++) - DEBUG("auth=%I ", conf.auth + i*IPaddrlen); + DEBUG("fs=(%I %I) auth=(%I %I)", conf.fs, conf.fs + IPaddrlen, conf.auth , conf.auth + IPaddrlen); - n = optgetp9addrs(vopts, OP9ipaddr, taddr, 1); - if (n > 0) - ipmove(conf.laddr, taddr); - n = optgetp9addrs(vopts, OP9ipmask, taddr, 1); - if (n > 0) - ipmove(conf.mask, taddr); - n = optgetp9addrs(vopts, OP9ipgw, taddr, 1); - if (n > 0) - ipmove(conf.gaddr, taddr); - DEBUG("new ipaddr=%I new ipmask=%M new ipgw=%I", - conf.laddr, conf.mask, conf.gaddr); + if(!(Oflag && validip(conf.laddr))) + if(optgetp9addrs(vopts, OP9ipaddr, taddr, 1)) + ipmove(conf.laddr, taddr); + + if(!(Oflag && validip(conf.mask))) + if(optgetp9addrs(vopts, OP9ipmask, taddr, 1)) + ipmove(conf.mask, taddr); + + if(!(Oflag && validip(conf.gaddr))) + if(optgetp9addrs(vopts, OP9ipgw, taddr, 1)) + ipmove(conf.gaddr, taddr); + + DEBUG("p9 opt ipaddr=%I ipmask=%M ipgw=%I", conf.laddr, conf.mask, conf.gaddr); } conf.lease = lease; conf.state = Sbound; @@ -779,8 +783,8 @@ optgetp9addrs(uchar *ap, int op, uchar *ip, int n) slen = strlen(p) + 1; if (parseip(&ip[i*IPaddrlen], p) == -1) fprint(2, "%s: bad address %s\n", argv0, p); - DEBUG("got plan 9 option %d addr %I (%s)", - op, &ip[i*IPaddrlen], p); + DEBUG("got plan 9 option %s addr %I (%s)", + option[op].name, &ip[i*IPaddrlen], p); p += slen; len -= slen; } From f4840cdba548979969cb2ad25b4c6acbc3e63f8c Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 7 Jun 2022 05:25:44 +0000 Subject: [PATCH 11/58] kernel: add devskel for pc and pc64 --- sys/man/3/skel | 35 ++++++ sys/src/9/pc/pc | 1 + sys/src/9/pc64/pc64 | 1 + sys/src/9/port/devskel.c | 237 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 sys/man/3/skel create mode 100644 sys/src/9/port/devskel.c diff --git a/sys/man/3/skel b/sys/man/3/skel new file mode 100644 index 000000000..cc8dfbc17 --- /dev/null +++ b/sys/man/3/skel @@ -0,0 +1,35 @@ +.TH SKEL 3 +.SH NAME +skel \- skeleton builder +.SH SYNOPSIS +.B bind #z/\fIskel\fR +.I dir +.PP +.B bind #zd/\fIskel\fR +.I dir +.PP +.B bind #ze/ +.I dir +.SH DESCRIPTION +.PP +This device serves a single child directory with a single empty child +file. The name of these files is determined by the first walk away +from the root. After which, the hierarchy for that attached session +becomes stable. The +.B d +attach option causes the child file to be an empty directory. The +.B e +attach option presents a completly empty root directory. +.SH EXAMPLES +Skeleton files can be used for constructing arbitrary bind targets. +.EX +.IP +bind -b '#zd/newroot' / +bind '#zd/bin' /newroot +bind '#z/walk' /newroot/bin +bind /bin/walk /newroot/bin/walk +bind /newroot / +walk / +.EE +.SH SOURCE +.B /sys/src/9/port/devskel.c diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 2cacee652..3581fe207 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -18,6 +18,7 @@ dev kprof fs dtracy + skel ether netif bridge netif log diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index bafda3d72..e78a2d47f 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -41,6 +41,7 @@ dev segment vmx dtracy + skel link # devpccard pci diff --git a/sys/src/9/port/devskel.c b/sys/src/9/port/devskel.c new file mode 100644 index 000000000..95e5b6038 --- /dev/null +++ b/sys/src/9/port/devskel.c @@ -0,0 +1,237 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include "netif.h" + +typedef struct Skel Skel; +struct Skel { + int ref; + QLock lk; + char name[KNAMELEN]; + char mode; +}; + +struct +{ + QLock lk; + ulong path; +} skelalloc; + +enum{ + Qroot, + Qdir, + Qskel, +}; + +static Chan* +skelattach(char *spec) +{ + Chan *c; + Skel *f; + uvlong path; + + c = devattach('z', spec); + + f = smalloc(sizeof *f); + if(spec != nil && spec[0] != '\0' && strchr("de", spec[0]) != nil) + f->mode = spec[0]; + else + f->mode = 'f'; + + f->ref = 1; + + qlock(&skelalloc.lk); + path = skelalloc.path++; + qunlock(&skelalloc.lk); + + mkqid(&c->qid, NETQID(path, Qroot), 0, QTDIR); + c->aux = f; + return c; +} + +static int +step(Chan *c, Dir *dp, int direction) +{ + Skel *f; + Qid qid; + ulong perm; + uvlong path; + char *name; + + perm = 0555|DMDIR; + path = NETTYPE(c->qid.path); + f = c->aux; + name = f->name; + + path += direction; + if(!f->name[0] && path != Qroot) + return -1; + + switch(path){ + case Qroot: + mkqid(&qid, Qroot, 0, QTDIR); + name = "#z"; + break; + case Qdir: + mkqid(&qid, Qdir, 0, QTDIR); + break; + case Qskel: + switch(f->mode){ + case 'd': + mkqid(&qid, Qskel, 0, QTDIR); + break; + case 'f': + default: + mkqid(&qid, Qskel, 0, QTFILE); + perm = 0666; + break; + } + break; + default: + return -1; + } + + qid.path = NETQID(NETID(c->qid.path), qid.path); + devdir(c, qid, name, 0, eve, perm, dp); + return 1; +} + + +static int +skelgen(Chan *c, char *name, Dirtab *, int, int s, Dir *dp) +{ + Skel *f; + + f = c->aux; + //First walk away from root + if(name && !f->name[0] && f->mode != 'e' && NETTYPE(c->qid.path) == Qroot) + utfecpy(f->name, &f->name[sizeof f->name-1], name); + + if(s != DEVDOTDOT) + s++; + + return step(c, dp, s); +} + +static Walkqid* +skelwalk(Chan *c, Chan *nc, char **name, int nname) +{ + Walkqid *wq; + Skel *f; + + f = c->aux; + qlock(&f->lk); + if(waserror()){ + qunlock(&f->lk); + nexterror(); + } + + wq = devwalk(c, nc, name, nname, nil, 0, skelgen); + if(wq != nil && wq->clone != nil && wq->clone != c){ + if(f->ref <= 0) + panic("devskel ref"); + f->ref++; + } + qunlock(&f->lk); + poperror(); + return wq; +} + +static Chan* +skelopen(Chan *c, int omode) +{ + if(!(c->qid.type & QTDIR)) + error(Eperm); + if(omode != OREAD) + error(Ebadarg); + + c->mode = omode; + c->flag |= COPEN; + c->offset = 0; + return c; +} + +static void +skelclose(Chan *c) +{ + Skel *f; + + f = c->aux; + qlock(&f->lk); + f->ref--; + if(f->ref == 0){ + qunlock(&f->lk); + free(f); + } else + qunlock(&f->lk); +} + +static long +skelread(Chan *c, void *va, long n, vlong) +{ + Skel *f; + long nout; + + if(!(c->qid.type & QTDIR)) + error(Eperm); + + f = c->aux; + qlock(&f->lk); + if(waserror()){ + qunlock(&f->lk); + nexterror(); + } + nout = devdirread(c, va, n, nil, 0, skelgen); + qunlock(&f->lk); + poperror(); + return nout; +} + +static long +skelwrite(Chan *, void *, long, vlong) +{ + error(Eperm); + return 0; +} + +static int +skelstat(Chan *c, uchar *db, int n) +{ + Skel *f; + Dir dir; + + f = c->aux; + qlock(&f->lk); + step(c, &dir, 0); + qunlock(&f->lk); + + n = convD2M(&dir, db, n); + if(n < BIT16SZ) + error(Eshortstat); + return n; +} + +Dev skeldevtab = { + 'z', + "skel", + + devreset, + devinit, + devshutdown, + skelattach, + skelwalk, + skelstat, + skelopen, + devcreate, + skelclose, + skelread, + devbread, + skelwrite, + devbwrite, + devremove, + devwstat, +}; From 056ad652a41fde51755aedb8119b37fe5946b12c Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 7 Jun 2022 05:38:08 +0000 Subject: [PATCH 12/58] auth/box: build restricted namespaces using components from the parent. --- sys/man/8/auth | 37 ++++++++ sys/src/cmd/auth/box.c | 192 ++++++++++++++++++++++++++++++++++++++++ sys/src/cmd/auth/mkfile | 1 + 3 files changed, 230 insertions(+) create mode 100644 sys/src/cmd/auth/box.c diff --git a/sys/man/8/auth b/sys/man/8/auth index e6c3c343d..fcfe8fcc9 100644 --- a/sys/man/8/auth +++ b/sys/man/8/auth @@ -60,6 +60,20 @@ changeuser, convkeys, printnetkey, status, enable, disable, authsrv, guard.srv, .I arg \&... .PP +.B auth/box +[ +.B -d +] [ +.B -rc +.I file +] [ +.B -e +.I devs +] +.I command +.I arg +\&... +.PP .B auth/as [ .B -d @@ -264,6 +278,29 @@ If there are no arguments, it It's an easy way to run a command as .IR none . .PP +.I Box +sets up a restricted namespace and +.IR exec's +its arguments as the user +.IR none . +Components of the current namespace are bound +into the child namespace with the +.B -r +and +.B -c +flags, using either +.I MREPL +or +.I MCREATE +respectively. The only components +in the child namespace will be those +defined this way. +By default all further kernel driver +access is blocked. The +.B -e +flag specifies a string of driver +characters to keep in the child namespace. +.PP .I As executes .I command diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c new file mode 100644 index 000000000..779cd0f9d --- /dev/null +++ b/sys/src/cmd/auth/box.c @@ -0,0 +1,192 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> + +static int debug; + +static void +binderr(char *new, char *old, int flag) +{ + char dash[4] = { '-' }; + + if(debug){ + if(flag & MCREATE){ + dash[2] = 'c'; + flag &= ~MCREATE; + } + switch(flag){ + case MREPL: + dash[0] = ' '; + if(dash[2] == 'c') + dash[1] = '-'; + else + dash[1] = ' '; + break; + case MBEFORE: + dash[1] = 'b'; + break; + case MAFTER: + dash[1] = 'a'; + break; + } + print("bind %s %s %s\n", dash, new, old); + } + if(bind(new, old, flag) < 0) + sysfatal("bind: %r"); +} + +static void +resolvenames(char **names, int nname) +{ + int i; + char buf[8192]; + int fd; + + fd = open(".", OREAD|OCEXEC); + if(fd < 0) + sysfatal("could not open .: %r"); + fd2path(fd, buf, sizeof buf); + for(i = 0; i < nname; i++){ + if(names[i] == nil) + continue; + cleanname(names[i]); + switch(names[i][0]){ + case '#': + case '/': + break; + case '.': + if(names[i][1] == '/') + break; + default: + names[i] = cleanname(smprint("%s/%s", buf, names[i])); + } + } + close(fd); +} + +static void +sandbox(char **names, int *flags, int nname) +{ + char *parts[32]; + char rootskel[128]; + char src[8192], targ[8192], dir[8192], skel[8192]; + char name[8192]; + char *newroot; + Dir *d; + int i, j, n; + + snprint(rootskel, sizeof rootskel, "#zd/newroot.%d", getpid()); + binderr(rootskel, "/", MBEFORE); + + newroot = rootskel + strlen("#zd"); + + for(j = 0; j < nname; j++){ + if(names[j] == nil) + continue; + utfecpy(name, &name[sizeof name-1], names[j]); + n = gettokens(name, parts, nelem(parts), "/"); + utfecpy(targ, &targ[sizeof targ-1], newroot); + memset(src, 0, sizeof src); + for(i = 0; i < n; i++){ + utfecpy(dir, &dir[sizeof dir-1], targ); + snprint(targ, sizeof targ, "%s/%s", targ, parts[i]); + snprint(src, sizeof src, "%s/%s", src, parts[i]); + d = dirstat(targ); + if(d != nil){ + free(d); + continue; + } + d = dirstat(src); + if(d == nil) + continue; + if(d->mode & DMDIR) + snprint(skel, sizeof skel, "#zd/%s", parts[i]); + else + snprint(skel, sizeof skel, "#zf/%s", parts[i]); + free(d); + binderr(skel, dir, MBEFORE); + } + binderr(names[j], targ, flags[j]); + } + binderr(newroot, "/", MREPL); +} + +static void +run(char **a) +{ + exec(a[0], a); + + if(a[0][0] != '/' && a[0][0] != '#' && + (a[0][0] != '.' || (a[0][1] != '/' && + (a[0][1] != '.' || a[0][2] != '/')))) + exec(smprint("/bin/%s", a[0]), a); + + sysfatal("exec: %s: %r", a[0]); +} + +void +usage(void) +{ + fprint(2, "usage %s: [ -d ] [ -r file ] [ -c dir ] [ -e devs ] cmd args...\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char devs[1024]; + int dfd; + char *parts[256]; + int mflags[256]; + int nparts; + + nparts = 0; + memset(devs, 0, sizeof devs); + ARGBEGIN{ + case 'd': + debug = 1; + break; + case 'r': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MREPL; + break; + case 'c': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MCREATE|MREPL; + break; + case 'e': + snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage())); + break; + default: + usage(); + break; + }ARGEND + if(argc == 0) + usage(); + + rfork(RFNAMEG|RFENVG); + dfd = open("/dev/drivers", OWRITE|OCEXEC); + if(dfd < 0) + sysfatal("could not /dev/drivers: %r"); + + resolvenames(parts, nparts); + + if(procsetuser("none") < 0) + sysfatal("cant become none: %r"); + putenv("user", "none"); + + sandbox(parts, mflags, nparts); + + if(debug) + print("chdev %s\n", devs); + + if(devs[0] != '\0'){ + if(fprint(dfd, "chdev & %s", devs) <= 0) + sysfatal("could not write chdev: %r"); + } else { + if(fprint(dfd, "chdev ~") <= 0) + sysfatal("could not write chdev: %r"); + } + close(dfd); + run(argv); +} diff --git a/sys/src/cmd/auth/mkfile b/sys/src/cmd/auth/mkfile index f8f6ec829..1dbc46941 100644 --- a/sys/src/cmd/auth/mkfile +++ b/sys/src/cmd/auth/mkfile @@ -9,6 +9,7 @@ TARG=\ asn1dump\ asn12rsa\ authsrv\ + box\ changeuser\ convkeys\ cron\ From 1b5ea51ee1203952900fafc0def48985d900f7a7 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Wed, 8 Jun 2022 02:44:35 +0000 Subject: [PATCH 13/58] auth/box: bind in the binary by default This prevents stuttering on the command line by not having to give a -r flag for the binary itself. --- sys/src/cmd/auth/box.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c index 779cd0f9d..e2dac74c6 100644 --- a/sys/src/cmd/auth/box.c +++ b/sys/src/cmd/auth/box.c @@ -54,9 +54,6 @@ resolvenames(char **names, int nname) case '#': case '/': break; - case '.': - if(names[i][1] == '/') - break; default: names[i] = cleanname(smprint("%s/%s", buf, names[i])); } @@ -111,19 +108,6 @@ sandbox(char **names, int *flags, int nname) binderr(newroot, "/", MREPL); } -static void -run(char **a) -{ - exec(a[0], a); - - if(a[0][0] != '/' && a[0][0] != '#' && - (a[0][0] != '.' || (a[0][1] != '/' && - (a[0][1] != '.' || a[0][2] != '/')))) - exec(smprint("/bin/%s", a[0]), a); - - sysfatal("exec: %s: %r", a[0]); -} - void usage(void) { @@ -134,6 +118,8 @@ usage(void) void main(int argc, char **argv) { + char *b; + Dir *d; char devs[1024]; int dfd; char *parts[256]; @@ -164,6 +150,19 @@ main(int argc, char **argv) if(argc == 0) usage(); + b = argv[0]; + d = dirstat(b); + if(d == nil){ + b = smprint("/bin/%s", b); + d = dirstat(b); + if(d == nil) + sysfatal("could not stat %s %r", argv[0]); + } + free(d); + parts[nparts] = b; + mflags[nparts++] = MREPL; + argv[0] = b; + rfork(RFNAMEG|RFENVG); dfd = open("/dev/drivers", OWRITE|OCEXEC); if(dfd < 0) @@ -188,5 +187,5 @@ main(int argc, char **argv) sysfatal("could not write chdev: %r"); } close(dfd); - run(argv); + exec(argv[0], argv); } From 13065e16b3c4fba4d9200ed7fec89ee49338f12a Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Fri, 10 Jun 2022 04:10:54 +0000 Subject: [PATCH 14/58] auth/box: don't bother switching to none Changing the user to none doesn't do much for us here. For kernel drivers that check the user of the current proc we'll be none, but anything from devmnt will still be accessed using creds from the original attachment. Instead, running with none can be done by chaining with auth/none: auth/none auth/box ... --- sys/man/8/auth | 35 ++++++++++++++++------------------- sys/src/cmd/auth/box.c | 7 +------ 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/sys/man/8/auth b/sys/man/8/auth index fcfe8fcc9..e31730a30 100644 --- a/sys/man/8/auth +++ b/sys/man/8/auth @@ -279,27 +279,24 @@ It's an easy way to run a command as .IR none . .PP .I Box -sets up a restricted namespace and -.IR exec's -its arguments as the user -.IR none . -Components of the current namespace are bound -into the child namespace with the -.B -r -and -.B -c -flags, using either -.I MREPL -or -.I MCREATE -respectively. The only components -in the child namespace will be those -defined this way. -By default all further kernel driver -access is blocked. The +executes its arguments in a minimal namespace. +This namespace is derived by binding in the specified +program to the same name within a new hierarchy. +The same is done with the paths +provided as arguments. Paths provided with the +.B -r +flag are bound with +.IR MREPL , +and those provided with the +.B -c +flag are bound with +.IR MCREATE . +.I Box +removes access to all kernel drivers from +the child namespace; the .B -e flag specifies a string of driver -characters to keep in the child namespace. +characters to keep. .PP .I As executes diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c index e2dac74c6..30eedce7d 100644 --- a/sys/src/cmd/auth/box.c +++ b/sys/src/cmd/auth/box.c @@ -163,17 +163,12 @@ main(int argc, char **argv) mflags[nparts++] = MREPL; argv[0] = b; - rfork(RFNAMEG|RFENVG); + rfork(RFNAMEG|RFFDG); dfd = open("/dev/drivers", OWRITE|OCEXEC); if(dfd < 0) sysfatal("could not /dev/drivers: %r"); resolvenames(parts, nparts); - - if(procsetuser("none") < 0) - sysfatal("cant become none: %r"); - putenv("user", "none"); - sandbox(parts, mflags, nparts); if(debug) From 4eeefed7b0c1c47329213f1da719820ebbbebf18 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Tue, 7 Jun 2022 22:38:04 +0000 Subject: [PATCH 15/58] cwfs: fix iounit negotiation cwfs had an issue with iounit negotiation as a result of the conversion to 9p2000 -- with the move to variable size messages, the fixed message overhead decreased, but the advertised message size was still adding the old fixed overhead. This meant that if the kernel negotiated the maximum io size, cwfs would negotiate something larger than it supported, and would hang up when an io of that size was made. In addition, the size of messages was stored in a short, which means that negotiating an iounit larger than 16384 bytes would overflow the message count, and cause things to fall over. Finally, whle we're here, we clean up some duplicated and unused constants. --- sys/src/cmd/cwfs/9p2.c | 11 ++++------- sys/src/cmd/cwfs/all.h | 1 + sys/src/cmd/cwfs/con.c | 8 ++++---- sys/src/cmd/cwfs/console.c | 1 - sys/src/cmd/cwfs/portdat.h | 14 +++----------- sys/src/cmd/cwfs/srv.c | 1 - sys/src/cmd/cwfs/sub.c | 2 -- 7 files changed, 12 insertions(+), 26 deletions(-) diff --git a/sys/src/cmd/cwfs/9p2.c b/sys/src/cmd/cwfs/9p2.c index a4d129c97..3745fff76 100644 --- a/sys/src/cmd/cwfs/9p2.c +++ b/sys/src/cmd/cwfs/9p2.c @@ -1,7 +1,4 @@ #include "all.h" -#include <fcall.h> - -enum { MSIZE = MAXDAT+MAXMSG }; static int mkmode9p1(ulong mode9p2) @@ -155,10 +152,10 @@ version(Chan* chan, Fcall* f, Fcall* r) if(chan->protocol != nil || f->msize < 256) return Eversion; - if(f->msize < MSIZE) + if(f->msize < MAXDAT+IOHDRSZ) r->msize = f->msize; else - r->msize = MSIZE; + r->msize = MAXDAT+IOHDRSZ; /* * Should check the '.' stuff here. @@ -1825,7 +1822,7 @@ serve9p2(Msgbuf* mb) * replies. */ if(convM2S(mb->data, mb->count, &f) != mb->count){ - fprint(2, "didn't like %d byte message\n", mb->count); + fprint(2, "didn't like %ld byte message\n", mb->count); return 0; } type = f.type; @@ -1921,7 +1918,7 @@ serve9p2(Msgbuf* mb) */ if(chan->msize == 0){ r.ename = "Tversion not seen"; - n = convS2M(&r, rmb->data, MAXMSG); + n = convS2M(&r, rmb->data, SMALLBUF); } else { snprint(ename, sizeof(ename), "9p2: convS2M: type %d", type); diff --git a/sys/src/cmd/cwfs/all.h b/sys/src/cmd/cwfs/all.h index 418d15f55..900113fbd 100644 --- a/sys/src/cmd/cwfs/all.h +++ b/sys/src/cmd/cwfs/all.h @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <ctype.h> +#include <fcall.h> #define Tfile Tfilescsi /* avoid name conflict */ #include <disk.h> #undef Tfile diff --git a/sys/src/cmd/cwfs/con.c b/sys/src/cmd/cwfs/con.c index 2b418d8c6..d604f9241 100644 --- a/sys/src/cmd/cwfs/con.c +++ b/sys/src/cmd/cwfs/con.c @@ -711,9 +711,9 @@ cmd_time(int argc, char *argv[]) { int i, len; char *cmd; - Timet t1, t2; + vlong t1, t2; - t1 = time(nil); + t1 = nsec(); len = 0; for(i=1; i<argc; i++) len += 1 + strlen(argv[i]); @@ -724,9 +724,9 @@ cmd_time(int argc, char *argv[]) strcat(cmd, argv[i]); } cmd_exec(cmd); - t2 = time(nil); + t2 = nsec(); free(cmd); - print("time = %ld ms\n", TK2MS(t2-t1)); + print("time = %lld ns\n", t2-t1); } void diff --git a/sys/src/cmd/cwfs/console.c b/sys/src/cmd/cwfs/console.c index 3a5e7771f..9f730678f 100644 --- a/sys/src/cmd/cwfs/console.c +++ b/sys/src/cmd/cwfs/console.c @@ -1,5 +1,4 @@ #include "all.h" -#include <fcall.h> /* 9p2 */ int version(Chan*, Fcall*, Fcall*); diff --git a/sys/src/cmd/cwfs/portdat.h b/sys/src/cmd/cwfs/portdat.h index 80af31044..3e025065c 100644 --- a/sys/src/cmd/cwfs/portdat.h +++ b/sys/src/cmd/cwfs/portdat.h @@ -20,18 +20,10 @@ typedef vlong Devsize; /* in bytes */ #define HOWMANY(x, y) (((x)+((y)-1)) / (y)) #define ROUNDUP(x, y) (HOWMANY((x), (y)) * (y)) -#define TK2MS(t) (((ulong)(t)*1000)/HZ) /* ticks to ms - beware rounding */ -#define MS2TK(t) (((ulong)(t)*HZ)/1000) /* ms to ticks - beware rounding */ -#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ - /* constants that don't affect disk layout */ enum { MAXDAT = 8192, /* max allowable data message */ - MAXMSG = 128, /* max protocol message sans data */ - MB = 1024*1024, - - HZ = 1, /* clock frequency */ }; /* @@ -152,8 +144,8 @@ enum { DIRPERBUF = BUFSIZE / sizeof(Dentry), INDPERBUF = BUFSIZE / sizeof(Off), FEPERBUF = (BUFSIZE-sizeof(Super1)-sizeof(Off)) / sizeof(Off), - SMALLBUF = MAXMSG, - LARGEBUF = MAXMSG+MAXDAT+256, + SMALLBUF = 128, + LARGEBUF = IOHDRSZ+MAXDAT+256, RAGAP = (300*1024)/BUFSIZE, /* readahead parameter */ BKPERBLK = 10, CEPERBK = (BUFSIZE - BKPERBLK*sizeof(Off)) / @@ -459,7 +451,7 @@ enum { struct Msgbuf { ulong magic; - short count; + ulong count; short flags; #define LARGE (1<<0) #define FREE (1<<1) diff --git a/sys/src/cmd/cwfs/srv.c b/sys/src/cmd/cwfs/srv.c index e022b9fbf..d745cdf8e 100644 --- a/sys/src/cmd/cwfs/srv.c +++ b/sys/src/cmd/cwfs/srv.c @@ -1,6 +1,5 @@ #include "all.h" #include "io.h" -#include <fcall.h> /* 9p2000 */ #include <thread.h> enum { diff --git a/sys/src/cmd/cwfs/sub.c b/sys/src/cmd/cwfs/sub.c index d8befccb9..6a871b554 100644 --- a/sys/src/cmd/cwfs/sub.c +++ b/sys/src/cmd/cwfs/sub.c @@ -101,8 +101,6 @@ loop: unlock(&flock); } -enum { NOFID = (ulong)~0 }; - /* * returns a locked file structure */ From bb33663b402060b6664d3a1829daad0e44fa9af0 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 11 Jun 2022 16:36:45 +0000 Subject: [PATCH 16/58] git/get: keep sending what we have until we get an ack Git9 was sloppy about telling git what commits we have. We would list the commits at the tip of the branch, but not walk down it, which means we would request too much data if our local branches were ahead of the remote. This patch changes that, sending the tips *and* the first 256 commits after them, so that git can produce a better pack for us, with fewer redundant commits. --- sys/src/cmd/git/get.c | 75 +++++++++++++++++++++++++++++++++-------- sys/src/cmd/git/git.h | 1 + sys/src/cmd/git/proto.c | 14 ++++++++ sys/src/cmd/git/serve.c | 14 -------- 4 files changed, 76 insertions(+), 28 deletions(-) diff --git a/sys/src/cmd/git/get.c b/sys/src/cmd/git/get.c index 95dfe106e..77547c0c0 100644 --- a/sys/src/cmd/git/get.c +++ b/sys/src/cmd/git/get.c @@ -177,17 +177,35 @@ fail(char *pack, char *idx, char *msg, ...) exits(buf); } +void +enqueueparent(Objq *q, Object *o) +{ + Object *p; + int i; + + if(o->type != GCommit) + return; + for(i = 0; i < o->commit->nparent; i++){ + if((p = readobject(o->commit->parent[i])) == nil) + continue; + qput(q, p, 0); + unref(p); + } +} + int fetchpack(Conn *c) { char buf[Pktmax], *sp[3], *ep; - char *packtmp, *idxtmp, **ref; + char *packtmp, *idxtmp, **ref, *caps; Hash h, *have, *want; - int nref, refsz, first; - int i, n, l, req, pfd; + int nref, refsz, first, nsent; + int i, l, n, req, pfd; vlong packsz; Objset hadobj; Object *o; + Objq haveq; + Qelt e; nref = 0; refsz = 16; @@ -234,6 +252,7 @@ fetchpack(Conn *c) if(writephase(c) == -1) sysfatal("write: %r"); req = 0; + caps = " multi_ack"; for(i = 0; i < nref; i++){ if(hasheq(&have[i], &want[i])) continue; @@ -241,30 +260,58 @@ fetchpack(Conn *c) unref(o); continue; } - n = snprint(buf, sizeof(buf), "want %H\n", want[i]); - if(writepkt(c, buf, n) == -1) + if(fmtpkt(c, "want %H%s\n", want[i], caps) == -1) sysfatal("could not send want for %H", want[i]); + caps = ""; req = 1; } flushpkt(c); + + nsent = 0; + qinit(&haveq); osinit(&hadobj); + /* + * We know we have these objects, and we want to make sure that + * they end up at the front of the queue. Send the 'have lines' + * first, and then enqueue their parents for a second round of + * sends. + */ for(i = 0; i < nref; i++){ if(hasheq(&have[i], &Zhash) || oshas(&hadobj, have[i])) continue; if((o = readobject(have[i])) == nil) sysfatal("missing object we should have: %H", have[i]); + if(fmtpkt(c, "have %H", o->hash) == -1) + sysfatal("write: %r"); + enqueueparent(&haveq, o); osadd(&hadobj, o); - unref(o); - n = snprint(buf, sizeof(buf), "have %H\n", have[i]); - if(writepkt(c, buf, n + 1) == -1) - sysfatal("could not send have for %H", have[i]); + unref(o); + } + /* + * While we could short circuit this and check if upstream has + * acked our objects, for the first 256 haves, this is simple + * enough. + * + * Also, doing multiple rounds of reference discovery breaks + * when using smart http. + */ + while(req && qpop(&haveq, &e) && nsent < 256){ + if(oshas(&hadobj, e.o->hash)) + continue; + if((o = readobject(e.o->hash)) == nil) + sysfatal("missing object we should have: %H", have[i]); + if(fmtpkt(c, "have %H", o->hash) == -1) + sysfatal("write: %r"); + enqueueparent(&haveq, o); + osadd(&hadobj, o); + unref(o); + nsent++; } osclear(&hadobj); + qclear(&haveq); if(!req) flushpkt(c); - - n = snprint(buf, sizeof(buf), "done\n"); - if(writepkt(c, buf, n) == -1) + if(fmtpkt(c, "done\n") == -1) sysfatal("write: %r"); if(!req) goto showrefs; @@ -298,9 +345,9 @@ fetchpack(Conn *c) if(strncmp(buf, "PACK", 4) == 0) break; l = strtol(buf, &ep, 16); - if(l == 0 || ep != buf + 4) + if(ep != buf + 4) sysfatal("fetch packfile: junk pktline"); - if(readn(c->rfd, buf, l) != l) + if(readn(c->rfd, buf, l-4) != l-4) sysfatal("fetch packfile: short read"); } if(write(pfd, "PACK", 4) != 4) diff --git a/sys/src/cmd/git/git.h b/sys/src/cmd/git/git.h index 88afcc1d7..c3ba7b7a9 100644 --- a/sys/src/cmd/git/git.h +++ b/sys/src/cmd/git/git.h @@ -313,6 +313,7 @@ Delta* deltify(Object*, Dtab*, int*); /* proto handling */ int readpkt(Conn*, char*, int); int writepkt(Conn*, char*, int); +int fmtpkt(Conn*, char*, ...); int flushpkt(Conn*); void initconn(Conn*, int, int); int gitconnect(Conn *, char *, char *); diff --git a/sys/src/cmd/git/proto.c b/sys/src/cmd/git/proto.c index ddc2258f3..9af09ec19 100644 --- a/sys/src/cmd/git/proto.c +++ b/sys/src/cmd/git/proto.c @@ -93,6 +93,20 @@ writepkt(Conn *c, char *buf, int nbuf) return 0; } +int +fmtpkt(Conn *c, char *fmt, ...) +{ + char pkt[Pktmax]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprint(pkt, sizeof(pkt), fmt, ap); + n = writepkt(c, pkt, n); + va_end(ap); + return n; +} + int flushpkt(Conn *c) { diff --git a/sys/src/cmd/git/serve.c b/sys/src/cmd/git/serve.c index 895c6f5e0..da7cd56b0 100644 --- a/sys/src/cmd/git/serve.c +++ b/sys/src/cmd/git/serve.c @@ -8,20 +8,6 @@ char *pathpfx = nil; int allowwrite; -int -fmtpkt(Conn *c, char *fmt, ...) -{ - char pkt[Pktmax]; - va_list ap; - int n; - - va_start(ap, fmt); - n = vsnprint(pkt, sizeof(pkt), fmt, ap); - n = writepkt(c, pkt, n); - va_end(ap); - return n; -} - int showrefs(Conn *c) { From 3e176bd975492427b232308e37ff51e7389d08e7 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 11 Jun 2022 17:48:20 +0000 Subject: [PATCH 17/58] git/pack: add support for skipping ssh signatures ssh signatures confused our commit parsing; teach our commit parsing to skip them. --- sys/src/cmd/git/pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/src/cmd/git/pack.c b/sys/src/cmd/git/pack.c index 41eac2262..05492e9f9 100644 --- a/sys/src/cmd/git/pack.c +++ b/sys/src/cmd/git/pack.c @@ -884,6 +884,7 @@ parsecommit(Object *o) }else if(strcmp(buf, "gpgsig") == 0){ /* just drop it */ if((t = strstr(p, "-----END PGP SIGNATURE-----")) == nil) + if((t = strstr(p, "-----END SSH SIGNATURE-----")) == nil) sysfatal("malformed gpg signature"); np -= t - p; p = t; From 276f2039a9bceb4bc23b0fa1ce3169057aac405e Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 11 Jun 2022 21:06:39 +0000 Subject: [PATCH 18/58] devi2c: add generic i2c bus driver --- sys/src/9/port/devi2c.c | 597 ++++++++++++++++++++++++++++++++++++++++ sys/src/9/port/i2c.h | 56 ++++ 2 files changed, 653 insertions(+) create mode 100644 sys/src/9/port/devi2c.c create mode 100644 sys/src/9/port/i2c.h diff --git a/sys/src/9/port/devi2c.c b/sys/src/9/port/devi2c.c new file mode 100644 index 000000000..568480ae7 --- /dev/null +++ b/sys/src/9/port/devi2c.c @@ -0,0 +1,597 @@ +/* I²C bus driver */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "../port/i2c.h" + +enum { + Qdir = 0, /* #J */ + Qbus, /* #J/bus */ + Qctl, /* #J/bus/i2c.n.ctl */ + Qdata, /* #J/bus/i2c.n.data */ +}; + +#define TYPE(q) ((ulong)(q).path & 0x0F) +#define BUS(q) (((ulong)(q).path>>4) & 0xFF) +#define DEV(q) (((ulong)(q).path>>12) & 0xFFF) +#define QID(d, b, t) (((d)<<12)|((b)<<4)|(t)) + +static I2Cbus *buses[16]; + +static I2Cdev *devs[1024]; +static Lock devslock; + +static void probebus(I2Cbus *bus); + +void +addi2cbus(I2Cbus *bus) +{ + int i; + + if(bus == nil) + return; + + for(i = 0; i < nelem(buses); i++){ + if(buses[i] == nil + || buses[i] == bus + || strcmp(bus->name, buses[i]->name) == 0){ + buses[i] = bus; + break; + } + } +} + +I2Cbus* +i2cbus(char *name) +{ + I2Cbus *bus; + int i; + + for(i = 0; i < nelem(buses); i++){ + bus = buses[i]; + if(bus == nil) + break; + if(strcmp(bus->name, name) == 0){ + probebus(bus); + return bus; + } + } + return nil; +} + +void +addi2cdev(I2Cdev *dev) +{ + int i; + + if(dev == nil || dev->bus == nil) + return; + + lock(&devslock); + for(i = 0; i < nelem(devs); i++){ + if(devs[i] == nil + || devs[i] == dev + || devs[i]->addr == dev->addr && devs[i]->bus == dev->bus){ + devs[i] = dev; + unlock(&devslock); + return; + } + } + unlock(&devslock); +} + +I2Cdev* +i2cdev(I2Cbus *bus, int addr) +{ + I2Cdev *dev; + int i; + + if(bus == nil || addr < 0 || addr >= 1<<10) + return nil; + + lock(&devslock); + for(i = 0; i < nelem(devs) && (dev = devs[i]) != nil; i++){ + if(dev->addr == addr && dev->bus == bus){ + unlock(&devslock); + return dev; + } + } + unlock(&devslock); + + return nil; +} + + +static int +enterbus(I2Cbus *bus) +{ + if(up != nil && islo()){ + eqlock(bus); + return 1; + } else { + while(!canqlock(bus)) + ; + return 0; + } +} + +static void +leavebus(I2Cbus *bus) +{ + qunlock(bus); +} + +int +i2cbusio(I2Cbus *bus, uchar *pkt, int olen, int ilen) +{ + int user, n; + + user = enterbus(bus); + if(!bus->probed){ + leavebus(bus); + return -1; + } + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + leavebus(bus); + nexterror(); + } +// iprint("%s: <- %.*H\n", bus->name, olen, pkt); + n = (*bus->io)(bus, pkt, olen, ilen); +// if(n > olen) iprint("%s: -> %.*H\n", bus->name, n - olen, pkt+olen); + + leavebus(bus); + if(user) poperror(); + + return n; +} + +static int +putaddr(I2Cdev *dev, int isread, uchar *pkt, vlong addr) +{ + int n, o = 0; + + if(dev->a10){ + pkt[o++] = 0xF0 | (dev->addr>>(8-1))&6 | (isread != 0); + pkt[o++] = dev->addr; + } else + pkt[o++] = dev->addr<<1 | (isread != 0); + + if(addr >= 0){ + for(n=0; n<dev->subaddr; n++) + pkt[o++] = addr >> (n*8); + } + + return o; +} + +int +i2csend(I2Cdev *dev, void *data, int len, vlong addr) +{ + uchar pkt[138]; + int o; + + o = putaddr(dev, 0, pkt, addr); + if(o+len > sizeof(pkt)) + len = sizeof(pkt)-o; + + if(len > 0) + memmove(pkt+o, data, len); + + return i2cbusio(dev->bus, pkt, o + len, 0) - o; +} + +int +i2crecv(I2Cdev *dev, void *data, int len, vlong addr) +{ + uchar pkt[138]; + int o; + + o = putaddr(dev, 1, pkt, addr); + if(o+len > sizeof(pkt)) + len = sizeof(pkt)-o; + + len = i2cbusio(dev->bus, pkt, o, len) - o; + if(len > 0) + memmove(data, pkt+o, len); + + return len; +} + +int +i2cquick(I2Cdev *dev, int rw) +{ + uchar pkt[2]; + int o = putaddr(dev, rw, pkt, -1); + if(i2cbusio(dev->bus, pkt, o, 0) != o) + return -1; + return rw != 0; +} +int +i2crecvbyte(I2Cdev *dev) +{ + uchar pkt[2+1]; + int o = putaddr(dev, 1, pkt, -1); + if(i2cbusio(dev->bus, pkt, o, 1) - o != 1) + return -1; + return pkt[o]; +} +int +i2csendbyte(I2Cdev *dev, uchar b) +{ + uchar pkt[2+1]; + int o = putaddr(dev, 0, pkt, -1); + pkt[o] = b; + if(i2cbusio(dev->bus, pkt, o+1, 0) - o != 1) + return -1; + return b; +} +int +i2creadbyte(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+1]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 1) - o != 1) + return -1; + return pkt[o]; +} +int +i2cwritebyte(I2Cdev *dev, ulong addr, uchar b) +{ + uchar pkt[2+4+1]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o] = b; + if(i2cbusio(dev->bus, pkt, o+1, 0) - o != 1) + return -1; + return b; +} +int +i2creadword(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+2]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 2) - o != 2) + return -1; + return pkt[o] | (ushort)pkt[o+1]<<8; +} +int +i2cwriteword(I2Cdev *dev, ulong addr, ushort w) +{ + uchar pkt[2+4+2]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o+0] = w; + pkt[o+1] = w>>8; + if(i2cbusio(dev->bus, pkt, o+2, 0) - o != 2) + return -1; + return w; +} +vlong +i2cread32(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+4]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 4) - o != 4) + return -1; + return pkt[o] | (ulong)pkt[o+1]<<8 | (ulong)pkt[o+2]<<16 | (ulong)pkt[o+3]<<24; +} +vlong +i2cwrite32(I2Cdev *dev, ulong addr, ulong u) +{ + uchar pkt[2+4+4]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o+0] = u; + pkt[o+1] = u>>8; + pkt[o+2] = u>>16; + pkt[o+3] = u>>24; + if(i2cbusio(dev->bus, pkt, o+4, 0) - o != 4) + return -1; + return u; +} + +static void +probeddev(I2Cdev *dummy) +{ + I2Cdev *dev = smalloc(sizeof(I2Cdev)); + memmove(dev, dummy, sizeof(I2Cdev)); + addi2cdev(dev); +} + +static void +probebus(I2Cbus *bus) +{ + I2Cdev dummy; + uchar pkt[2]; + int user, n; + + if(bus->probed) + return; + + user = enterbus(bus); + if(bus->probed){ + leavebus(bus); + return; + } + if(user && waserror() + || (*bus->init)(bus)){ + leavebus(bus); + if(user) nexterror(); + return; + } + + memset(&dummy, 0, sizeof(dummy)); + dummy.bus = bus; + + dummy.a10 = 0; + for(dummy.addr = 8; dummy.addr < 0x78; dummy.addr++) { + if(i2cdev(bus, dummy.addr) != nil) + continue; + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + continue; + } + n = putaddr(&dummy, 0, pkt, -1); + if((*bus->io)(bus, pkt, n, 0) == n) + probeddev(&dummy); + if(user) poperror(); + } + + dummy.a10 = 1; + for(dummy.addr = 0; dummy.addr < (1<<10); dummy.addr++) { + if(i2cdev(bus, dummy.addr) != nil) + continue; + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + continue; + } + n = putaddr(&dummy, 0, pkt, -1); + if((*bus->io)(bus, pkt, n, 0) == n) + probeddev(&dummy); + if(user) poperror(); + } + + bus->probed = 1; + leavebus(bus); + if(user) poperror(); +} + +static int +i2cgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) +{ + I2Cbus *bus; + I2Cdev *dev; + + Qid q; + + switch(TYPE(c->qid)){ + case Qdir: + if(s == DEVDOTDOT){ + Gendir: + mkqid(&q, QID(0, 0, Qdir), 0, QTDIR); + snprint(up->genbuf, sizeof up->genbuf, "#J"); + devdir(c, q, up->genbuf, 0, eve, 0500, dp); + return 1; + } + if(s >= nelem(buses)) + return -1; + bus = buses[s]; + if(bus == nil) + return -1; + mkqid(&q, QID(0, s, Qbus), 0, QTDIR); + devdir(c, q, bus->name, 0, eve, 0500, dp); + return 1; + case Qbus: + if(s == DEVDOTDOT) + goto Gendir; + if((s/2) >= nelem(devs)) + return -1; + + bus = buses[BUS(c->qid)]; + probebus(bus); + + lock(&devslock); + dev = devs[s/2]; + unlock(&devslock); + + if(dev == nil) + return -1; + if(dev->bus != bus) + return 0; + if(s & 1){ + mkqid(&q, QID(dev->addr, BUS(c->qid), Qdata), 0, 0); + goto Gendata; + } + mkqid(&q, QID(dev->addr, BUS(c->qid), Qctl), 0, 0); + goto Genctl; + case Qctl: + q = c->qid; + Genctl: + snprint(up->genbuf, sizeof up->genbuf, "i2c.%lux.ctl", DEV(q)); + devdir(c, q, up->genbuf, 0, eve, 0600, dp); + return 1; + case Qdata: + q = c->qid; + bus = buses[BUS(q)]; + dev = i2cdev(bus, DEV(q)); + if(dev == nil) + return -1; + Gendata: + snprint(up->genbuf, sizeof up->genbuf, "i2c.%lux.data", DEV(q)); + devdir(c, q, up->genbuf, dev->size, eve, 0600, dp); + return 1; + } + return -1; +} + +static Chan* +i2cattach(char *spec) +{ + return devattach('J', spec); +} + +static Chan* +i2copen(Chan *c, int mode) +{ + c = devopen(c, mode, nil, 0, i2cgen); + switch(TYPE(c->qid)){ + case Qctl: + case Qdata: + c->aux = i2cdev(buses[BUS(c->qid)], DEV(c->qid)); + if(c->aux == nil) + error(Enonexist); + break; + } + return c; +} + +enum { + CMsize, + CMsubaddress, +}; + +static Cmdtab i2cctlmsg[] = +{ + CMsize, "size", 2, + CMsubaddress, "subaddress", 2, +}; + +static long +i2cwrctl(I2Cdev *dev, void *data, long len) +{ + Cmdbuf *cb; + Cmdtab *ct; + ulong u; + + cb = parsecmd(data, len); + if(waserror()){ + free(cb); + nexterror(); + } + ct = lookupcmd(cb, i2cctlmsg, nelem(i2cctlmsg)); + switch(ct->index){ + case CMsize: + dev->size = strtoul(cb->f[1], nil, 0); + break; + case CMsubaddress: + u = strtoul(cb->f[1], nil, 0); + if(u > 4) + cmderror(cb, Ebadarg); + dev->subaddr = u; + break; + default: + cmderror(cb, Ebadarg); + } + free(cb); + poperror(); + return len; +} + +static long +i2crdctl(I2Cdev *dev, void *data, long len, vlong offset) +{ + char cfg[64]; + + snprint(cfg, sizeof(cfg), "size %lud\nsubaddress %d\n", dev->size, dev->subaddr); + return readstr((ulong)offset, data, len, cfg); +} + +static long +i2cwrite(Chan *c, void *data, long len, vlong offset) +{ + I2Cdev *dev; + + switch(TYPE(c->qid)){ + default: + error(Egreg); + return -1; + case Qctl: + dev = c->aux; + return i2cwrctl(dev, data, len); + case Qdata: + break; + } + dev = c->aux; + if(dev->size){ + if(offset+len > dev->size){ + if(offset >= dev->size) + return 0; + len = dev->size - offset; + } + } + len = i2csend(dev, data, len, offset); + if(len < 0) + error(Eio); + return len; +} + +static long +i2cread(Chan *c, void *data, long len, vlong offset) +{ + I2Cdev *dev; + + if(c->qid.type == QTDIR) + return devdirread(c, data, len, nil, 0, i2cgen); + + switch(TYPE(c->qid)){ + default: + error(Egreg); + case Qctl: + dev = c->aux; + return i2crdctl(dev, data, len, offset); + case Qdata: + break; + } + dev = c->aux; + if(dev->size){ + if(offset+len > dev->size){ + if(offset >= dev->size) + return 0; + len = dev->size - offset; + } + } + len = i2crecv(dev, data, len, offset); + if(len < 0) + error(Eio); + return len; +} + +void +i2cclose(Chan*) +{ +} + +static Walkqid* +i2cwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, nil, 0, i2cgen); +} + +static int +i2cstat(Chan *c, uchar *dp, int n) +{ + return devstat(c, dp, n, nil, 0, i2cgen); +} + +Dev i2cdevtab = { + 'J', + "i2c", + + devreset, + devinit, + devshutdown, + i2cattach, + i2cwalk, + i2cstat, + i2copen, + devcreate, + i2cclose, + i2cread, + devbread, + i2cwrite, + devbwrite, + devremove, + devwstat, + devpower, +}; diff --git a/sys/src/9/port/i2c.h b/sys/src/9/port/i2c.h new file mode 100644 index 000000000..eebff9569 --- /dev/null +++ b/sys/src/9/port/i2c.h @@ -0,0 +1,56 @@ +typedef struct I2Cbus I2Cbus; +struct I2Cbus +{ + char *name; + int speed; + + void *ctlr; + int (*init)(I2Cbus *bus); + int (*io)(I2Cbus *bus, uchar *pkt, int olen, int ilen); + + int probed; + QLock; +}; + +typedef struct I2Cdev I2Cdev; +struct I2Cdev +{ + I2Cbus *bus; + + int a10; + int addr; + int subaddr; + ulong size; +}; + +/* + * Register busses (controllers) and devices (addresses) + */ +extern void addi2cbus(I2Cbus *bus); +extern void addi2cdev(I2Cdev *dev); + +/* + * Look-up busses and devices by name and address + */ +extern I2Cbus* i2cbus(char *name); +extern I2Cdev* i2cdev(I2Cbus *bus, int addr); + +/* + * generic I/O + */ +extern int i2cbusio(I2Cbus *bus, uchar *pkt, int olen, int ilen); +extern int i2crecv(I2Cdev *dev, void *data, int len, vlong addr); +extern int i2csend(I2Cdev *dev, void *data, int len, vlong addr); + +/* + * common I/O for SMbus + */ +extern int i2cquick(I2Cdev *dev, int rw); +extern int i2crecvbyte(I2Cdev *dev); +extern int i2csendbyte(I2Cdev *dev, uchar b); +extern int i2creadbyte(I2Cdev *dev, ulong addr); +extern int i2cwritebyte(I2Cdev *dev, ulong addr, uchar b); +extern int i2creadword(I2Cdev *dev, ulong addr); +extern int i2cwriteword(I2Cdev *dev, ulong addr, ushort w); +extern vlong i2cread32(I2Cdev *dev, ulong addr); +extern vlong i2cwrite32(I2Cdev *dev, ulong addr, ulong u); From 931ae0cfebeb46892406efc7468636e59f8110a9 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 11 Jun 2022 21:12:04 +0000 Subject: [PATCH 19/58] imx8: mainscreen turn on! supports the lcd panel and adds alot of infrastructure like for the ccm clock module and the i2c controllers. --- sys/src/9/imx8/ccm.c | 1357 +++++++++++++++++++++++++++++++++++ sys/src/9/imx8/etherimx.c | 10 + sys/src/9/imx8/fns.h | 9 + sys/src/9/imx8/lcd.c | 949 ++++++++++++++++++++++++ sys/src/9/imx8/main.c | 12 +- sys/src/9/imx8/mem.h | 6 +- sys/src/9/imx8/mkfile | 8 +- sys/src/9/imx8/mmu.c | 29 +- sys/src/9/imx8/reform | 6 + sys/src/9/imx8/screen.c | 341 +++++++++ sys/src/9/imx8/screen.h | 32 + sys/src/9/imx8/uartimx.c | 18 + sys/src/9/imx8/usbxhciimx.c | 20 + 13 files changed, 2774 insertions(+), 23 deletions(-) create mode 100644 sys/src/9/imx8/ccm.c create mode 100644 sys/src/9/imx8/lcd.c create mode 100644 sys/src/9/imx8/screen.c create mode 100644 sys/src/9/imx8/screen.h diff --git a/sys/src/9/imx8/ccm.c b/sys/src/9/imx8/ccm.c new file mode 100644 index 000000000..ffec22d52 --- /dev/null +++ b/sys/src/9/imx8/ccm.c @@ -0,0 +1,1357 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static u32int *regs = (u32int*)(VIRTIO + 0x380000); +static u32int *anatop = (u32int*)(VIRTIO + 0x360000); + +enum { + /* input clocks */ + ARM_PLL_CLK = 12, + GPU_PLL_CLK, + VPU_PLL_CLK, + DRAM_PLL1_CLK, + SYSTEM_PLL1_CLK, + SYSTEM_PLL1_DIV2, + SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_DIV4, + SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_DIV6, + SYSTEM_PLL1_DIV8, + SYSTEM_PLL1_DIV10, + SYSTEM_PLL1_DIV20, + SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV6, + SYSTEM_PLL2_DIV8, + SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV20, + SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, + AUDIO_PLL2_CLK, + VIDEO_PLL1_CLK, + VIDEO_PLL2_CLK, + + OSC_32K_REF_CLK, + OSC_25M_REF_CLK, + OSC_27M_REF_CLK, + EXT_CLK_1, + EXT_CLK_2, + EXT_CLK_3, + EXT_CLK_4, + + /* root clocks (slices) */ + ARM_A53_CLK_ROOT = 0, + ARM_M4_CLK_ROOT = 1, + VPU_A53_CLK_ROOT = 2, + GPU_CORE_CLK_ROOT = 3, + GPU_SHADER_CLK_ROOT = 4, + + MAIN_AXI_CLK_ROOT = 16, + ENET_AXI_CLK_ROOT = 17, + NAND_USDHC_BUS_CLK_ROOT = 18, + VPU_BUS_CLK_ROOT = 19, + DISPLAY_AXI_CLK_ROOT = 20, + DISPLAY_APB_CLK_ROOT = 21, + DISPLAY_RTRM_CLK_ROOT = 22, + USB_BUS_CLK_ROOT = 23, + GPU_AXI_CLK_ROOT = 24, + GPU_AHB_CLK_ROOT = 25, + NOC_CLK_ROOT = 26, + NOC_APB_CLK_ROOT = 27, + + AHB_CLK_ROOT = 32, + IPG_CLK_ROOT = 33, + AUDIO_AHB_CLK_ROOT = 34, + AUDIO_IPG_CLK_ROOT = 35, + MIPI_DSI_ESC_RX_CLK_ROOT = 36, + MIPI_DSI_ESC_CLK_ROOT = 37, + + DRAM_ALT_CLK_ROOT = 64, + DRAM_APB_CLK_ROOT = 65, + VPU_G1_CLK_ROOT = 66, + VPU_G2_CLK_ROOT = 67, + DISPLAY_DTRC_CLK_ROOT = 68, + DISPLAY_DC8000_CLK_ROOT = 69, + PCIE1_CTRL_CLK_ROOT = 70, + PCIE1_PHY_CLK_ROOT = 71, + PCIE1_AUX_CLK_ROOT = 72, + DC_PIXEL_CLK_ROOT = 73, + LCDIF_PIXEL_CLK_ROOT = 74, + SAI1_CLK_ROOT = 75, + SAI2_CLK_ROOT = 76, + SAI3_CLK_ROOT = 77, + SAI4_CLK_ROOT = 78, + SAI5_CLK_ROOT = 79, + SAI6_CLK_ROOT = 80, + SPDIF1_CLK_ROOT = 81, + SPDIF2_CLK_ROOT = 82, + ENET_REF_CLK_ROOT = 83, + ENET_TIMER_CLK_ROOT = 84, + ENET_PHY_REF_CLK_ROOT = 85, + NAND_CLK_ROOT = 86, + QSPI_CLK_ROOT = 87, + USDHC1_CLK_ROOT = 88, + USDHC2_CLK_ROOT = 89, + I2C1_CLK_ROOT = 90, + I2C2_CLK_ROOT = 91, + I2C3_CLK_ROOT = 92, + I2C4_CLK_ROOT = 93, + UART1_CLK_ROOT = 94, + UART2_CLK_ROOT = 95, + UART3_CLK_ROOT = 96, + UART4_CLK_ROOT = 97, + USB_CORE_REF_CLK_ROOT = 98, + USB_PHY_REF_CLK_ROOT = 99, + GIC_CLK_ROOT = 100, + ECSPI1_CLK_ROOT = 101, + ECSPI2_CLK_ROOT = 102, + PWM1_CLK_ROOT = 103, + PWM2_CLK_ROOT = 104, + PWM3_CLK_ROOT = 105, + PWM4_CLK_ROOT = 106, + GPT1_CLK_ROOT = 107, + GPT2_CLK_ROOT = 108, + GPT3_CLK_ROOT = 109, + GPT4_CLK_ROOT = 110, + GPT5_CLK_ROOT = 111, + GPT6_CLK_ROOT = 112, + TRACE_CLK_ROOT = 113, + WDOG_CLK_ROOT = 114, + WRCLK_CLK_ROOT = 115, + IPP_DO_CLKO1 = 116, + IPP_DO_CLKO2 = 117, + MIPI_DSI_CORE_CLK_ROOT = 118, + MIPI_DSI_PHY_REF_CLK_ROOT = 119, + MIPI_DSI_DBI_CLK_ROOT = 120, + OLD_MIPI_DSI_ESC_CLK_ROOT = 121, + MIPI_CSI1_CORE_CLK_ROOT = 122, + MIPI_CSI1_PHY_REF_CLK_ROOT = 123, + MIPI_CSI1_ESC_CLK_ROOT = 124, + MIPI_CSI2_CORE_CLK_ROOT = 125, + MIPI_CSI2_PHY_REF_CLK_ROOT = 126, + MIPI_CSI2_ESC_CLK_ROOT = 127, + PCIE2_CTRL_CLK_ROOT = 128, + PCIE2_PHY_CLK_ROOT = 129, + PCIE2_AUX_CLK_ROOT = 130, + ECSPI3_CLK_ROOT = 131, + OLD_MIPI_DSI_ESC_RX_CLK_ROOT = 132, + DISPLAY_HDMI_CLK_ROOT = 133, +}; + +static int input_clk_freq[] = { + [ARM_PLL_CLK] 1600*Mhz, + [GPU_PLL_CLK] 1600*Mhz, + [VPU_PLL_CLK] 800*Mhz, + [DRAM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_DIV2] 400*Mhz, + [SYSTEM_PLL1_DIV3] 266*Mhz, + [SYSTEM_PLL1_DIV4] 200*Mhz, + [SYSTEM_PLL1_DIV5] 160*Mhz, + [SYSTEM_PLL1_DIV6] 133*Mhz, + [SYSTEM_PLL1_DIV8] 100*Mhz, + [SYSTEM_PLL1_DIV10] 80*Mhz, + [SYSTEM_PLL1_DIV20] 40*Mhz, + [SYSTEM_PLL2_CLK] 1000*Mhz, + [SYSTEM_PLL2_DIV2] 500*Mhz, + [SYSTEM_PLL2_DIV3] 333*Mhz, + [SYSTEM_PLL2_DIV4] 250*Mhz, + [SYSTEM_PLL2_DIV5] 200*Mhz, + [SYSTEM_PLL2_DIV6] 166*Mhz, + [SYSTEM_PLL2_DIV8] 125*Mhz, + [SYSTEM_PLL2_DIV10] 100*Mhz, + [SYSTEM_PLL2_DIV20] 50*Mhz, + [SYSTEM_PLL3_CLK] 1000*Mhz, + [AUDIO_PLL1_CLK] 650*Mhz, + [AUDIO_PLL2_CLK] 650*Mhz, + [VIDEO_PLL1_CLK] 594*Mhz, + [VIDEO_PLL2_CLK] 600*Mhz, + [OSC_32K_REF_CLK] 32000, + [OSC_25M_REF_CLK] 25*Mhz, + [OSC_27M_REF_CLK] 27*Mhz, + [EXT_CLK_1] 133*Mhz, + [EXT_CLK_2] 133*Mhz, + [EXT_CLK_3] 133*Mhz, + [EXT_CLK_4] 133*Mhz, +}; + +static char *input_clk_name[] = { + [ARM_PLL_CLK] "arm_pll_clk", + [GPU_PLL_CLK] "gpu_pll_clk", + [VPU_PLL_CLK] "vpu_pll_clk", + [DRAM_PLL1_CLK] "dram_pll1_clk", + [SYSTEM_PLL1_CLK] "system_pll1_clk", + [SYSTEM_PLL1_DIV2] "system_pll1_div2", + [SYSTEM_PLL1_DIV3] "system_pll1_div3", + [SYSTEM_PLL1_DIV4] "system_pll1_div4", + [SYSTEM_PLL1_DIV5] "system_pll1_div5", + [SYSTEM_PLL1_DIV6] "system_pll1_div6", + [SYSTEM_PLL1_DIV8] "system_pll1_div8", + [SYSTEM_PLL1_DIV10] "system_pll1_div10", + [SYSTEM_PLL1_DIV20] "system_pll1_div20", + [SYSTEM_PLL2_CLK] "system_pll2_clk", + [SYSTEM_PLL2_DIV2] "system_pll2_div2", + [SYSTEM_PLL2_DIV3] "system_pll2_div3", + [SYSTEM_PLL2_DIV4] "system_pll2_div4", + [SYSTEM_PLL2_DIV5] "system_pll2_div5", + [SYSTEM_PLL2_DIV6] "system_pll2_div6", + [SYSTEM_PLL2_DIV8] "system_pll2_div8", + [SYSTEM_PLL2_DIV10] "system_pll2_div10", + [SYSTEM_PLL2_DIV20] "system_pll2_div20", + [SYSTEM_PLL3_CLK] "system_pll3_clk", + [AUDIO_PLL1_CLK] "audio_pll1_clk", + [AUDIO_PLL2_CLK] "audio_pll2_clk", + [VIDEO_PLL1_CLK] "video_pll1_clk", + [VIDEO_PLL2_CLK] "video_pll2_clk", + [OSC_32K_REF_CLK] "osc_32k_ref_clk", + [OSC_25M_REF_CLK] "osc_25m_ref_clk", + [OSC_27M_REF_CLK] "osc_27m_ref_clk", + [EXT_CLK_1] "ext_clk_1", + [EXT_CLK_2] "ext_clk_2", + [EXT_CLK_3] "ext_clk_3", + [EXT_CLK_4] "ext_clk_4", +}; + +static char *root_clk_name[] = { + [ARM_A53_CLK_ROOT] "ccm_arm_a53_clk_root", + [ARM_M4_CLK_ROOT] "ccm_arm_m4_clk_root", + [VPU_A53_CLK_ROOT] "ccm_vpu_a53_clk_root", + [GPU_CORE_CLK_ROOT] "ccm_gpu_core_clk_root", + [GPU_SHADER_CLK_ROOT] "ccm_gpu_shader_clk_root", + [MAIN_AXI_CLK_ROOT] "ccm_main_axi_clk_root", + [ENET_AXI_CLK_ROOT] "ccm_enet_axi_clk_root", + [NAND_USDHC_BUS_CLK_ROOT] "ccm_nand_usdhc_bus_clk_root", + [VPU_BUS_CLK_ROOT] "ccm_vpu_bus_clk_root", + [DISPLAY_AXI_CLK_ROOT] "ccm_display_axi_clk_root", + [DISPLAY_APB_CLK_ROOT] "ccm_display_apb_clk_root", + [DISPLAY_RTRM_CLK_ROOT] "ccm_display_rtrm_clk_root", + [USB_BUS_CLK_ROOT] "ccm_usb_bus_clk_root", + [GPU_AXI_CLK_ROOT] "ccm_gpu_axi_clk_root", + [GPU_AHB_CLK_ROOT] "ccm_gpu_ahb_clk_root", + [NOC_CLK_ROOT] "ccm_noc_clk_root", + [NOC_APB_CLK_ROOT] "ccm_noc_apb_clk_root", + [AHB_CLK_ROOT] "ccm_ahb_clk_root", + [IPG_CLK_ROOT] "ccm_ipg_clk_root", + [AUDIO_AHB_CLK_ROOT] "ccm_audio_ahb_clk_root", + [AUDIO_IPG_CLK_ROOT] "ccm_audio_ipg_clk_root", + [MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_mipi_dsi_esc_rx_clk_root", + [MIPI_DSI_ESC_CLK_ROOT] "ccm_mipi_dsi_esc_clk_root", + [DRAM_ALT_CLK_ROOT] "ccm_dram_alt_clk_root", + [DRAM_APB_CLK_ROOT] "ccm_dram_apb_clk_root", + [VPU_G1_CLK_ROOT] "ccm_vpu_g1_clk_root", + [VPU_G2_CLK_ROOT] "ccm_vpu_g2_clk_root", + [DISPLAY_DTRC_CLK_ROOT] "ccm_display_dtrc_clk_root", + [DISPLAY_DC8000_CLK_ROOT] "ccm_display_dc8000_clk_root", + [PCIE1_CTRL_CLK_ROOT] "ccm_pcie1_ctrl_clk_root", + [PCIE1_PHY_CLK_ROOT] "ccm_pcie1_phy_clk_root", + [PCIE1_AUX_CLK_ROOT] "ccm_pcie1_aux_clk_root", + [DC_PIXEL_CLK_ROOT] "ccm_dc_pixel_clk_root", + [LCDIF_PIXEL_CLK_ROOT] "ccm_lcdif_pixel_clk_root", + [SAI1_CLK_ROOT] "ccm_sai1_clk_root", + [SAI2_CLK_ROOT] "ccm_sai2_clk_root", + [SAI3_CLK_ROOT] "ccm_sai3_clk_root", + [SAI4_CLK_ROOT] "ccm_sai4_clk_root", + [SAI5_CLK_ROOT] "ccm_sai5_clk_root", + [SAI6_CLK_ROOT] "ccm_sai6_clk_root", + [SPDIF1_CLK_ROOT] "ccm_spdif1_clk_root", + [SPDIF2_CLK_ROOT] "ccm_spdif2_clk_root", + [ENET_REF_CLK_ROOT] "ccm_enet_ref_clk_root", + [ENET_TIMER_CLK_ROOT] "ccm_enet_timer_clk_root", + [ENET_PHY_REF_CLK_ROOT] "ccm_enet_phy_ref_clk_root", + [NAND_CLK_ROOT] "ccm_nand_clk_root", + [QSPI_CLK_ROOT] "ccm_qspi_clk_root", + [USDHC1_CLK_ROOT] "ccm_usdhc1_clk_root", + [USDHC2_CLK_ROOT] "ccm_usdhc2_clk_root", + [I2C1_CLK_ROOT] "ccm_i2c1_clk_root", + [I2C2_CLK_ROOT] "ccm_i2c2_clk_root", + [I2C3_CLK_ROOT] "ccm_i2c3_clk_root", + [I2C4_CLK_ROOT] "ccm_i2c4_clk_root", + [UART1_CLK_ROOT] "ccm_uart1_clk_root", + [UART2_CLK_ROOT] "ccm_uart2_clk_root", + [UART3_CLK_ROOT] "ccm_uart3_clk_root", + [UART4_CLK_ROOT] "ccm_uart4_clk_root", + [USB_CORE_REF_CLK_ROOT] "ccm_usb_core_ref_clk_root", + [USB_PHY_REF_CLK_ROOT] "ccm_usb_phy_ref_clk_root", + [GIC_CLK_ROOT] "ccm_gic_clk_root", + [ECSPI1_CLK_ROOT] "ccm_ecspi1_clk_root", + [ECSPI2_CLK_ROOT] "ccm_ecspi2_clk_root", + [PWM1_CLK_ROOT] "ccm_pwm1_clk_root", + [PWM2_CLK_ROOT] "ccm_pwm2_clk_root", + [PWM3_CLK_ROOT] "ccm_pwm3_clk_root", + [PWM4_CLK_ROOT] "ccm_pwm4_clk_root", + [GPT1_CLK_ROOT] "ccm_gpt1_clk_root", + [GPT2_CLK_ROOT] "ccm_gpt2_clk_root", + [GPT3_CLK_ROOT] "ccm_gpt3_clk_root", + [GPT4_CLK_ROOT] "ccm_gpt4_clk_root", + [GPT5_CLK_ROOT] "ccm_gpt5_clk_root", + [GPT6_CLK_ROOT] "ccm_gpt6_clk_root", + [TRACE_CLK_ROOT] "ccm_trace_clk_root", + [WDOG_CLK_ROOT] "ccm_wdog_clk_root", + [WRCLK_CLK_ROOT] "ccm_wrclk_clk_root", + [IPP_DO_CLKO1] "ccm_ipp_do_clko1", + [IPP_DO_CLKO2] "ccm_ipp_do_clko2", + [MIPI_DSI_CORE_CLK_ROOT] "ccm_mipi_dsi_core_clk_root", + [MIPI_DSI_PHY_REF_CLK_ROOT] "ccm_mipi_dsi_phy_ref_clk_root", + [MIPI_DSI_DBI_CLK_ROOT] "ccm_mipi_dsi_dbi_clk_root", + [OLD_MIPI_DSI_ESC_CLK_ROOT] "ccm_old_mipi_dsi_esc_clk_root", + [MIPI_CSI1_CORE_CLK_ROOT] "ccm_mipi_csi1_core_clk_root", + [MIPI_CSI1_PHY_REF_CLK_ROOT] "ccm_mipi_csi1_phy_ref_clk_root", + [MIPI_CSI1_ESC_CLK_ROOT] "ccm_mipi_csi1_esc_clk_root", + [MIPI_CSI2_CORE_CLK_ROOT] "ccm_mipi_csi2_core_clk_root", + [MIPI_CSI2_PHY_REF_CLK_ROOT] "ccm_mipi_csi2_phy_ref_clk_root", + [MIPI_CSI2_ESC_CLK_ROOT] "ccm_mipi_csi2_esc_clk_root", + [PCIE2_CTRL_CLK_ROOT] "ccm_pcie2_ctrl_clk_root", + [PCIE2_PHY_CLK_ROOT] "ccm_pcie2_phy_clk_root", + [PCIE2_AUX_CLK_ROOT] "ccm_pcie2_aux_clk_root", + [ECSPI3_CLK_ROOT] "ccm_ecspi3_clk_root", + [OLD_MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_old_mipi_dsi_esc_rx_clk_root", + [DISPLAY_HDMI_CLK_ROOT] "ccm_display_hdmi_clk_root", +}; + +static uchar root_clk_input_mux[] = { +[ARM_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL3_CLK, +[ARM_M4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[VPU_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, VPU_PLL_CLK, +[GPU_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_SHADER_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[MAIN_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV8, +[ENET_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[NAND_USDHC_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, + SYSTEM_PLL1_DIV6, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL1_CLK, +[VPU_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, VPU_PLL_CLK, AUDIO_PLL2_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV8, +[DISPLAY_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_4, +[DISPLAY_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_3, +[DISPLAY_RTRM_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_2, EXT_CLK_3, +[USB_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[GPU_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AUDIO_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV6, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DRAM_ALT_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV3, +[DRAM_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[VPU_G1_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[VPU_G2_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[DISPLAY_DTRC_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[DISPLAY_DC8000_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[PCIE1_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE1_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE1_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[DC_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[LCDIF_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[SAI1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI3_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SAI4_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI5_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI6_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SPDIF1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SPDIF2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[ENET_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_4, +[ENET_TIMER_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, VIDEO_PLL1_CLK, +[ENET_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NAND_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, VIDEO_PLL1_CLK, +[QSPI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV8, +[USDHC1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[USDHC2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[I2C1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[UART1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[UART3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_CORE_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[GIC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[ECSPI1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[ECSPI2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[PWM1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[GPT1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[GPT4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT5_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT6_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[TRACE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, EXT_CLK_1, EXT_CLK_3, +[WDOG_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV6, +[WRCLK_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV20, VPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_DIV8, +[IPP_DO_CLKO1*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, OSC_27M_REF_CLK, SYSTEM_PLL1_DIV4, + AUDIO_PLL2_CLK, SYSTEM_PLL2_DIV2, VPU_PLL_CLK, SYSTEM_PLL1_DIV10, +[IPP_DO_CLKO2*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, SYSTEM_PLL2_DIV6, + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, OSC_32K_REF_CLK, +[MIPI_DSI_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_DBI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[MIPI_CSI2_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[PCIE2_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE2_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE2_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[ECSPI3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[OLD_MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DISPLAY_HDMI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV4, SYSTEM_PLL2_DIV5, VPU_PLL_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +}; + +typedef struct Clock Clock; +struct Clock { + char *name; /* clock instance name */ + int root; /* root clock slice */ + int ccgr; /* clock gating register */ +}; + +static Clock clocks[] = { + { "aips_tz1.hclk", AHB_CLK_ROOT, 28 }, + { "ipmux1.master_clk", AHB_CLK_ROOT, 28 }, + { "ipmux1.slave_clk", IPG_CLK_ROOT, 28 }, + + { "aips_tz2.hclk", AHB_CLK_ROOT, 29 }, + { "ipmux2.master_clk", AHB_CLK_ROOT, 29 }, + { "ipmux2.slave_clk", AHB_CLK_ROOT, 29 }, + + { "aips_tz3.hclk", AHB_CLK_ROOT, 30 }, + { "ipmux3.master_clk", AHB_CLK_ROOT, 30 }, + { "ipmux3.slave_clk", IPG_CLK_ROOT, 30 }, + + { "apbhdma.hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "apdhdma_sec.mst_hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_gpmi_bch_input_gpmi_io_clk", NAND_CLK_ROOT, 48 }, + { "rawnand.U_gpmi_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + + { "caam.aclk", AHB_CLK_ROOT }, + { "caam.ipg_clk", IPG_CLK_ROOT }, + { "caam.ipg_clk_s", IPG_CLK_ROOT }, + { "caam_exsc.aclk_exsc", AHB_CLK_ROOT }, + { "caam_mem.clk", AHB_CLK_ROOT }, + + { "cm4.cm4_cti_clk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_fclk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_hclk", ARM_M4_CLK_ROOT }, + { "cm4.dap_clk", AHB_CLK_ROOT }, + { "cm4.ipg_clk_nic", ARM_M4_CLK_ROOT }, + { "cm4.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_mem.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_sec.ipg_clk", IPG_CLK_ROOT }, + { "cm4_sec.ipg_clk_s", IPG_CLK_ROOT }, + { "cm4_sec.mst_hclk", ARM_M4_CLK_ROOT }, + + { "csi2_1.clk_vid", MIPI_CSI1_PHY_REF_CLK_ROOT }, + { "csi2_1.clk", MIPI_CSI1_CORE_CLK_ROOT, 101}, + { "csi2_1.clk_esc", MIPI_CSI1_ESC_CLK_ROOT, 101}, + { "csi2_1.pclk", MIPI_CSI1_CORE_CLK_ROOT }, + { "csi2_1.clk_ui", MIPI_CSI1_PHY_REF_CLK_ROOT, 101}, + + { "csi2_2.clk_vid", MIPI_CSI2_PHY_REF_CLK_ROOT }, + { "csi2_2.clk", MIPI_CSI2_CORE_CLK_ROOT, 102 }, + { "csi2_2.clk_esc", MIPI_CSI2_ESC_CLK_ROOT, 102 }, + { "csi2_2.pclk", MIPI_CSI2_CORE_CLK_ROOT }, + { "csi2_2.clk_ui", MIPI_CSI2_PHY_REF_CLK_ROOT, 102 }, + + { "csu.ipg_clk_s", IPG_CLK_ROOT, 3}, + + { "dap.dapclk_2_2", AHB_CLK_ROOT, 4}, + + { "ecspi1.ipg_clk", IPG_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_per", ECSPI1_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_s", IPG_CLK_ROOT, 7}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi3.ipg_clk", IPG_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_per", ECSPI3_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_s", IPG_CLK_ROOT, 9}, + + { "enet1.ipp_ind_mac0_txclk", ENET_REF_CLK_ROOT, 10 }, + { "enet1.ipg_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_time", ENET_TIMER_CLK_ROOT, 10 }, + { "enet1.mem.mac0_rxmem_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.mem.mac0_txmem_clk", ENET_AXI_CLK_ROOT, 10 }, + + { "gpio1.ipg_clk_s", IPG_CLK_ROOT, 11 }, + { "gpio2.ipg_clk_s", IPG_CLK_ROOT, 12 }, + { "gpio3.ipg_clk_s", IPG_CLK_ROOT, 13 }, + { "gpio4.ipg_clk_s", IPG_CLK_ROOT, 14 }, + { "gpio5.ipg_clk_s", IPG_CLK_ROOT, 15 }, + + { "gpt1.ipg_clk", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_highfreq", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_s", GPT1_CLK_ROOT, 16 }, + + { "gpt2.ipg_clk", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_highfreq", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_s", GPT2_CLK_ROOT, 17 }, + + { "gpt3.ipg_clk", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_highfreq", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_s", GPT3_CLK_ROOT, 18 }, + + { "gpt4.ipg_clk", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_highfreq", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_s", GPT4_CLK_ROOT, 19 }, + + { "gpt5.ipg_clk", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_highfreq", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_s", GPT5_CLK_ROOT, 20 }, + + { "gpt6.ipg_clk", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_highfreq", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_s", GPT6_CLK_ROOT, 21 }, + + { "i2c1.ipg_clk_patref", I2C1_CLK_ROOT, 23 }, + { "i2c1.iph_clk_s", I2C1_CLK_ROOT, 23 }, + + { "i2c2.ipg_clk_patref", I2C2_CLK_ROOT, 24 }, + { "i2c2.iph_clk_s", I2C2_CLK_ROOT, 24 }, + + { "i2c3.ipg_clk_patref", I2C3_CLK_ROOT, 25 }, + { "i2c3.iph_clk_s", I2C3_CLK_ROOT, 25 }, + + { "i2c4.ipg_clk_patref", I2C4_CLK_ROOT, 26 }, + { "i2c4.iph_clk_s", I2C4_CLK_ROOT, 26 }, + + { "iomuxc.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomuxc_gpr.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomux.ipt_clk_io", IPG_CLK_ROOT, 27 }, + + { "lcdif.pix_clk", LCDIF_PIXEL_CLK_ROOT }, + { "lcdif.apb_clk", MAIN_AXI_CLK_ROOT }, + + { "disp.apb_clk", DISPLAY_APB_CLK_ROOT, 93 }, + { "disp.axi_clk", DISPLAY_AXI_CLK_ROOT, 93 }, + { "disp.rtrm_clk", DISPLAY_RTRM_CLK_ROOT, 93 }, + { "disp.dc8000_clk", DISPLAY_DC8000_CLK_ROOT, 93 }, + { "disp.dtrc_clk", DISPLAY_DTRC_CLK_ROOT }, + + { "mipi.CLKREF", MIPI_DSI_PHY_REF_CLK_ROOT }, + { "mipi.pclk", MAIN_AXI_CLK_ROOT }, + { "mipi.RxClkEsc", MIPI_DSI_ESC_RX_CLK_ROOT }, + { "mipi.TxClkEsc", MIPI_DSI_ESC_CLK_ROOT }, + { "mipi.core", MIPI_DSI_CORE_CLK_ROOT }, + { "mipi.ahb", MIPI_DSI_ESC_RX_CLK_ROOT }, + + { "mu.ipg_clk_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_mcu", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_mcu", IPG_CLK_ROOT, 33 }, + + { "ocotp.ipg_clk", IPG_CLK_ROOT, 34 }, + { "ocotp.ipg_clk_s", IPG_CLK_ROOT, 34 }, + + { "ocram_ctrl.clk", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_excs.aclk_exsc", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_exsc.ipg_clk", IPG_CLK_ROOT, 35 }, + { "ocram_mem.clk", MAIN_AXI_CLK_ROOT, 35 }, + + { "ocram_ctrl_s.clk", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.aclk_exsc", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.ipg_clk", IPG_CLK_ROOT, 36 }, + { "ocram_s.mem_clk", AHB_CLK_ROOT, 36 }, + + { "pcie_clk_rst.auxclk", PCIE1_AUX_CLK_ROOT, 37 }, + { "pcie_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.ipg_clk", IPG_CLK_ROOT, 37 }, + { "pcie_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + + { "pcie2_clk_rst.auxclk", PCIE2_AUX_CLK_ROOT, 100 }, + { "pcie2_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.ipg_clk", IPG_CLK_ROOT, 100 }, + { "pcie2_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + + { "pcie_phy.ref_alt_clk_p", PCIE1_PHY_CLK_ROOT }, + { "pcie2_phy.ref_alt_clk_p", PCIE2_PHY_CLK_ROOT }, + + { "perfmon1.apb_clk", IPG_CLK_ROOT, 38 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 38 }, + + { "perfmon2.apb_clk", IPG_CLK_ROOT, 39 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 39 }, + + { "pwm1.ipg_clk", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_high_freq", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_s", PWM1_CLK_ROOT, 40 }, + + { "pwm2.ipg_clk", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_high_freq", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_s", PWM2_CLK_ROOT, 41 }, + + { "pwm3.ipg_clk", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_high_freq", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_s", PWM3_CLK_ROOT, 42 }, + + { "pwm4.ipg_clk", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_high_freq", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_s", PWM4_CLK_ROOT, 43 }, + + { "qspi.ahb_clk", AHB_CLK_ROOT, 47 }, + { "qspi.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi.ipg_clk_4xsfif", QSPI_CLK_ROOT, 47 }, + { "qspi.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.mst_hclk", AHB_CLK_ROOT, 47 }, + + { "rdc.ipg_clk_s", IPG_CLK_ROOT, 49 }, + { "rdc.ipg_clk", IPG_CLK_ROOT, 49 }, + { "rdc_mem.ipg_clk", IPG_CLK_ROOT, 49 }, + + { "romcp.hclk", AHB_CLK_ROOT, 50 }, + { "romcp.hclk_reg", IPG_CLK_ROOT, 50 }, + { "romcp_mem.rom_CLK", AHB_CLK_ROOT, 50 }, + { "romcp_sec.mst_hclk", AHB_CLK_ROOT, 50 }, + + { "sai1.ipg_clk", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_sai_mclk_1", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 51 }, + + { "sai2.ipg_clk", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_sai_mclk_1", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 52 }, + + { "sai3.ipg_clk", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_sai_mclk_1", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 53 }, + + { "sai4.ipg_clk", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_sai_mclk_1", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 54 }, + + { "sai5.ipg_clk", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_sai_mclk_1", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 55 }, + + { "sai6.ipg_clk", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_sai_mclk_1", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 56 }, + + { "sctr.ipg_clk", IPG_CLK_ROOT, 57 }, + { "sctr.ipg_clk_s", IPG_CLK_ROOT, 57 }, + + { "sdma1.ips_hostctrl_clk", IPG_CLK_ROOT, 58 }, + { "sdma1.sdma_ap_ahb_clk", AHB_CLK_ROOT, 58 }, + { "sdma1.sdma_core_clk", IPG_CLK_ROOT, 58 }, + + { "sdma2.ips_hostctrl_clk", AUDIO_IPG_CLK_ROOT, 59 }, + { "sdma2.sdma_ap_ahb_clk", AUDIO_AHB_CLK_ROOT, 59 }, + { "sdma2.sdma_core_clk", AUDIO_IPG_CLK_ROOT, 59 }, + + { "sec_wrapper.clk", IPG_CLK_ROOT, 60 }, + + { "sema1.clk", IPG_CLK_ROOT, 61 }, + { "sema2.clk", IPG_CLK_ROOT, 62 }, + + { "sim_display.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_display.mainclk", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_display.mainclk_r", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_enet.mainclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_enet.mainclk_r", ENET_AXI_CLK_ROOT, 64 }, + { "sim_m.mainclk", AHB_CLK_ROOT, 65 }, + { "sim_m.mainclk_r", AHB_CLK_ROOT, 65 }, + { "sim_m.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_m.usdhcclk_r", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_main.enetclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_main.mainclk", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main,mainclk_r", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main.per_mclk", AHB_CLK_ROOT, 65 }, + { "sim_main.per_sclk", AHB_CLK_ROOT, 67 }, + { "sim_main.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.wakeupclk", AHB_CLK_ROOT, 68 }, + { "sim_s.apbhdmaclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "sim_s.gpv4clk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_s.mainclk", AHB_CLK_ROOT, 67 }, + { "sim_s.mainclk_r", AHB_CLK_ROOT, 67 }, + { "sim_s.weimclk", AHB_CLK_ROOT }, + { "sim_wakeup.mainclk", AHB_CLK_ROOT, 68 }, + { "sim_wakeup.mainclk_r", AHB_CLK_ROOT, 68 }, + { "pl301_audio.displayclk", MAIN_AXI_CLK_ROOT, 63 }, + + { "snvs_hs_wrapper.ipg_clk", IPG_CLK_ROOT, 71 }, + { "snvs_hs.wrapper.ipg_clk_s", IPG_CLK_ROOT, 71 }, + { "snvsmix.ipg_clk_root", IPG_CLK_ROOT }, + + { "spba1.ipg_clk", IPG_CLK_ROOT, 30 }, + { "spba1.ipg_clk_s", IPG_CLK_ROOT, 30 }, + + { "spba2.ipg_clk", AUDIO_IPG_CLK_ROOT }, + { "spba2.ipg_clk_s", AUDIO_IPG_CLK_ROOT }, + + { "spdif1.gclkw_t0", SPDIF1_CLK_ROOT}, + { "spdif1.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif1.tx_clk", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk1", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk3", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk4", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk5", SPDIF1_CLK_ROOT}, + + { "spdif2.gclkw_t0", SPDIF2_CLK_ROOT}, + { "spdif2.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif2.tx_clk", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk1", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk3", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk4", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk5", SPDIF2_CLK_ROOT}, + + { "coresight.DBGCLK", MAIN_AXI_CLK_ROOT, 72 }, + { "coresight.traceclkin", TRACE_CLK_ROOT, 72 }, + { "coresight_mem.cs_etf_clk", MAIN_AXI_CLK_ROOT, 72 }, + + { "uart1.ipg_clk", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_clk_s", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_perclk", UART1_CLK_ROOT, 73 }, + + { "uart2.ipg_clk", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_clk_s", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_perclk", UART2_CLK_ROOT, 74 }, + + { "uart3.ipg_clk", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_clk_s", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_perclk", UART3_CLK_ROOT, 75 }, + + { "uart4.ipg_clk", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_clk_s", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_perclk", UART4_CLK_ROOT, 76 }, + + { "usb.clk", IPG_CLK_ROOT, 22 }, /* HS */ + + { "usb1.ctrl", IPG_CLK_ROOT, 77 }, /* what is the root clock? */ + { "usb2.ctrl", IPG_CLK_ROOT, 78 }, + { "usb1.phy", IPG_CLK_ROOT, 79 }, /* what is the root clock? */ + { "usb2.phy", IPG_CLK_ROOT, 80 }, + + { "usdhc1.hclk", NAND_USDHC_BUS_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_s", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_perclk", USDHC1_CLK_ROOT, 81 }, + + { "usdhc2.hclk", NAND_USDHC_BUS_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_s", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_perclk", USDHC2_CLK_ROOT, 82 }, + + { "wdog1.ipg_clk", WDOG_CLK_ROOT, 83 }, + { "wdog1.ipg_clk_s", WDOG_CLK_ROOT, 83 }, + + { "wdog2.ipg_clk", WDOG_CLK_ROOT, 84 }, + { "wdog2.ipg_clk_s", WDOG_CLK_ROOT, 84 }, + + { "wdog3.ipg_clk", WDOG_CLK_ROOT, 85 }, + { "wdog3.ipg_clk_s", WDOG_CLK_ROOT, 85 }, + + { 0 } +}; + +static void +enablefracpll(u32int *reg, int ref_sel, int ref_freq, int freq) +{ + int divq, divr, ref, divfi, divff, pllout, error; + u32int cfg0, cfg1; + vlong v; + + cfg0 = reg[0]; + cfg1 = reg[1]; + + error = freq; + for(divq = 2; divq <= 64; divq += 2){ + for(divr = 1; divr <= 64; divr++){ + ref = ref_freq/divr; + if(ref < 10*Mhz || ref > 300*Mhz) + continue; + + ref *= 8; + divfi = ((vlong)freq*divq) / ref; + if(divfi < 1 || divfi > 32) + continue; + + v = ((vlong)freq*divq) - (vlong)ref*divfi; + divff = (v<<24) / ref; + if(divff < 1 || divff > (1<<24)) + continue; + + v = (vlong)ref*(vlong)divff; + pllout = (ref*divfi + (v>>24))/divq; + if(pllout < 30*Mhz || pllout > 2000*Mhz) + continue; + + if(pllout > freq) + continue; + + if(freq - pllout > error) + continue; + +// iprint("%p enablefracpll: freq=%d (actual %d)\n", PADDR(reg), freq, pllout); + + cfg0 = 1<<21 | ref_sel<<16 | 1<<15 | (divr-1)<<5 | (divq/2)-1; + cfg1 = divff<<7 | divfi-1; + + error = freq - pllout; + if(error == 0) + goto Found; + } + } + +Found: + /* skip if nothing has changed */ + if(((reg[0] ^ cfg0) & (1<<21 | 3<<16 | 1<<15 | 0x3F<<5 | 0x1F)) == 0 + && ((reg[1] ^ cfg1) & ~(1<<31)) == 0) + return; + + reg[0] |= 1<<14; /* bypass */ + +// iprint("%p cfg1=%.8ux\n", PADDR(reg), cfg1); + reg[1] = cfg1; + +// iprint("%p cfg0=%.8ux\n", PADDR(reg), cfg0); + reg[0] = cfg0 | (1<<14) | (1<<12); + + /* unbypass */ + reg[0] &= ~(1<<14); + +// iprint("%p wait for lock...", PADDR(reg)); + while((reg[0] & (1<<31)) == 0) + ; +// iprint("locked!\n"); + reg[0] &= ~(1<<12); +} + +static void +enablepll(int input) +{ + u32int old, val = 2; + + if(input < 0 || input > 38 || input_clk_freq[input] <= 0) + return; + + /* CCM_PLL_CTRL */ + old = regs[(0x800/4) + (16/4)*input] & 3; + if(old < val){ +// iprint("ccm: %s PLL_CTRL%d %.ux->%.ux\n", input_clk_name[input], input, old, val); + regs[(0x800/4) + (16/4)*input] = val; + } + + switch(input){ + case AUDIO_PLL1_CLK: + enablefracpll(&anatop[0x00/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case AUDIO_PLL2_CLK: + enablefracpll(&anatop[0x08/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VIDEO_PLL1_CLK: + enablefracpll(&anatop[0x10/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case GPU_PLL_CLK: + enablefracpll(&anatop[0x18/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VPU_PLL_CLK: + enablefracpll(&anatop[0x20/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case ARM_PLL_CLK: + enablefracpll(&anatop[0x28/4], 0, 25*Mhz, input_clk_freq[input]); + break; + } +} + +static u32int +clkgate(Clock *gate, u32int val) +{ + u32int old; + + if(gate == nil || gate->ccgr == 0) + return 0; + + /* CCM_CCGR */ + old = regs[(0x4000/4) + (16/4)*gate->ccgr] & 3; + if(old != val){ +// if(gate->ccgr != 73) iprint("ccm: %s CCGR%d %.ux->%.ux\n", gate->name, gate->ccgr, old, val); + regs[(0x4000/4) + (16/4)*gate->ccgr] = val; + } + return old; +} + +static int +rootclkisipg(int root) +{ + switch(root){ + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + case MIPI_DSI_ESC_CLK_ROOT: + return 1; + } + return 0; +} + +static u32int +gettarget(int root) +{ + u32int val = regs[(0x8000/4) + (128/4)*root]; +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d -> %.8ux\n", root_clk_name[root], root, val); + return val; +} + +static void +settarget(int root, Clock *gate, u32int val) +{ + if(gate != nil){ + for(; gate->name != nil; gate++){ + u32int old; + + if(gate->root != root) + continue; + + old = clkgate(gate, 0); + if(old == 0) + continue; + + /* skip restore when root is being disabled */ + if((val & (1<<28)) == 0) + continue; + + /* now change the root clock target */ + settarget(root, gate+1, val); + + /* restore gate */ + clkgate(gate, old); + return; + } + } + + if(rootclkisipg(root)) + val &= ~(1<<28); +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d <- %.8ux\n", root_clk_name[root], root, val); + regs[(0x8000/4) + (128/4)*root] = val; +} + +static int +rootclkgetcfg(int root, int *input) +{ + u32int t = gettarget(root); + int freq = input_clk_freq[*input = root_clk_input_mux[root*8 + ((t >> 24)&7)]]; + int pre_podf = (t >> 16)&7; + int post_podf = (t >> 0)&0x3F; + + /* return negative frequency if disabled */ + if((t & (1<<28)) == 0) + freq = -freq; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_podf &= 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_podf = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_podf &= 1; + case MIPI_DSI_ESC_CLK_ROOT: + freq = rootclkgetcfg(root-1, input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_podf = 0; + break; + } + freq /= pre_podf+1; + freq /= post_podf+1; + + return freq; +} + +static void +rootclksetcfg(int root, int input, int freq) +{ + u32int t = gettarget(root); + + if(!rootclkisipg(root)){ + int mux; + + for(mux = 0; mux < 8; mux++){ + if(root_clk_input_mux[root*8 + mux] == input){ + t = (t & ~(7<<24)) | (mux << 24); + goto Muxok; + } + } + panic("rootclksetcfg: invalid input clock %d for TARGET_ROOT%d\n", input, root); +Muxok:; + } + /* disable by default */ + t &= ~(1 << 28); + + if(freq){ + int pre_mask, pre_podf, post_mask, post_podf; + int error, input_freq = input_clk_freq[input]; + + if(freq < 0) { + /* set dividers but keep disabled */ + freq = -freq; + } else { + /* set dividers and enable */ + t |= (1 << 28); + } + + pre_mask = 7; + post_mask = 0x3F; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_mask = 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_mask = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_mask = 1; + case MIPI_DSI_ESC_CLK_ROOT: + input_freq = rootclkgetcfg(root-1, &input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_mask = 0; + break; + } + if(input_freq < 0) input_freq = -input_freq; + + + error = freq; + for(pre_podf = 0; pre_podf <= pre_mask; pre_podf++){ + for(post_podf = 0; post_podf <= post_mask; post_podf++){ + int f = input_freq; + f /= pre_podf+1; + f /= post_podf+1; + if(f <= freq && (freq - f) < error){ + t = (t & ~(7<<16)) | (pre_podf << 16); + t = (t & ~0x3F) | post_podf; + error = freq - f; + if(error == 0) + break; + } + } + } + if(error >= freq) + panic("rootclksetcfg: frequency %d invalid for TARGET_ROOT%d\n", freq, root); + if(t & (1<<28)) + enablepll(input); + } + settarget(root, clocks, t); +} + +static int +lookinputclk(char *name) +{ + int i; + + for(i = 0; i < nelem(input_clk_name); i++){ + if(input_clk_name[i] != nil + && cistrcmp(name, input_clk_name[i]) == 0) + return i; + } + + return -1; +} + +static Clock* +lookmodclk(char *name) +{ + Clock *clk; + + for(clk = clocks; clk->name != nil; clk++){ + if(cistrcmp(name, clk->name) == 0) + return clk; + } + + return nil; +} + +static int +lookrootclk(char *name) +{ + Clock *clk; + int i; + + for(i = 0; i < nelem(root_clk_name); i++){ + if(root_clk_name[i] != nil + && cistrcmp(name, root_clk_name[i]) == 0) + return i; + } + + if((clk = lookmodclk(name)) != nil) + return clk->root; + + return -1; +} + +void +setclkgate(char *name, int on) +{ + clkgate(lookmodclk(name), on ? 3 : 0); +} + +void +setclkrate(char *name, char *source, int freq) +{ + int root, input; + + if((root = lookrootclk(name)) < 0) + panic("setclkrate: clock %s not defined", name); + if(source == nil) + rootclkgetcfg(root, &input); + else { + if((input = lookinputclk(source)) < 0) + panic("setclkrate: input clock %s not defined", source); + } + rootclksetcfg(root, input, freq); +} + +int +getclkrate(char *name) +{ + int root, input; + + if((root = lookrootclk(name)) >= 0) + return rootclkgetcfg(root, &input); + + if((input = lookinputclk(name)) > 0) + return input_clk_freq[input]; + + panic("getclkrate: clock %s not defined", name); + return -1; +} diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index 7a78c4c9d..893b04455 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -688,6 +688,16 @@ pnp(Ether *edev) edev->mbps = 1000; edev->maxmtu = Maxtu; + setclkgate("enet1.ipp_ind_mac0_txclk", 0); + setclkgate("sim_enet.mainclk", 0); + + setclkrate("enet1.ipg_clk", "system_pll1_div3", 266*Mhz); + setclkrate("enet1.ipp_ind_mac0_txclk", "system_pll2_div8", Moduleclk); + setclkrate("enet1.ipg_clk_time", "system_pll2_div10", 25*Mhz); + + setclkgate("enet1.ipp_ind_mac0_txclk", 1); + setclkgate("sim_enet.mainclk", 1); + if(reset(edev) < 0) return -1; diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 146216073..31baa25c9 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -80,6 +80,7 @@ extern void meminit(void); extern void putasid(Proc*); extern void* ucalloc(usize); +extern void* fbmemalloc(usize); /* clock */ extern void clockinit(void); @@ -138,3 +139,11 @@ extern void writeconf(void); extern int isaconfig(char*, int, ISAConf*); extern void links(void); + +/* ccm */ +extern void setclkgate(char *name, int on); +extern void setclkrate(char *name, char *source, int freq); +extern int getclkrate(char *name); + +/* lcd */ +extern void lcdinit(void); diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c new file mode 100644 index 000000000..d54d667b6 --- /dev/null +++ b/sys/src/9/imx8/lcd.c @@ -0,0 +1,949 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/i2c.h" + +#define Image IMAGE +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +extern Memimage *gscreen; + +/* pinmux registers */ +enum { + IOMUXC_CTL_PAD_SAI5_RXC = 0x144/4, /* for gpio3 20 */ + IOMUXC_CTL_PAD_SPDIF_RX = 0x1EC/4, /* for pwm2 */ + IOMUXC_CTL_PAD_GPIO1_IO10 = 0x50/4, /* for gpio1 10 */ + SION = 1<<4, + MUX_MODE = 7, + + IOMUXC_GPR_GPR13 = 0x10034/4, /* GPR13 for MIPI_MUX_SEL */ + MIPI_MUX_SEL = 1<<2, + MIPI_MUX_INV = 1<<3, +}; + +/* gpio registers */ +enum { + GPIO_DR = 0x00/4, + GPIO_GDIR = 0x04/4, + GPIO_PSR = 0x08/4, + GPIO_ICR1 = 0x0C/4, + GPIO_ICR2 = 0x10/4, + GPIO_IMR = 0x14/4, + GPIO_ISR = 0x18/4, + GPIO_EDGE_SEL = 0x1C/4, +}; + +/* power gating controller registers */ +enum { + GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, + GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, + + GPC_A53_PU_PGC_PUP_STATUS0 = 0x1C4/4, + GPC_A53_PU_PGC_PUP_STATUS1 = 0x1C8/4, + GPC_A53_PU_PGC_PUP_STATUS2 = 0x1CC/4, + DISP_SW_PUP_REQ = 1<<10, + HDMI_SW_PUP_REQ = 1<<9, + MIPI_SW_PUP_REQ = 1<<0, +}; + +/* system reset controller registers */ +enum { + SRC_MIPIPHY_RCR = 0x28/4, + RCR_MIPI_DSI_PCLK_RESET_N = 1<<5, + RCR_MIPI_DSI_ESC_RESET_N = 1<<4, + RCR_MIPI_DSI_DPI_RESET_N = 1<<3, + RCR_MIPI_DSI_RESET_N = 1<<2, + RCR_MIPI_DSI_RESET_BYTE_N = 1<<1, + + SRC_DISP_RCR = 0x34/4, +}; + +/* pwm controller registers */ +enum { + Pwmsrcclk = 25*Mhz, + + PWMCR = 0x00/4, + CR_FWM_1 = 0<<26, + CR_FWM_2 = 1<<26, + CR_FWM_3 = 2<<26, + CR_FWM_4 = 3<<26, + + CR_STOPEN = 1<<25, + CR_DOZEN = 1<<24, + CR_WAITEN = 1<<23, + CR_DBGEN = 1<<22, + CR_BCTR = 1<<21, + CR_HCTR = 1<<20, + + CR_POUTC = 1<<18, + + CR_CLKSRC_OFF = 0<<16, + CR_CLKSRC_IPG = 1<<16, + CR_CLKSRC_HIGHFREQ = 2<<16, + CR_CLKSRC_32K = 3<<16, + + CR_PRESCALER_SHIFT = 4, + + CR_SWR = 1<<3, + + CR_REPEAT_1 = 0<<1, + CR_REPEAT_2 = 1<<1, + CR_REPEAT_4 = 2<<1, + CR_REPEAT_8 = 3<<1, + + CR_EN = 1<<0, + + PWMSR = 0x04/4, + PWMIR = 0x08/4, + PWMSAR = 0x0C/4, + SAR_MASK = 0xFFFF, + PWMPR = 0x10/4, + PR_MASK = 0xFFFF, + PWMCNR = 0x14/4, + CNR_MASK = 0xFFFF, +}; + +/* dphy registers */ +enum { + DPHY_PD_PHY = 0x0/4, + DPHY_M_PRG_HS_PREPARE = 0x4/4, + DPHY_MC_PRG_HS_PREPARE = 0x8/4, + DPHY_M_PRG_HS_ZERO = 0xc/4, + DPHY_MC_PRG_HS_ZERO = 0x10/4, + DPHY_M_PRG_HS_TRAIL = 0x14/4, + DPHY_MC_PRG_HS_TRAIL = 0x18/4, + DPHY_PD_PLL = 0x1c/4, + DPHY_TST = 0x20/4, + DPHY_CN = 0x24/4, + DPHY_CM = 0x28/4, + DPHY_CO = 0x2c/4, + DPHY_LOCK = 0x30/4, + DPHY_LOCK_BYP = 0x34/4, + DPHY_RTERM_SEL = 0x38/4, + DPHY_AUTO_PD_EN = 0x3c/4, + DPHY_RXLPRP = 0x40/4, + DPHY_RXCDR = 0x44/4, + DPHY_RXHS_SETTLE = 0x48/4, /* undocumented */ +}; + +/* dsi-host registers */ +enum { + DSI_HOST_CFG_NUM_LANES = 0x0/4, + DSI_HOST_CFG_NONCONTINUOUS_CLK = 0x4/4, + DSI_HOST_CFG_AUTOINSERT_EOTP = 0x14/4, + DSI_HOST_CFG_T_PRE = 0x8/4, + DSI_HOST_CFG_T_POST = 0xc/4, + DSI_HOST_CFG_TX_GAP = 0x10/4, + DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP = 0x18/4, + DSI_HOST_CFG_HTX_TO_COUNT = 0x1c/4, + DSI_HOST_CFG_LRX_H_TO_COUNT = 0x20/4, + DSI_HOST_CFG_BTA_H_TO_COUNT = 0x24/4, + DSI_HOST_CFG_TWAKEUP = 0x28/4, + + DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING = 0x208/4, + DSI_HOST_CFG_DPI_PIXEL_FORMAT = 0x20c/4, + DSI_HOST_CFG_DPI_VSYNC_POLARITY = 0x210/4, + DSI_HOST_CFG_DPI_HSYNC_POLARITY = 0x214/4, + DSI_HOST_CFG_DPI_VIDEO_MODE = 0x218/4, + DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL = 0x204/4, + DSI_HOST_CFG_DPI_HFP = 0x21c/4, + DSI_HOST_CFG_DPI_HBP = 0x220/4, + DSI_HOST_CFG_DPI_HSA = 0x224/4, + DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS = 0x228/4, + DSI_HOST_CFG_DPI_BLLP_MODE = 0x234/4, + DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP = 0x238/4, + DSI_HOST_CFG_DPI_VC = 0x240/4, + DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE = 0x200/4, + DSI_HOST_CFG_DPI_VACTIVE = 0x23c/4, + DSI_HOST_CFG_DPI_VBP = 0x22c/4, + DSI_HOST_CFG_DPI_VFP = 0x230/4, +}; + +/* lcdif registers */ +enum { + LCDIF_CTRL = 0x00/4, + LCDIF_CTRL_SET = 0x04/4, + LCDIF_CTRL_CLR = 0x08/4, + LCDIF_CTRL_TOG = 0x0C/4, + CTRL_SFTRST = 1<<31, + CTRL_CLKGATE = 1<<30, + CTRL_YCBCR422_INPUT = 1<<29, + CTRL_READ_WEITEB = 1<<28, + CTRL_WAIT_FOR_VSYNC_EDGE = 1<<27, + CTRL_DATA_SHIFT_DIR = 1<<26, + CTRL_SHIFT_NUM_BITS = 0x1F<<21, + CTRL_DVI_MODE = 1<<20, + CTRL_BYPASS_COUNT = 1<<19, + CTRL_VSYNC_MODE = 1<<18, + CTRL_DOTCLK_MODE = 1<<17, + CTRL_DATA_SELECT = 1<<16, + + CTRL_INPUT_DATA_NO_SWAP = 0<<14, + CTRL_INPUT_DATA_LITTLE_ENDIAN = 0<<14, + CTRL_INPUT_DATA_BIG_ENDIAB = 1<<14, + CTRL_INPUT_DATA_SWAP_ALL_BYTES = 1<<14, + CTRL_INPUT_DATA_HWD_SWAP = 2<<14, + CTRL_INPUT_DATA_HWD_BYTE_SWAP = 3<<14, + + CTRL_CSC_DATA_NO_SWAP = 0<<12, + CTRL_CSC_DATA_LITTLE_ENDIAN = 0<<12, + CTRL_CSC_DATA_BIG_ENDIAB = 1<<12, + CTRL_CSC_DATA_SWAP_ALL_BYTES = 1<<12, + CTRL_CSC_DATA_HWD_SWAP = 2<<12, + CTRL_CSC_DATA_HWD_BYTE_SWAP = 3<<12, + + CTRL_LCD_DATABUS_WIDTH_16_BIT = 0<<10, + CTRL_LCD_DATABUS_WIDTH_8_BIT = 1<<10, + CTRL_LCD_DATABUS_WIDTH_18_BIT = 2<<10, + CTRL_LCD_DATABUS_WIDTH_24_BIT = 3<<10, + + CTRL_WORD_LENGTH_16_BIT = 0<<8, + CTRL_WORD_LENGTH_8_BIT = 1<<8, + CTRL_WORD_LENGTH_18_BIT = 2<<8, + CTRL_WORD_LENGTH_24_BIT = 3<<8, + + CTRL_RGB_TO_YCBCR422_CSC = 1<<7, + + CTRL_MASTER = 1<<5, + + CTRL_DATA_FORMAT_16_BIT = 1<<3, + CTRL_DATA_FORMAT_18_BIT = 1<<2, + CTRL_DATA_FORMAT_24_BIT = 1<<1, + + CTRL_RUN = 1<<0, + + LCDIF_CTRL1 = 0x10/4, + LCDIF_CTRL1_SET = 0x14/4, + LCDIF_CTRL1_CLR = 0x18/4, + LCDIF_CTRL1_TOG = 0x1C/4, + CTRL1_COMBINE_MPU_WR_STRB = 1<<27, + CTRL1_BM_ERROR_IRQ_EN = 1<<26, + CTRL1_BM_ERROR_IRQ = 1<<25, + CTRL1_RECOVER_ON_UNDERFLOW = 1<<24, + + CTRL1_INTERLACE_FIELDS = 1<<23, + CTRL1_START_INTERLACE_FROM_SECOND_FIELD = 1<<22, + + CTRL1_FIFO_CLEAR = 1<<21, + CTRL1_IRQ_ON_ALTERNATE_FIELDS = 1<<20, + + CTRL1_BYTE_PACKING_FORMAT = 0xF<<16, + + CTRL1_OVERFLOW_IRQ_EN = 1<<15, + CTRL1_UNDERFLOW_IRQ_EN = 1<<14, + CTRL1_CUR_FRAME_DONE_IRQ_EN = 1<<13, + CTRL1_VSYNC_EDGE_IRQ_EN = 1<<12, + CTRL1_OVERFLOW_IRQ = 1<<11, + CTRL1_UNDERFLOW_IRQ = 1<<10, + CTRL1_CUR_FRAME_DONE_IRQ = 1<<9, + CTRL1_VSYNC_EDGE_IRQ = 1<<8, + + CTRL1_BUSY_ENABLE = 1<<2, + CTRL1_MODE86 = 1<<1, + CTRL1_RESET = 1<<0, + + LCDIF_CTRL2 = 0x20/4, + LCDIF_CTRL2_SET = 0x24/4, + LCDIF_CTRL2_CLR = 0x28/4, + LCDIF_CTRL2_TOG = 0x2C/4, + CTRL2_OUTSTANDING_REQS_REQ_1 = 0<<21, + CTRL2_OUTSTANDING_REQS_REQ_2 = 1<<21, + CTRL2_OUTSTANDING_REQS_REQ_4 = 2<<21, + CTRL2_OUTSTANDING_REQS_REQ_8 = 3<<21, + CTRL2_OUTSTANDING_REQS_REQ_16 = 4<<21, + + CTRL2_BURST_LEN_8 = 1<<20, + + CTRL2_ODD_LINE_PATTERN_RGB = 0<<16, + CTRL2_ODD_LINE_PATTERN_RBG = 1<<16, + CTRL2_ODD_LINE_PATTERN_GBR = 2<<16, + CTRL2_ODD_LINE_PATTERN_GRB = 3<<16, + CTRL2_ODD_LINE_PATTERN_BRG = 4<<16, + CTRL2_ODD_LINE_PATTERN_BGR = 5<<16, + + CTRL2_EVEN_LINE_PATTERN_RGB = 0<<12, + CTRL2_EVEN_LINE_PATTERN_RBG = 1<<12, + CTRL2_EVEN_LINE_PATTERN_GBR = 2<<12, + CTRL2_EVEN_LINE_PATTERN_GRB = 3<<12, + CTRL2_EVEN_LINE_PATTERN_BRG = 4<<12, + CTRL2_EVEN_LINE_PATTERN_BGR = 5<<12, + + CTRL2_READ_PACK_DIR = 1<<10, + + CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT = 1<<9, + CTRL2_READ_MODE_6_BIT_INPUT = 1<<8, + CTRL2_READ_MODE_NUM_PACKED_SUBWORDS = 7<<4, + CTRL2_INITIAL_DUMMY_READS = 7<<1, + + LCDIF_TRANSFER_COUNT= 0x30/4, + TRANSFER_COUNT_V_COUNT = 0xFFFF<<16, + TRANSFER_COUNT_H_COUNT = 0xFFFF, + + LCDIF_CUR_BUF = 0x40/4, + LCDIF_NEXT_BUF = 0x50/4, + + LCDIF_TIMING = 0x60/4, + TIMING_CMD_HOLD = 0xFF<<24, + TIMING_CMD_SETUP = 0xFF<<16, + TIMING_DATA_HOLD = 0xFF<<8, + TIMING_DATA_SETUP = 0xFF<<0, + + LCDIF_VDCTRL0 = 0x70/4, + VDCTRL0_VSYNC_OEB = 1<<29, + VDCTRL0_ENABLE_PRESENT = 1<<28, + + VDCTRL0_VSYNC_POL = 1<<27, + VDCTRL0_HSYNC_POL = 1<<26, + VDCTRL0_DOTCLK_POL = 1<<25, + VDCTRL0_ENABLE_POL = 1<<24, + + VDCTRL0_VSYNC_PERIOD_UNIT = 1<<21, + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT = 1<<20, + VDCTRL0_HALF_LINE = 1<<19, + VDCTRL0_HALF_LINE_MODE = 1<<18, + + VDCTRL0_VSYNC_PULSE_WIDTH = 0x3FFFF, + + LCDIF_VDCTRL1 = 0x80/4, + VDCTRL1_VSYNC_PERIOD = 0xFFFFFFFF, + + LCDIF_VDCTRL2 = 0x90/4, + VDCTRL2_HSYNC_PERIOD = 0x3FFFF, + VDCTRL2_HSYNC_PULSE_WIDTH = 0x3FFF<<18, + + LCDIF_VDCTRL3 = 0xA0/4, + VDCTRL3_VERTICAL_WAIT_CNT = 0xFFFF, + VDCTRL3_HORIZONTAL_WAIT_CNT = 0xFFF<<16, + VDCTRL3_VSYNC_ONLY = 1<<28, + VDCTRL3_MUX_SYNC_SIGNALS = 1<<29, + + LCDIF_VDCTRL4 = 0xB0/4, + VDCTRL4_DOTCLK_H_VALID_DATA_CNT = 0x3FFFF, + VDCTRL4_SYNC_SIGNALS_ON = 1<<18, + + VDCTRL4_DOTCLK_DLY_2NS = 0<<29, + VDCTRL4_DOTCLK_DLY_4NS = 1<<29, + VDCTRL4_DOTCLK_DLY_6NS = 2<<29, + VDCTRL4_DOTCLK_DLY_8NS = 3<<29, + + LCDIF_DATA = 0x180/4, + + LCDIF_STAT = 0x1B0/4, + + LCDIF_AS_CTRL = 0x210/4, +}; + +struct video_mode { + int pixclk; + int hactive; + int vactive; + int hblank; + int vblank; + int hso; + int vso; + int hspw; + int vspw; + + char vsync_pol; + char hsync_pol; +}; + +struct dsi_cfg { + int lanes; + + int ref_clk; + int hs_clk; + int ui_ps; + + int byte_clk; + int byte_t_ps; + + int tx_esc_clk; + int tx_esc_t_ps; + + int rx_esc_clk; + + int clk_pre_ps; + int clk_prepare_ps; + int clk_zero_ps; + + int hs_prepare_ps; + int hs_zero_ps; + int hs_trail_ps; + int hs_exit_ps; + + int lpx_ps; + + vlong wakeup_ps; +}; + +/* base addresses, VIRTIO is at 0x30000000 physical */ + +static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); + +static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); +static u32int *gpio3 = (u32int*)(VIRTIO + 0x220000); + +static u32int *pwm2 = (u32int*)(VIRTIO + 0x670000); + +static u32int *resetc= (u32int*)(VIRTIO + 0x390000); +static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); + +static u32int *dsi = (u32int*)(VIRTIO + 0xA00000); +static u32int *dphy = (u32int*)(VIRTIO + 0xA00300); + +static u32int *lcdif = (u32int*)(VIRTIO + 0x320000); + +/* shift and mask */ +static u32int +sm(u32int v, u32int m) +{ + int s; + + if(m == 0) + return 0; + + s = 0; + while((m & 1) == 0){ + m >>= 1; + s++; + } + + return (v & m) << s; +} + +static u32int +rr(u32int *base, int reg) +{ + u32int val = base[reg]; +// iprint("%#p+%#.4x -> %#.8ux\n", PADDR(base), reg*4, val); + return val; +} +static void +wr(u32int *base, int reg, u32int val) +{ +// iprint("%#p+%#.4x <- %#.8ux\n", PADDR(base), reg*4, val); + base[reg] = val; +} +static void +mr(u32int *base, int reg, u32int val, u32int mask) +{ + wr(base, reg, (rr(base, reg) & ~mask) | (val & mask)); +} + +static void +dsiparams(struct dsi_cfg *cfg, int lanes, int hs_clk, int ref_clk, int tx_esc_clk, int rx_esc_clk) +{ + cfg->lanes = lanes; + cfg->ref_clk = ref_clk; + + cfg->hs_clk = hs_clk; + cfg->ui_ps = (1000000000000LL + (cfg->hs_clk-1)) / cfg->hs_clk; + + cfg->byte_clk = cfg->hs_clk / 8; + cfg->byte_t_ps = cfg->ui_ps * 8; + + cfg->tx_esc_clk = tx_esc_clk; + cfg->tx_esc_t_ps = (1000000000000LL + (cfg->tx_esc_clk-1)) / cfg->tx_esc_clk; + + cfg->rx_esc_clk = rx_esc_clk; + + /* min 8*ui */ + cfg->clk_pre_ps = 8*cfg->ui_ps; + + /* min 38ns, max 95ns */ + cfg->clk_prepare_ps = 38*1000; + + /* clk_prepare + clk_zero >= 300ns */ + cfg->clk_zero_ps = 300*1000 - cfg->clk_prepare_ps; + + /* min 40ns + 4*ui, max 85ns + 6*ui */ + cfg->hs_prepare_ps = 40*1000 + 4*cfg->ui_ps; + + /* hs_prepae + hs_zero >= 145ns + 10*ui */ + cfg->hs_zero_ps = (145*1000 + 10*cfg->ui_ps) - cfg->hs_prepare_ps; + + /* min max(n*8*ui, 60ns + n*4*ui); n=1 */ + cfg->hs_trail_ps = 60*1000 + 1*4*cfg->ui_ps; + if(cfg->hs_trail_ps < 1*8*cfg->ui_ps) + cfg->hs_trail_ps = 1*8*cfg->ui_ps; + + /* min 100ns */ + cfg->hs_exit_ps = 100*1000; + + /* min 50ns */ + cfg->lpx_ps = 50*1000; + + /* min 1ms */ + cfg->wakeup_ps = 1000000000000LL; +} + +static void +lcdifinit(struct video_mode *mode) +{ + wr(lcdif, LCDIF_CTRL_CLR, CTRL_SFTRST); + while(rr(lcdif, LCDIF_CTRL) & CTRL_SFTRST) + ; + wr(lcdif, LCDIF_CTRL_CLR, CTRL_CLKGATE); + while(rr(lcdif, LCDIF_CTRL) & (CTRL_SFTRST|CTRL_CLKGATE)) + ; + + wr(lcdif, LCDIF_CTRL1_SET, CTRL1_FIFO_CLEAR); + wr(lcdif, LCDIF_AS_CTRL, 0); + + wr(lcdif, LCDIF_CTRL1, sm(7, CTRL1_BYTE_PACKING_FORMAT)); + + wr(lcdif, LCDIF_CTRL, + CTRL_BYPASS_COUNT | + CTRL_MASTER | + CTRL_LCD_DATABUS_WIDTH_24_BIT | + CTRL_WORD_LENGTH_24_BIT); + + wr(lcdif, LCDIF_TRANSFER_COUNT, + sm(mode->vactive, TRANSFER_COUNT_V_COUNT) | + sm(mode->hactive, TRANSFER_COUNT_H_COUNT)); + + wr(lcdif, LCDIF_VDCTRL0, + VDCTRL0_ENABLE_PRESENT | + VDCTRL0_VSYNC_POL | VDCTRL0_HSYNC_POL | + VDCTRL0_VSYNC_PERIOD_UNIT | + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | + sm(mode->vspw, VDCTRL0_VSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL1, + sm(mode->vactive + mode->vblank, VDCTRL1_VSYNC_PERIOD)); + + wr(lcdif, LCDIF_VDCTRL2, + sm(mode->hactive + mode->hblank, VDCTRL2_HSYNC_PERIOD) | + sm(mode->hspw, VDCTRL2_HSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL3, + sm(mode->vblank - mode->vso, VDCTRL3_VERTICAL_WAIT_CNT) | + sm(mode->hblank - mode->hso, VDCTRL3_HORIZONTAL_WAIT_CNT)); + + wr(lcdif, LCDIF_VDCTRL4, + sm(mode->hactive, VDCTRL4_DOTCLK_H_VALID_DATA_CNT)); + + wr(lcdif, LCDIF_CUR_BUF, PADDR(gscreen->data->bdata)); + wr(lcdif, LCDIF_NEXT_BUF, PADDR(gscreen->data->bdata)); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_DOTCLK_MODE); + + mr(lcdif, LCDIF_VDCTRL4, VDCTRL4_SYNC_SIGNALS_ON, VDCTRL4_SYNC_SIGNALS_ON); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_RUN); +} + +static void +bridgeinit(I2Cdev *dev, struct video_mode *mode, struct dsi_cfg *cfg) +{ + int n; + + // clock derived from dsi clock + switch(cfg->hs_clk/2000000){ + case 384: + default: n = 1 << 1; break; + case 416: n = 2 << 1; break; + case 468: n = 0 << 1; break; + case 486: n = 3 << 1; break; + case 461: n = 4 << 1; break; + } + i2cwritebyte(dev, 0x0a, n); + + // single channel A + n = 1<<5 | (cfg->lanes-4)<<3 | 3<<1; + i2cwritebyte(dev, 0x10, n); + + // Enhanced framing and ASSR + i2cwritebyte(dev, 0x5a, 0x05); + + // 2 DP lanes w/o SSC + i2cwritebyte(dev, 0x93, 0x20); + + // 2.7Gbps DP data rate + i2cwritebyte(dev, 0x94, 0x80); + + // Enable PLL and confirm PLL is locked + i2cwritebyte(dev, 0x0d, 0x01); + + // wait for PLL to lock + while((i2creadbyte(dev, 0x0a) & 0x80) == 0) + ; + + // Enable ASSR on display + i2cwritebyte(dev, 0x64, 0x01); + i2cwritebyte(dev, 0x75, 0x01); + i2cwritebyte(dev, 0x76, 0x0a); + i2cwritebyte(dev, 0x77, 0x01); + i2cwritebyte(dev, 0x78, 0x81); + + // Train link and confirm trained + i2cwritebyte(dev, 0x96, 0x0a); + while(i2creadbyte(dev, 0x96) != 1) + ; + + // video timings + i2cwritebyte(dev, 0x20, mode->hactive & 0xFF); + i2cwritebyte(dev, 0x21, mode->hactive >> 8); + i2cwritebyte(dev, 0x24, mode->vactive & 0xFF); + i2cwritebyte(dev, 0x25, mode->vactive >> 8); + i2cwritebyte(dev, 0x2c, mode->hspw); + i2cwritebyte(dev, 0x2d, mode->hspw>>8 | (mode->hsync_pol=='-')<<7); + i2cwritebyte(dev, 0x30, mode->vspw); + i2cwritebyte(dev, 0x31, mode->vspw>>8 | (mode->vsync_pol=='-')<<7); + i2cwritebyte(dev, 0x34, mode->hblank - mode->hspw - mode->hso); + i2cwritebyte(dev, 0x36, mode->vblank - mode->vspw - mode->vso); + i2cwritebyte(dev, 0x38, mode->hso); + i2cwritebyte(dev, 0x3a, mode->vso); + + // Enable video stream, ASSR, enhanced framing + i2cwritebyte(dev, 0x5a, 0x0d); +} + +static char* +parseedid128(struct video_mode *mode, uchar edid[128]) +{ + static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; + uchar *p, sum; + int i; + + if(memcmp(edid, magic, 8) != 0) + return "bad edid magic"; + + sum = 0; + for(i=0; i<128; i++) + sum += edid[i]; + if(sum != 0) + return "bad edid checksum"; + + /* + * Detailed Timings + */ + p = edid+8+10+2+5+10+3+16; + for(i=0; i<4; i++, p+=18){ + if((p[0]|p[1])==0) + continue; + + memset(mode, 0, sizeof(*mode)); + + mode->pixclk = ((p[1]<<8) | p[0]) * 10000; + + mode->hactive = ((p[4] & 0xF0)<<4) | p[2]; /* horizontal active */ + mode->hblank = ((p[4] & 0x0F)<<8) | p[3]; /* horizontal blanking */ + mode->vactive = ((p[7] & 0xF0)<<4) | p[5]; /* vertical active */ + mode->vblank = ((p[7] & 0x0F)<<8) | p[6]; /* vertical blanking */ + mode->hso = ((p[11] & 0xC0)<<2) | p[8]; /* horizontal sync offset */ + mode->hspw = ((p[11] & 0x30)<<4) | p[9]; /* horizontal sync pulse width */ + mode->vso = ((p[11] & 0x0C)<<2) | ((p[10] & 0xF0)>>4); /* vertical sync offset */ + mode->vspw = ((p[11] & 0x03)<<4) | (p[10] & 0x0F); /* vertical sync pulse width */ + + switch((p[17] & 0x18)>>3) { + case 3: /* digital separate sync signal; the norm */ + mode->vsync_pol = (p[17] & 0x04) ? '+' : '-'; + mode->hsync_pol = (p[17] & 0x02) ? '+' : '-'; + break; + } + + return nil; + } + + return "no edid timings available"; +} + +static char* +getmode(I2Cdev *dev, struct video_mode *mode) +{ + static uchar edid[128]; + static I2Cdev aux; + + aux.bus = dev->bus; + aux.addr = 0x50; + aux.subaddr = 1; + aux.size = sizeof(edid); + + /* enable passthru mode for address 0x50 (EDID) */ + i2cwritebyte(dev, 0x60, aux.addr<<1 | 1); + addi2cdev(&aux); + + if(i2crecv(&aux, edid, sizeof(edid), 0) != sizeof(edid)) + return "i2crecv failed to get edid bytes"; + + return parseedid128(mode, edid); +} + +static void +dphyinit(struct dsi_cfg *cfg) +{ + int n; + + /* powerdown */ + wr(dphy, DPHY_PD_PLL, 1); + wr(dphy, DPHY_PD_PHY, 1); + + /* magic */ + wr(dphy, DPHY_LOCK_BYP, 0); + wr(dphy, DPHY_RTERM_SEL, 1); + wr(dphy, DPHY_AUTO_PD_EN, 0); + wr(dphy, DPHY_RXLPRP, 2); + wr(dphy, DPHY_RXCDR, 2); + wr(dphy, DPHY_TST, 0x25); + + /* hs timings */ + n = (2*cfg->hs_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 3) + n = 3; + wr(dphy, DPHY_M_PRG_HS_PREPARE, n); + + n = (2*cfg->clk_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_PREPARE, n); + + n = ((cfg->hs_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 6; + if(n < 1) + n = 1; + wr(dphy, DPHY_M_PRG_HS_ZERO, n); + + n = ((cfg->clk_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 3; + if(n < 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_ZERO, n); + + n = (cfg->hs_trail_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps; + if(n < 1) + n = 1; + else if(n > 15) + n = 15; + wr(dphy, DPHY_M_PRG_HS_TRAIL, n); + wr(dphy, DPHY_MC_PRG_HS_TRAIL, n); + + if(cfg->hs_clk < 80*Mhz) + n = 0xD; + else if(cfg->hs_clk < 90*Mhz) + n = 0xC; + else if(cfg->hs_clk < 125*Mhz) + n = 0xB; + else if(cfg->hs_clk < 150*Mhz) + n = 0xA; + else if(cfg->hs_clk < 225*Mhz) + n = 0x9; + else if(cfg->hs_clk < 500*Mhz) + n = 0x8; + else + n = 0x7; + wr(dphy, DPHY_RXHS_SETTLE, n); + + /* hs_clk = ref_clk * (CM / (CN*CO)); just set CN=CO=1 */ + n = (cfg->hs_clk + cfg->ref_clk-1) / cfg->ref_clk; + + /* strange encoding for CM */ + if(n < 32) + n = 0xE0 | (n - 16); + else if(n < 64) + n = 0xC0 | (n - 32); + else if(n < 128) + n = 0x80 | (n - 64); + else + n = n - 128; + wr(dphy, DPHY_CM, n); + + wr(dphy, DPHY_CN, 0x1F); /* CN==1 */ + wr(dphy, DPHY_CO, 0x00); /* CO==1 */ +} + +static void +dphypowerup(void) +{ + wr(dphy, DPHY_PD_PLL, 0); + while((rr(dphy, DPHY_LOCK) & 1) == 0) + ; + wr(dphy, DPHY_PD_PHY, 0); +} + +static void +dsiinit(struct dsi_cfg *cfg) +{ + int n; + + wr(dsi, DSI_HOST_CFG_NUM_LANES, cfg->lanes-1); + + wr(dsi, DSI_HOST_CFG_NONCONTINUOUS_CLK, 0x0); + wr(dsi, DSI_HOST_CFG_AUTOINSERT_EOTP, 0x0); + + n = (cfg->clk_pre_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_PRE, n); + + n = (cfg->clk_pre_ps + cfg->lpx_ps + cfg->clk_prepare_ps + cfg->clk_zero_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_POST, n); + + n = (cfg->hs_exit_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_TX_GAP, n); + + wr(dsi, DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP, 0x1); + + wr(dsi, DSI_HOST_CFG_HTX_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_LRX_H_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_BTA_H_TO_COUNT, 0x0); + + n = (cfg->wakeup_ps + cfg->tx_esc_t_ps-1) / cfg->tx_esc_t_ps; + wr(dsi, DSI_HOST_CFG_TWAKEUP, n); +} + +static void +dpiinit(struct video_mode *mode) +{ + wr(dsi, DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING, 0x5); // 24-bit + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FORMAT, 0x3); // 24-bit + + /* this seems wrong */ + wr(dsi, DSI_HOST_CFG_DPI_VSYNC_POLARITY, 0); + wr(dsi, DSI_HOST_CFG_DPI_HSYNC_POLARITY, 0); + + wr(dsi, DSI_HOST_CFG_DPI_VIDEO_MODE, 0x1); // non-burst mode with sync events + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL, mode->hactive); + + wr(dsi, DSI_HOST_CFG_DPI_HFP, mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HBP, mode->hblank - mode->hspw - mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HSA, mode->hspw); + + wr(dsi, DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_BLLP_MODE, 0x1); + + wr(dsi, DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_VC, 0x0); + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE, mode->hactive); + wr(dsi, DSI_HOST_CFG_DPI_VACTIVE, mode->vactive - 1); + wr(dsi, DSI_HOST_CFG_DPI_VBP, mode->vblank - mode->vspw - mode->vso); + wr(dsi, DSI_HOST_CFG_DPI_VFP, mode->vso); +} + +void +lcdinit(void) +{ + struct dsi_cfg dsi_cfg; + struct video_mode mode; + I2Cdev *bridge; + char *err; + + /* gpio3 20 for sn65dsi86 bridge */ + mr(iomuxc, IOMUXC_CTL_PAD_SAI5_RXC, 5, MUX_MODE); + /* gpio1 10 pad for panel */ + mr(iomuxc, IOMUXC_CTL_PAD_GPIO1_IO10, 0, MUX_MODE); + /* pwm2 pad */ + mr(iomuxc, IOMUXC_CTL_PAD_SPDIF_RX, 1, MUX_MODE); + + /* lcdif to dpi=0, dcss=1 */ + mr(iomuxc, IOMUXC_GPR_GPR13, 0, MIPI_MUX_SEL); + + setclkgate("gpio1.ipg_clk_s", 1); + setclkgate("gpio3.ipg_clk_s", 1); + + setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); + setclkgate("pwm2.ipg_clk_high_freq", 1); + + mr(gpio1, GPIO_GDIR, 1<<10, 1<<10); /* gpio1 10 output */ + mr(gpio1, GPIO_DR, 0<<10, 1<<10); /* gpio1 10 low: panel off */ + + wr(pwm2, PWMIR, 0); + wr(pwm2, PWMCR, CR_STOPEN | CR_DOZEN | CR_WAITEN | CR_DBGEN | CR_CLKSRC_HIGHFREQ | 0<<CR_PRESCALER_SHIFT); + wr(pwm2, PWMSAR, Pwmsrcclk/150000); + wr(pwm2, PWMPR, (Pwmsrcclk/100000)-2); + mr(pwm2, PWMCR, CR_EN, CR_EN); + + mr(gpio1, GPIO_DR, 1<<10, 1<<10); /* gpio1 10 high: panel on */ + + mr(gpio3, GPIO_GDIR, 1<<20, 1<<20); /* gpio3 20 output */ + mr(gpio3, GPIO_DR, 1<<20, 1<<20); /* gpio3 20 high: bridge on */ + + bridge = i2cdev(i2cbus("i2c4"), 0x2C); + if(bridge == nil) + return; + bridge->subaddr = 1; + + /* power on mipi dsi */ + wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0x0000FFFF); + mr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ, MIPI_SW_PUP_REQ, MIPI_SW_PUP_REQ); + while(rr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ) & MIPI_SW_PUP_REQ) + ; + wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0); + + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_PCLK_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_BYTE_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_DPI_RESET_N); + + setclkgate("sim_display.mainclk", 0); + setclkgate("disp.axi_clk", 0); + setclkrate("disp.axi_clk", "system_pll1_clk", 800*Mhz); + setclkrate("disp.rtrm_clk", "system_pll1_clk", 400*Mhz); + setclkgate("disp.axi_clk", 1); + setclkgate("sim_display.mainclk", 1); + + setclkrate("mipi.core", "system_pll1_div3", 266*Mhz); + setclkrate("mipi.CLKREF", "system_pll2_clk", 25*Mhz); + setclkrate("mipi.RxClkEsc", "system_pll1_clk", 80*Mhz); + setclkrate("mipi.TxClkEsc", nil, 20*Mhz); + + /* dsi parameters are fixed for the bridge */ + dsiparams(&dsi_cfg, 4, 2*486*Mhz, + getclkrate("mipi.CLKREF"), + getclkrate("mipi.TxClkEsc"), + getclkrate("mipi.RxClkEsc")); + + /* release dphy reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_PCLK_RESET_N, RCR_MIPI_DSI_PCLK_RESET_N); + + dphyinit(&dsi_cfg); + dsiinit(&dsi_cfg); + dphypowerup(); + + /* release mipi clock resets (generated by the dphy) */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_ESC_RESET_N, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_RESET_BYTE_N, RCR_MIPI_DSI_RESET_BYTE_N); + + /* + * get mode information from EDID, this can only be done after the clocks + * are generated by the DPHY and the clock resets have been released. + */ + err = getmode(bridge, &mode); + if(err != nil) + goto out; + + /* allocates the framebuffer (gscreen->data->bdata) */ + if(screeninit(mode.hactive, mode.vactive, 32) < 0){ + err = "screeninit failed"; + goto out; + } + + /* start the pixel clock */ + setclkrate("lcdif.pix_clk", "system_pll1_clk", mode.pixclk); + dpiinit(&mode); + + /* release dpi reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_DPI_RESET_N, RCR_MIPI_DSI_DPI_RESET_N); + + /* enable display port bridge */ + bridgeinit(bridge, &mode, &dsi_cfg); + + /* send the pixels */ + lcdifinit(&mode); + return; + +out: + print("lcdinit: %s\n", err); +} diff --git a/sys/src/9/imx8/main.c b/sys/src/9/imx8/main.c index 01e4ce20c..b0494f682 100644 --- a/sys/src/9/imx8/main.c +++ b/sys/src/9/imx8/main.c @@ -32,6 +32,7 @@ init0(void) poperror(); } kproc("alarm", alarmkproc, 0); + sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4); sp[3] = sp[2] = sp[1] = nil; strcpy(sp[1] = (char*)&sp[4], "boot"); @@ -99,14 +100,7 @@ confinit(void) + conf.nswap + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; - if(!cpuserver) - /* - * give terminals lots of image memory, too; the dynamic - * allocation will balance the load properly, hopefully. - * be careful with 32-bit overflow. - */ - imagmem->maxsize = kpages; - + imagmem->maxsize = kpages; } void @@ -149,7 +143,6 @@ main(void) fpuinit(); intrinit(); clockinit(); - print("cpu%d: UP!\n", m->machno); synccycles(); timersinit(); flushtlb(); @@ -175,6 +168,7 @@ main(void) initseg(); links(); chandevreset(); + lcdinit(); userinit(); mpinit(); mmu0clear((uintptr*)L1); diff --git a/sys/src/9/imx8/mem.h b/sys/src/9/imx8/mem.h index f20037bd9..0c92e9ae2 100644 --- a/sys/src/9/imx8/mem.h +++ b/sys/src/9/imx8/mem.h @@ -39,9 +39,9 @@ #define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ #define TRAPFRAMESIZE (38*8) -/* reserved dram for ucalloc() at the end of KZERO (physical) */ +/* reserved dram for ucalloc() and fbmemalloc() at the end of KZERO (physical) */ #define UCRAMBASE (-KZERO - UCRAMSIZE) -#define UCRAMSIZE (1*MiB) +#define UCRAMSIZE (8*MiB) #define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */ #define KTZERO (VDRAM + 0x100000) /* kernel text start */ @@ -54,7 +54,7 @@ #define VMAP (0xFFFFFFFF00000000ULL) /* 0x00000000 - 0x40000000 */ #define KMAPEND (0xFFFFFFFF00000000ULL) /* 0x140000000 */ -#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ +#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ #define KSEG0 (0xFFFFFFFE00000000ULL) diff --git a/sys/src/9/imx8/mkfile b/sys/src/9/imx8/mkfile index 2e37a5a8b..01f8adad6 100644 --- a/sys/src/9/imx8/mkfile +++ b/sys/src/9/imx8/mkfile @@ -58,12 +58,12 @@ OBJ=\ # HFILES= LIB=\ -# /$objtype/lib/libmemlayer.a\ -# /$objtype/lib/libmemdraw.a\ -# /$objtype/lib/libdraw.a\ + /$objtype/lib/libmemlayer.a\ + /$objtype/lib/libmemdraw.a\ + /$objtype/lib/libdraw.a\ /$objtype/lib/libip.a\ /$objtype/lib/libsec.a\ -# /$objtype/lib/libmp.a\ + /$objtype/lib/libmp.a\ /$objtype/lib/libc.a\ # /$objtype/lib/libdtracy.a\ diff --git a/sys/src/9/imx8/mmu.c b/sys/src/9/imx8/mmu.c index 5bec2ab05..c61ca7f01 100644 --- a/sys/src/9/imx8/mmu.c +++ b/sys/src/9/imx8/mmu.c @@ -472,21 +472,36 @@ checkmmu(uintptr, uintptr) { } -void* -ucalloc(usize size) +static void* +ucramalloc(usize size, uintptr align, uint attr) { static uintptr top = UCRAMBASE + UCRAMSIZE; static Lock lk; - uintptr va; - - size = PGROUND(size); + uintptr va, pg; lock(&lk); top -= size; + size += top & align-1; + top &= -align; if(top < UCRAMBASE) - panic("ucalloc: %p needs %zd bytes\n", getcallerpc(&size), size); + panic("ucramalloc: need %zd bytes", size); va = KZERO + top; + pg = va & -BY2PG; + if(pg != ((va+size) & -BY2PG)) + mmukmap(pg | attr, pg - KZERO, PGROUND(size)); unlock(&lk); - return (void*)mmukmap(va | PTEUNCACHED, PADDR(va), size); + return (void*)va; +} + +void* +ucalloc(usize size) +{ + return ucramalloc(size, 8, PTEUNCACHED); +} + +void* +fbmemalloc(usize size) +{ + return ucramalloc(PGROUND(size), BY2PG, PTEWT); } diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index ae88c1d99..64a012e7d 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -14,14 +14,18 @@ dev fs ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno + draw screen swcursor + mouse screen swcursor uart usb + i2c link usbxhciimx etherimx ethermii ethermedium loopbackmedium + i2cimx devi2c ip tcp udp @@ -31,8 +35,10 @@ ip icmp6 ipmux misc + ccm gic uartimx + lcd port int cpuserver = 0; bootdir diff --git a/sys/src/9/imx8/screen.c b/sys/src/9/imx8/screen.c new file mode 100644 index 000000000..5be30fa79 --- /dev/null +++ b/sys/src/9/imx8/screen.c @@ -0,0 +1,341 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#define Image IMAGE +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +enum { + Tabstop = 4, + Scroll = 8, +}; + +Memimage *gscreen; + +static Memdata xgdata; +static Memimage xgscreen; +static Memimage *conscol; +static Memimage *back; +static Memsubfont *memdefont; + +static Lock screenlock; + +static Point curpos; +static int h, w; +static Rectangle window; + +static void myscreenputs(char *s, int n); +static void screenputc(char *buf); +static void screenwin(void); + +enum +{ + CMaccelerated, + CMlinear, +}; + +static Cmdtab mousectlmsg[] = +{ + CMaccelerated, "accelerated", 0, + CMlinear, "linear", 1, +}; + +void +mousectl(Cmdbuf *cb) +{ + Cmdtab *ct; + + ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); + switch(ct->index){ + case CMaccelerated: + mouseaccelerate(cb->nf == 1? 1: atoi(cb->f[1])); + break; + case CMlinear: + mouseaccelerate(0); + break; + } +} + +void +cursoron(void) +{ + swcursorhide(0); + swcursordraw(mousexy()); +} + +void +cursoroff(void) +{ + swcursorhide(0); +} + +void +setcursor(Cursor* curs) +{ + swcursorload(curs); +} + +int +hwdraw(Memdrawparam *par) +{ + Memimage *dst, *src, *mask; + + if((dst = par->dst) == nil || dst->data == nil) + return 0; + if((src = par->src) && src->data == nil) + src = nil; + if((mask = par->mask) && mask->data == nil) + mask = nil; + + if(dst->data->bdata == xgdata.bdata) + swcursoravoid(par->r); + if(src && src->data->bdata == xgdata.bdata) + swcursoravoid(par->sr); + if(mask && mask->data->bdata == xgdata.bdata) + swcursoravoid(par->mr); + + return 0; +} + +int +screeninit(int width, int height, int depth) +{ + ulong chan; + + switch(depth){ + default: + return -1; + case 32: + chan = XRGB32; + break; + case 24: + chan = RGB24; + break; + case 16: + chan = RGB16; + break; + } + memsetchan(&xgscreen, chan); + xgscreen.r = Rect(0, 0, width, height); + xgscreen.clipr = xgscreen.r; + xgscreen.depth = depth; + xgscreen.width = wordsperline(xgscreen.r, xgscreen.depth); + xgdata.bdata = fbmemalloc(xgscreen.width*sizeof(ulong)*height); + xgdata.ref = 1; + + xgscreen.data = &xgdata; + + gscreen = &xgscreen; + + conf.monitor = 1; + + memimageinit(); + memdefont = getmemdefont(); + screenwin(); + myscreenputs(kmesg.buf, kmesg.n); + screenputs = myscreenputs; + swcursorinit(); + + return 0; +} + +void +flushmemscreen(Rectangle) +{ +} + +Memdata* +attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) +{ + if(gscreen == nil) + return nil; + + *r = gscreen->r; + *d = gscreen->depth; + *chan = gscreen->chan; + *width = gscreen->width; + *softscreen = 0; + + gscreen->data->ref++; + return gscreen->data; +} + +void +getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) +{ + USED(p, pr, pg, pb); +} + +int +setcolor(ulong p, ulong r, ulong g, ulong b) +{ + USED(p, r, g, b); + return 0; +} + +void +blankscreen(int) +{ +} + +static void +myscreenputs(char *s, int n) +{ + int i; + Rune r; + char buf[4]; + + if(!islo()) { + /* don't deadlock trying to print in interrupt */ + if(!canlock(&screenlock)) + return; + } + else + lock(&screenlock); + + while(n > 0){ + i = chartorune(&r, s); + if(i == 0){ + s++; + --n; + continue; + } + memmove(buf, s, i); + buf[i] = 0; + n -= i; + s += i; + screenputc(buf); + } + unlock(&screenlock); +} + +static void +screenwin(void) +{ + char *greet; + Memimage *orange; + Point p, q; + Rectangle r; + + back = memblack; + conscol = memwhite; + + orange = allocmemimage(Rect(0, 0, 1, 1), RGB16); + orange->flags |= Frepl; + orange->clipr = gscreen->r; + orange->data->bdata[0] = 0x40; /* magic: colour? */ + orange->data->bdata[1] = 0xfd; /* magic: colour? */ + + w = memdefont->info[' '].width; + h = memdefont->height; + + r = gscreen->r; + memimagedraw(gscreen, r, memwhite, ZP, memopaque, ZP, S); + window = insetrect(r, 4); + memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); + + memimagedraw(gscreen, Rect(window.min.x, window.min.y, + window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S); + + freememimage(orange); + window = insetrect(window, 5); + + greet = " Plan 9 Console "; + p = addpt(window.min, Pt(10, 0)); + q = memsubfontwidth(memdefont, greet); + memimagestring(gscreen, p, conscol, ZP, memdefont, greet); + flushmemscreen(r); + window.min.y += h + 6; + curpos = window.min; + window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h; +} + +static void +scroll(void) +{ + int o; + Point p; + Rectangle r; + + o = Scroll*h; + r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); + p = Pt(window.min.x, window.min.y+o); + memimagedraw(gscreen, r, gscreen, p, nil, p, S); + flushmemscreen(r); + r = Rpt(Pt(window.min.x, window.max.y-o), window.max); + memimagedraw(gscreen, r, back, ZP, nil, ZP, S); + flushmemscreen(r); + + curpos.y -= o; +} + +static void +screenputc(char *buf) +{ + int w; + uint pos; + Point p; + Rectangle r; + static int *xp; + static int xbuf[256]; + + if (xp < xbuf || xp >= &xbuf[nelem(xbuf)]) + xp = xbuf; + + switch (buf[0]) { + case '\n': + if (curpos.y + h >= window.max.y) + scroll(); + curpos.y += h; + screenputc("\r"); + break; + case '\r': + xp = xbuf; + curpos.x = window.min.x; + break; + case '\t': + p = memsubfontwidth(memdefont, " "); + w = p.x; + if (curpos.x >= window.max.x - Tabstop * w) + screenputc("\n"); + + pos = (curpos.x - window.min.x) / w; + pos = Tabstop - pos % Tabstop; + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x += pos * w; + break; + case '\b': + if (xp <= xbuf) + break; + xp--; + r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x = *xp; + break; + case '\0': + break; + default: + p = memsubfontwidth(memdefont, buf); + w = p.x; + + if (curpos.x >= window.max.x - w) + screenputc("\n"); + + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); + flushmemscreen(r); + curpos.x += w; + break; + } +} diff --git a/sys/src/9/imx8/screen.h b/sys/src/9/imx8/screen.h new file mode 100644 index 000000000..fc0b7f582 --- /dev/null +++ b/sys/src/9/imx8/screen.h @@ -0,0 +1,32 @@ +/* devmouse.c */ +typedef struct Cursor Cursor; +extern Cursor cursor; +extern void mousetrack(int, int, int, ulong); +extern void absmousetrack(int, int, int, ulong); +extern Point mousexy(void); +extern void mouseaccelerate(int); + +/* screen.c */ +extern int screeninit(int width, int hight, int depth); +extern void blankscreen(int); +extern void flushmemscreen(Rectangle); +extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*); +extern void cursoron(void); +extern void cursoroff(void); +extern void setcursor(Cursor*); + +extern void mousectl(Cmdbuf*); +extern void mouseresize(void); +extern void mouseredraw(void); + +/* devdraw.c */ +extern QLock drawlock; + +#define ishwimage(i) 1 /* for ../port/devdraw.c */ + +/* swcursor.c */ +void swcursorhide(int); +void swcursoravoid(Rectangle); +void swcursordraw(Point); +void swcursorload(Cursor *); +void swcursorinit(void); diff --git a/sys/src/9/imx8/uartimx.c b/sys/src/9/imx8/uartimx.c index 5d6e0d2f1..c7173f423 100644 --- a/sys/src/9/imx8/uartimx.c +++ b/sys/src/9/imx8/uartimx.c @@ -314,18 +314,36 @@ interrupt(Ureg*, void *arg) uartkick(uart); } +static void +clkenable(Uart *u, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "%s.ipg_perclk", u->name); + if(on) setclkrate(clk, "osc_25m_ref_clk", u->freq); + setclkgate(clk, on); +} + static void disable(Uart *u) { u32int *regs = u->regs; + + if(u->console) + return; /* avoid glitch */ + regs[UCR1] = 0; + clkenable(u, 0); } static void enable(Uart *u, int ie) { disable(u); + clkenable(u, 1); + if(ie) intrenable(IRQuart1, interrupt, u, BUSUNKNOWN, u->name); + config(u); } diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index e08b80b19..6eebb3dfe 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1774,6 +1774,17 @@ portreset(Hci *hp, int port, int on) return 0; } +static void +clkenable(int i, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "usb%d.ctrl", i+1); + setclkgate(clk, on); + snprint(clk, sizeof(clk), "usb%d.phy", i+1); + setclkgate(clk, on); +} + static int reset(Hci *hp) { @@ -1796,6 +1807,15 @@ reset(Hci *hp) return -1; Found: + if(i == 0){ + for(i = 0; i < nelem(ctlrs); i++) clkenable(i, 0); + setclkrate("ccm_usb_bus_clk_root", "system_pll2_div2", 500*Mhz); + setclkrate("ccm_usb_core_ref_clk_root", "system_pll1_div8", 100*Mhz); + setclkrate("ccm_usb_phy_ref_clk_root", "system_pll1_div8", 100*Mhz); + i = 0; + } + clkenable(i, 1); + hp->init = init; hp->dump = dump; hp->interrupt = interrupt; From 1d81f7eacbe2db017f49cf5646c7671f0581f170 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sun, 12 Jun 2022 00:21:28 +0000 Subject: [PATCH 20/58] imx8/lcd: silly work around for display instability running at the actual pixel clock causes the screen to shift horizontally after a while. using 60% seems to fix it - for now. --- sys/src/9/imx8/lcd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index d54d667b6..661585eee 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -930,8 +930,12 @@ lcdinit(void) goto out; } - /* start the pixel clock */ - setclkrate("lcdif.pix_clk", "system_pll1_clk", mode.pixclk); + /* + * start the pixel clock. running at the actual pixel clock + * causes the screen to shift horizontally after a while. + * using 60% seems to fix it - for now. + */ + setclkrate("lcdif.pix_clk", "system_pll1_clk", (mode.pixclk*6)/10); dpiinit(&mode); /* release dpi reset */ From c3e1346bbcc2f737ff69fdc353125714ec937ddb Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Sun, 12 Jun 2022 00:44:10 +0000 Subject: [PATCH 21/58] kernel: add /srv/clone /srv/clone allows a namespace to get their own private /srv session. --- sys/man/3/srv | 11 ++ sys/src/9/port/devsrv.c | 265 ++++++++++++++++++++++++++++++++-------- 2 files changed, 225 insertions(+), 51 deletions(-) diff --git a/sys/man/3/srv b/sys/man/3/srv index 820c849db..00497c79d 100644 --- a/sys/man/3/srv +++ b/sys/man/3/srv @@ -5,6 +5,7 @@ srv \- server registry .nf .B bind #s /srv +.BI #s/ clone/ .BI #s/ service1 .BI #s/ service2 ... @@ -40,6 +41,16 @@ releases that reference. .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. +.PP +A walk to +.I clone +creates a blank private bulletin board. Private boards are +recursable but disjoint; walks may only descend. A process +may get a private +.B /srv +by doing: +.IP +bind -c /srv/clone /srv .SH EXAMPLE To drop one end of a pipe into .BR /srv , diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 8128569a1..9cece906b 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -5,6 +5,7 @@ #include "fns.h" #include "../port/error.h" +#include "netif.h" typedef struct Srv Srv; struct Srv @@ -17,16 +18,34 @@ struct Srv ulong path; }; -static QLock srvlk; -static Srv *srv; -static int qidpath; +typedef struct Fid Fid; +struct Fid +{ + int ref; + QLock lk; + Srv *tail; + ulong nextpath; +}; + +enum{ + Qroot, + Qclone, + + Qend +}; + +static Fid global; + +struct { + QLock; + ulong path; +} sessions; static Srv* -srvlookup(char *name, ulong qidpath) +srvlookup(Srv *sp, char *name, ulong qidpath) { - Srv *sp; - - for(sp = srv; sp != nil; sp = sp->link) { + qidpath = NETTYPE(qidpath); + for(; sp != nil; sp = sp->link) { if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) return sp; } @@ -38,47 +57,139 @@ srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; Qid q; + Fid *f; + ulong id; if(s == DEVDOTDOT){ - devdir(c, c->qid, "#s", 0, eve, 0555, dp); + switch(NETTYPE(c->qid.path)){ + case Qroot: + mkqid(&q, Qroot, 0, QTDIR); + devdir(c, q, "#s", 0, eve, 0555|DMDIR, dp); + break; + case Qclone: + default: + /* + * Someone has walked down /srv/clone/clone/.... and + * would like back up. We do not allow revisiting + * previous sessions. Dead end + */ + error(Enonexist); + break; + } return 1; } - qlock(&srvlk); + id = NETID(c->qid.path); + if(name != nil && strcmp(name, "clone") == 0){ + /* walk; new session */ + qlock(&sessions); + id = ++sessions.path; + qunlock(&sessions); + + f = smalloc(sizeof *f); + f->ref = 1; + f->nextpath = Qend; + + mkqid(&q, NETQID(id, Qclone), id, QTDIR); + devdir(c, q, "clone", 0, eve, 0555|DMDIR, dp); + c->aux = f; + return 1; + } else if(name == nil && s == 0) { + /* stat, dirread; current session */ + mkqid(&q, NETQID(id, Qclone), id, QTDIR); + devdir(c, q, "clone", 0, eve, 0555|DMDIR, dp); + return 1; + } + + f = c->aux; + qlock(&f->lk); if(name != nil) - sp = srvlookup(name, -1); + sp = srvlookup(f->tail, name, -1); else { - for(sp = srv; sp != nil && s > 0; sp = sp->link) + s -= 1; + for(sp = f->tail; sp != nil && s > 0; sp = sp->link) s--; } if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { - qunlock(&srvlk); + qunlock(&f->lk); return -1; } - mkqid(&q, sp->path, 0, QTFILE); + mkqid(&q, NETQID(id, sp->path), 0, QTFILE); /* make sure name string continues to exist after we release lock */ kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - qunlock(&srvlk); + qunlock(&f->lk); return 1; } static void srvinit(void) { - qidpath = 1; + global.nextpath = Qend; } static Chan* srvattach(char *spec) { - return devattach('s', spec); + Chan *c; + + c = devattach('s', spec); + c->aux = &global; + return c; } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, 0, 0, srvgen); + Walkqid *wq; + Fid *f; + int tripped; + + /* + * We need to allow for infinite recursions through clone but we + * don't need to permit passing multiple clones in a single walk. + * This allows us to ensure that only a single clone is alloted + * per walk. + */ + tripped = 0; + if(nname > 1){ + nname = 1; + tripped = 1; + } + wq = devwalk(c, nc, name, nname, 0, 0, srvgen); + if(wq == nil || wq->clone == nil || wq->clone == c) + return wq; + + if(tripped){ + /* + * Our partial walk returned a newly alloc'd clone. + * We wll never see a clunk for that partially walked + * fid, so just clean it up now. + */ + if(NETTYPE(wq->clone->qid.path) == Qclone){ + f = wq->clone->aux; + assert(f->tail == nil); + assert(f->ref == 1); + free(f); + } + /* Correct state to indicate failure to walk all names */ + wq->clone->type = 0; + cclose(wq->clone); + wq->clone = nil; + return wq; + } + if(wq->clone->aux == &global) + return wq; + + if(NETID(c->qid.path) != NETID(wq->clone->qid.path)) + return wq; + + assert(c->aux == wq->clone->aux); + f = c->aux; + qlock(&f->lk); + f->ref++; + qunlock(&f->lk); + return wq; } static int @@ -91,11 +202,13 @@ char* srvname(Chan *c) { Srv *sp; + Fid *f; char *s; s = nil; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + f = &global; + qlock(&f->lk); + for(sp = f->tail; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -103,7 +216,7 @@ srvname(Chan *c) break; } } - qunlock(&srvlk); + qunlock(&f->lk); return s; } @@ -111,6 +224,7 @@ static Chan* srvopen(Chan *c, int omode) { Srv *sp; + Fid *f; Chan *nc; if(c->qid.type == QTDIR){ @@ -123,13 +237,14 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } - qlock(&srvlk); + f = c->aux; + qlock(&f->lk); if(waserror()){ - qunlock(&srvlk); + qunlock(&f->lk); nexterror(); } - sp = srvlookup(nil, c->qid.path); + sp = srvlookup(f->tail, nil, c->qid.path); if(sp == nil || sp->chan == nil) error(Eshutdown); @@ -144,7 +259,7 @@ srvopen(Chan *c, int omode) nc = sp->chan; incref(nc); - qunlock(&srvlk); + qunlock(&f->lk); poperror(); cclose(c); @@ -155,6 +270,7 @@ static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { Srv *sp; + Fid *f; if(openmode(omode) != OWRITE) error(Eperm); @@ -162,31 +278,32 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); + f = c->aux; sp = smalloc(sizeof *sp); kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - qlock(&srvlk); + qlock(&f->lk); if(waserror()){ - qunlock(&srvlk); + qunlock(&f->lk); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(srvlookup(name, -1) != nil) + if(srvlookup(f->tail, name, -1) != nil) error(Eexist); sp->perm = perm&0777; - sp->path = qidpath++; + sp->path = f->nextpath++; - c->qid.path = sp->path; + c->qid.path = NETQID(NETID(c->qid.path), sp->path); c->qid.type = QTFILE; - sp->link = srv; - srv = sp; + sp->link = f->tail; + f->tail = sp; - qunlock(&srvlk); + qunlock(&f->lk); poperror(); c->flag |= COPEN; @@ -199,18 +316,22 @@ static void srvremove(Chan *c) { Srv *sp, **l; + Fid *f; + ulong id; if(c->qid.type == QTDIR) error(Eperm); - qlock(&srvlk); + f = c->aux; + + qlock(&f->lk); if(waserror()){ - qunlock(&srvlk); + qunlock(&f->lk); nexterror(); } - l = &srv; + l = &f->tail; for(sp = *l; sp != nil; sp = *l) { - if(sp->path == c->qid.path) + if(sp->path == NETTYPE(c->qid.path)) break; l = &sp->link; } @@ -231,15 +352,29 @@ srvremove(Chan *c) *l = sp->link; sp->link = nil; + id = NETID(c->qid.path); - qunlock(&srvlk); poperror(); - if(sp->chan != nil) cclose(sp->chan); free(sp->owner); free(sp->name); free(sp); + + if(f == &global){ + qunlock(&f->lk); + return; + } + + f->ref--; + if(f->ref == 0){ + assert(f->tail == nil); + qunlock(&f->lk); + free(f); + } else if(f->ref < 0) + panic("srv ref rm %d id %uld", f->ref, id); + else + qunlock(&f->lk); } static int @@ -247,6 +382,7 @@ srvwstat(Chan *c, uchar *dp, int n) { char *strs; Srv *sp; + Fid *f; Dir d; if(c->qid.type & QTDIR) @@ -261,13 +397,15 @@ srvwstat(Chan *c, uchar *dp, int n) if(n == 0) error(Eshortstat); - qlock(&srvlk); + f = c->aux; + + qlock(&f->lk); if(waserror()){ - qunlock(&srvlk); + qunlock(&f->lk); nexterror(); } - sp = srvlookup(nil, c->qid.path); + sp = srvlookup(f->tail, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -286,7 +424,7 @@ srvwstat(Chan *c, uchar *dp, int n) if(d.mode != ~0UL) sp->perm = d.mode & 0777; - qunlock(&srvlk); + qunlock(&f->lk); poperror(); free(strs); @@ -298,16 +436,36 @@ srvwstat(Chan *c, uchar *dp, int n) static void srvclose(Chan *c) { + Fid *f; + /* * in theory we need to override any changes in removability * since open, but since all that's checked is the owner, * which is immutable, all is well. */ - if(c->flag & CRCLOSE){ + if((c->flag & COPEN) && (c->flag & CRCLOSE)){ if(waserror()) - return; + goto ref; + srvremove(c); poperror(); + } else { + +ref: + f = c->aux; + if(f == &global) + return; + + qlock(&f->lk); + f->ref--; + if(f->ref == 0){ + assert(f->tail == nil); + qunlock(&f->lk); + free(f); + } else if(f->ref < 0) + panic("srvref close %d %uld", f->ref, NETID(c->qid.path)); + else + qunlock(&f->lk); } } @@ -322,6 +480,7 @@ static long srvwrite(Chan *c, void *va, long n, vlong) { Srv *sp; + Fid *f; Chan *c1; int fd; char buf[32]; @@ -334,15 +493,17 @@ srvwrite(Chan *c, void *va, long n, vlong) c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - qlock(&srvlk); + f = c->aux; + + qlock(&f->lk); if(waserror()) { - qunlock(&srvlk); + qunlock(&f->lk); cclose(c1); nexterror(); } if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = srvlookup(nil, c->qid.path); + sp = srvlookup(f->tail, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -351,7 +512,7 @@ srvwrite(Chan *c, void *va, long n, vlong) sp->chan = c1; - qunlock(&srvlk); + qunlock(&f->lk); poperror(); return n; } @@ -381,11 +542,13 @@ void srvrenameuser(char *old, char *new) { Srv *sp; + Fid *f; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + f = &global; + qlock(&f->lk); + for(sp = f->tail; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - qunlock(&srvlk); + qunlock(&f->lk); } From f1f5045b2e3c0ce6540abad3cad88f5e69a59a3c Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sun, 12 Jun 2022 14:31:55 +0000 Subject: [PATCH 22/58] imx8/usbxhci: bring usb out of reset do all the magic dwc3 specific initalization as well as reset the hub and power on the phys. with this, "usb start" command is not needed anymore from u-boot. --- sys/src/9/imx8/usbxhciimx.c | 104 ++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index 6eebb3dfe..18b6efc00 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1785,6 +1785,92 @@ clkenable(int i, int on) setclkgate(clk, on); } +static void +hubreset(int on) +{ + /* gpio registers */ + enum { + GPIO_DR = 0x00/4, + GPIO_GDIR = 0x04/4, + GPIO_PSR = 0x08/4, + GPIO_ICR1 = 0x0C/4, + GPIO_ICR2 = 0x10/4, + GPIO_IMR = 0x14/4, + GPIO_ISR = 0x18/4, + GPIO_EDGE_SEL = 0x1C/4, + }; + static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); + + gpio1[GPIO_GDIR] |= 1<<14; /* output */ + if(on) + gpio1[GPIO_DR] |= 1<<14; + else + gpio1[GPIO_DR] &= ~(1<<14); +} + +static void +powerup(int i) +{ + /* power gating controller registers */ + enum { + GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, + GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, + USB_OTG1_SW_PUP_REQ = 1<<2, + }; + static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); + + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0x0000FFFF; + + gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] |= (USB_OTG1_SW_PUP_REQ<<i); + while(gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] & (USB_OTG1_SW_PUP_REQ<<i)) + ; + + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0; +} + +static void +phyinit(u32int *reg) +{ + enum { + PHY_CTRL0 = 0x0/4, + CTRL0_REF_SSP_EN = 1<<2, + PHY_CTRL1 = 0x4/4, + CTRL1_RESET = 1<<0, + CTRL1_ATERESET = 1<<3, + CTRL1_VDATSRCENB0 = 1<<19, + CTRL1_VDATDETEBB0 = 1<<20, + PHY_CTRL2 = 0x8/4, + CTRL2_TXENABLEN0 = 1<<8, + }; + reg[PHY_CTRL1] = (reg[PHY_CTRL1] & ~(CTRL1_VDATSRCENB0 | CTRL1_VDATDETEBB0)) | CTRL1_RESET | CTRL1_ATERESET; + reg[PHY_CTRL0] |= CTRL0_REF_SSP_EN; + reg[PHY_CTRL2] |= CTRL2_TXENABLEN0; + reg[PHY_CTRL1] &= ~(CTRL1_RESET | CTRL1_ATERESET); +} + +static void +coreinit(u32int *reg) +{ + enum { + GCTL = 0xC110/4, + PWRDNSCALE_SHIFT = 19, + PWRDNSCALE_MASK = 0x3FFF << PWRDNSCALE_SHIFT, + PRTCAPDIR_SHIFT = 12, + PRTCAPDIR_MASK = 3 << PRTCAPDIR_SHIFT, + DISSCRAMBLE = 1<<3, + DSBLCLKGTNG = 1<<0, + + GFLADJ = 0xC630/4, + GFLADJ_30MHZ_SDBND_SEL = 1<<7, + GFLADJ_30MHZ_SHIFT = 0, + GFLADJ_30MHZ_MASK = 0x3F << GFLADJ_30MHZ_SHIFT, + + }; + reg[GCTL] &= ~(PWRDNSCALE_MASK | DISSCRAMBLE | DSBLCLKGTNG | PRTCAPDIR_MASK); + reg[GCTL] |= 2<<PWRDNSCALE_SHIFT | 1<<PRTCAPDIR_SHIFT; + reg[GFLADJ] = (reg[GFLADJ] & ~GFLADJ_30MHZ_MASK) | 0x20<<GFLADJ_30MHZ_SHIFT | GFLADJ_30MHZ_SDBND_SEL; +} + static int reset(Hci *hp) { @@ -1808,13 +1894,31 @@ reset(Hci *hp) Found: if(i == 0){ + static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); + enum { + IOMUXC_CTL_PAD_GPIO1_IO13 = 0x5C/4, /* for gpio1 13 */ + IOMUXC_CTL_PAD_GPIO1_IO14 = 0x60/4, /* for gpio1 14 */ + + IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14 = 0x2C8/4, + }; + iomuxc[IOMUXC_CTL_PAD_GPIO1_IO13] = 1; + iomuxc[IOMUXC_CTL_PAD_GPIO1_IO14] = 0; + iomuxc[IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14] = 0x16; + + hubreset(0); + microdelay(500); + hubreset(1); + for(i = 0; i < nelem(ctlrs); i++) clkenable(i, 0); setclkrate("ccm_usb_bus_clk_root", "system_pll2_div2", 500*Mhz); setclkrate("ccm_usb_core_ref_clk_root", "system_pll1_div8", 100*Mhz); setclkrate("ccm_usb_phy_ref_clk_root", "system_pll1_div8", 100*Mhz); i = 0; } + powerup(i); clkenable(i, 1); + phyinit(&ctlr->mmio[0xF0040/4]); + coreinit(ctlr->mmio); hp->init = init; hp->dump = dump; From 306e7ca618cec67d780cee0ddf9160a1245d5925 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sun, 12 Jun 2022 15:23:19 +0000 Subject: [PATCH 23/58] devsrv: revert 'add /srv/clone' this leaks /srvs, revert until we can fix it. --- sys/man/3/srv | 11 -- sys/src/9/port/devsrv.c | 265 ++++++++-------------------------------- 2 files changed, 51 insertions(+), 225 deletions(-) diff --git a/sys/man/3/srv b/sys/man/3/srv index 00497c79d..820c849db 100644 --- a/sys/man/3/srv +++ b/sys/man/3/srv @@ -5,7 +5,6 @@ srv \- server registry .nf .B bind #s /srv -.BI #s/ clone/ .BI #s/ service1 .BI #s/ service2 ... @@ -41,16 +40,6 @@ releases that reference. .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. -.PP -A walk to -.I clone -creates a blank private bulletin board. Private boards are -recursable but disjoint; walks may only descend. A process -may get a private -.B /srv -by doing: -.IP -bind -c /srv/clone /srv .SH EXAMPLE To drop one end of a pipe into .BR /srv , diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 9cece906b..8128569a1 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -5,7 +5,6 @@ #include "fns.h" #include "../port/error.h" -#include "netif.h" typedef struct Srv Srv; struct Srv @@ -18,34 +17,16 @@ struct Srv ulong path; }; -typedef struct Fid Fid; -struct Fid -{ - int ref; - QLock lk; - Srv *tail; - ulong nextpath; -}; - -enum{ - Qroot, - Qclone, - - Qend -}; - -static Fid global; - -struct { - QLock; - ulong path; -} sessions; +static QLock srvlk; +static Srv *srv; +static int qidpath; static Srv* -srvlookup(Srv *sp, char *name, ulong qidpath) +srvlookup(char *name, ulong qidpath) { - qidpath = NETTYPE(qidpath); - for(; sp != nil; sp = sp->link) { + Srv *sp; + + for(sp = srv; sp != nil; sp = sp->link) { if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) return sp; } @@ -57,139 +38,47 @@ srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; Qid q; - Fid *f; - ulong id; if(s == DEVDOTDOT){ - switch(NETTYPE(c->qid.path)){ - case Qroot: - mkqid(&q, Qroot, 0, QTDIR); - devdir(c, q, "#s", 0, eve, 0555|DMDIR, dp); - break; - case Qclone: - default: - /* - * Someone has walked down /srv/clone/clone/.... and - * would like back up. We do not allow revisiting - * previous sessions. Dead end - */ - error(Enonexist); - break; - } + devdir(c, c->qid, "#s", 0, eve, 0555, dp); return 1; } - id = NETID(c->qid.path); - if(name != nil && strcmp(name, "clone") == 0){ - /* walk; new session */ - qlock(&sessions); - id = ++sessions.path; - qunlock(&sessions); - - f = smalloc(sizeof *f); - f->ref = 1; - f->nextpath = Qend; - - mkqid(&q, NETQID(id, Qclone), id, QTDIR); - devdir(c, q, "clone", 0, eve, 0555|DMDIR, dp); - c->aux = f; - return 1; - } else if(name == nil && s == 0) { - /* stat, dirread; current session */ - mkqid(&q, NETQID(id, Qclone), id, QTDIR); - devdir(c, q, "clone", 0, eve, 0555|DMDIR, dp); - return 1; - } - - f = c->aux; - qlock(&f->lk); + qlock(&srvlk); if(name != nil) - sp = srvlookup(f->tail, name, -1); + sp = srvlookup(name, -1); else { - s -= 1; - for(sp = f->tail; sp != nil && s > 0; sp = sp->link) + for(sp = srv; sp != nil && s > 0; sp = sp->link) s--; } if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { - qunlock(&f->lk); + qunlock(&srvlk); return -1; } - mkqid(&q, NETQID(id, sp->path), 0, QTFILE); + mkqid(&q, sp->path, 0, QTFILE); /* make sure name string continues to exist after we release lock */ kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - qunlock(&f->lk); + qunlock(&srvlk); return 1; } static void srvinit(void) { - global.nextpath = Qend; + qidpath = 1; } static Chan* srvattach(char *spec) { - Chan *c; - - c = devattach('s', spec); - c->aux = &global; - return c; + return devattach('s', spec); } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - Walkqid *wq; - Fid *f; - int tripped; - - /* - * We need to allow for infinite recursions through clone but we - * don't need to permit passing multiple clones in a single walk. - * This allows us to ensure that only a single clone is alloted - * per walk. - */ - tripped = 0; - if(nname > 1){ - nname = 1; - tripped = 1; - } - wq = devwalk(c, nc, name, nname, 0, 0, srvgen); - if(wq == nil || wq->clone == nil || wq->clone == c) - return wq; - - if(tripped){ - /* - * Our partial walk returned a newly alloc'd clone. - * We wll never see a clunk for that partially walked - * fid, so just clean it up now. - */ - if(NETTYPE(wq->clone->qid.path) == Qclone){ - f = wq->clone->aux; - assert(f->tail == nil); - assert(f->ref == 1); - free(f); - } - /* Correct state to indicate failure to walk all names */ - wq->clone->type = 0; - cclose(wq->clone); - wq->clone = nil; - return wq; - } - if(wq->clone->aux == &global) - return wq; - - if(NETID(c->qid.path) != NETID(wq->clone->qid.path)) - return wq; - - assert(c->aux == wq->clone->aux); - f = c->aux; - qlock(&f->lk); - f->ref++; - qunlock(&f->lk); - return wq; + return devwalk(c, nc, name, nname, 0, 0, srvgen); } static int @@ -202,13 +91,11 @@ char* srvname(Chan *c) { Srv *sp; - Fid *f; char *s; s = nil; - f = &global; - qlock(&f->lk); - for(sp = f->tail; sp != nil; sp = sp->link) { + qlock(&srvlk); + for(sp = srv; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -216,7 +103,7 @@ srvname(Chan *c) break; } } - qunlock(&f->lk); + qunlock(&srvlk); return s; } @@ -224,7 +111,6 @@ static Chan* srvopen(Chan *c, int omode) { Srv *sp; - Fid *f; Chan *nc; if(c->qid.type == QTDIR){ @@ -237,14 +123,13 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } - f = c->aux; - qlock(&f->lk); + qlock(&srvlk); if(waserror()){ - qunlock(&f->lk); + qunlock(&srvlk); nexterror(); } - sp = srvlookup(f->tail, nil, c->qid.path); + sp = srvlookup(nil, c->qid.path); if(sp == nil || sp->chan == nil) error(Eshutdown); @@ -259,7 +144,7 @@ srvopen(Chan *c, int omode) nc = sp->chan; incref(nc); - qunlock(&f->lk); + qunlock(&srvlk); poperror(); cclose(c); @@ -270,7 +155,6 @@ static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { Srv *sp; - Fid *f; if(openmode(omode) != OWRITE) error(Eperm); @@ -278,32 +162,31 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) if(strlen(name) >= sizeof(up->genbuf)) error(Etoolong); - f = c->aux; sp = smalloc(sizeof *sp); kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - qlock(&f->lk); + qlock(&srvlk); if(waserror()){ - qunlock(&f->lk); + qunlock(&srvlk); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(srvlookup(f->tail, name, -1) != nil) + if(srvlookup(name, -1) != nil) error(Eexist); sp->perm = perm&0777; - sp->path = f->nextpath++; + sp->path = qidpath++; - c->qid.path = NETQID(NETID(c->qid.path), sp->path); + c->qid.path = sp->path; c->qid.type = QTFILE; - sp->link = f->tail; - f->tail = sp; + sp->link = srv; + srv = sp; - qunlock(&f->lk); + qunlock(&srvlk); poperror(); c->flag |= COPEN; @@ -316,22 +199,18 @@ static void srvremove(Chan *c) { Srv *sp, **l; - Fid *f; - ulong id; if(c->qid.type == QTDIR) error(Eperm); - f = c->aux; - - qlock(&f->lk); + qlock(&srvlk); if(waserror()){ - qunlock(&f->lk); + qunlock(&srvlk); nexterror(); } - l = &f->tail; + l = &srv; for(sp = *l; sp != nil; sp = *l) { - if(sp->path == NETTYPE(c->qid.path)) + if(sp->path == c->qid.path) break; l = &sp->link; } @@ -352,29 +231,15 @@ srvremove(Chan *c) *l = sp->link; sp->link = nil; - id = NETID(c->qid.path); + qunlock(&srvlk); poperror(); + if(sp->chan != nil) cclose(sp->chan); free(sp->owner); free(sp->name); free(sp); - - if(f == &global){ - qunlock(&f->lk); - return; - } - - f->ref--; - if(f->ref == 0){ - assert(f->tail == nil); - qunlock(&f->lk); - free(f); - } else if(f->ref < 0) - panic("srv ref rm %d id %uld", f->ref, id); - else - qunlock(&f->lk); } static int @@ -382,7 +247,6 @@ srvwstat(Chan *c, uchar *dp, int n) { char *strs; Srv *sp; - Fid *f; Dir d; if(c->qid.type & QTDIR) @@ -397,15 +261,13 @@ srvwstat(Chan *c, uchar *dp, int n) if(n == 0) error(Eshortstat); - f = c->aux; - - qlock(&f->lk); + qlock(&srvlk); if(waserror()){ - qunlock(&f->lk); + qunlock(&srvlk); nexterror(); } - sp = srvlookup(f->tail, nil, c->qid.path); + sp = srvlookup(nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -424,7 +286,7 @@ srvwstat(Chan *c, uchar *dp, int n) if(d.mode != ~0UL) sp->perm = d.mode & 0777; - qunlock(&f->lk); + qunlock(&srvlk); poperror(); free(strs); @@ -436,36 +298,16 @@ srvwstat(Chan *c, uchar *dp, int n) static void srvclose(Chan *c) { - Fid *f; - /* * in theory we need to override any changes in removability * since open, but since all that's checked is the owner, * which is immutable, all is well. */ - if((c->flag & COPEN) && (c->flag & CRCLOSE)){ + if(c->flag & CRCLOSE){ if(waserror()) - goto ref; - + return; srvremove(c); poperror(); - } else { - -ref: - f = c->aux; - if(f == &global) - return; - - qlock(&f->lk); - f->ref--; - if(f->ref == 0){ - assert(f->tail == nil); - qunlock(&f->lk); - free(f); - } else if(f->ref < 0) - panic("srvref close %d %uld", f->ref, NETID(c->qid.path)); - else - qunlock(&f->lk); } } @@ -480,7 +322,6 @@ static long srvwrite(Chan *c, void *va, long n, vlong) { Srv *sp; - Fid *f; Chan *c1; int fd; char buf[32]; @@ -493,17 +334,15 @@ srvwrite(Chan *c, void *va, long n, vlong) c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - f = c->aux; - - qlock(&f->lk); + qlock(&srvlk); if(waserror()) { - qunlock(&f->lk); + qunlock(&srvlk); cclose(c1); nexterror(); } if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = srvlookup(f->tail, nil, c->qid.path); + sp = srvlookup(nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -512,7 +351,7 @@ srvwrite(Chan *c, void *va, long n, vlong) sp->chan = c1; - qunlock(&f->lk); + qunlock(&srvlk); poperror(); return n; } @@ -542,13 +381,11 @@ void srvrenameuser(char *old, char *new) { Srv *sp; - Fid *f; - f = &global; - qlock(&f->lk); - for(sp = f->tail; sp != nil; sp = sp->link) { + qlock(&srvlk); + for(sp = srv; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - qunlock(&f->lk); + qunlock(&srvlk); } From 771a93f3b7e8f18ac81c9c54152605214f82ff10 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sun, 12 Jun 2022 16:15:55 +0000 Subject: [PATCH 24/58] imx8/lcd: reduce flicker increasing the pixel clock to 80% of the edid clock value reduces flicker and also seems to not trigger the shifting issue. --- sys/src/9/imx8/lcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index 661585eee..c3ab44a37 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -933,9 +933,9 @@ lcdinit(void) /* * start the pixel clock. running at the actual pixel clock * causes the screen to shift horizontally after a while. - * using 60% seems to fix it - for now. + * using 80% seems to fix it - for now. */ - setclkrate("lcdif.pix_clk", "system_pll1_clk", (mode.pixclk*6)/10); + setclkrate("lcdif.pix_clk", "system_pll1_clk", (mode.pixclk*8)/10); dpiinit(&mode); /* release dpi reset */ From d35e41424ca244b2fbcce9e1cac9651cbd062741 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sun, 12 Jun 2022 21:16:47 +0000 Subject: [PATCH 25/58] imx8: make gpc functionality available with a powerup() function --- sys/src/9/imx8/fns.h | 3 ++ sys/src/9/imx8/gpc.c | 63 +++++++++++++++++++++++++++++++++++++ sys/src/9/imx8/lcd.c | 20 +----------- sys/src/9/imx8/reform | 1 + sys/src/9/imx8/usbxhciimx.c | 23 ++------------ 5 files changed, 70 insertions(+), 40 deletions(-) create mode 100644 sys/src/9/imx8/gpc.c diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 31baa25c9..17ff2ec49 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -145,5 +145,8 @@ extern void setclkgate(char *name, int on); extern void setclkrate(char *name, char *source, int freq); extern int getclkrate(char *name); +/* gpc */ +extern void powerup(char *dom); + /* lcd */ extern void lcdinit(void); diff --git a/sys/src/9/imx8/gpc.c b/sys/src/9/imx8/gpc.c new file mode 100644 index 000000000..5b3ef8794 --- /dev/null +++ b/sys/src/9/imx8/gpc.c @@ -0,0 +1,63 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +/* power gating controller registers */ +enum { + GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, + GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, + GPC_PGC_PU_PGC_SW_PDN_REQ = 0x104/4, +}; + +static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); + +typedef struct Tab Tab; +struct Tab { + char *dom; + uint mask; +}; + +static Tab pu_tab[] = { + "mipi", 1<<0, + "pcie", 1<<1, + "usb_otg1", 1<<2, + "usb_otg2", 1<<3, + "ddr1", 1<<5, + "ddr2", 1<<6, + "gpu", 1<<7, + "vpu", 1<<8, + "hdmi", 1<<9, + "disp", 1<<10, + "mipi_csi1", 1<<11, + "mipi_csi2", 1<<12, + "pcie2", 1<<13, + + nil, +}; + +void +powerup(char *dom) +{ + Tab *t; + + if(dom == nil) + return; + + for(t = pu_tab; t->dom != nil; t++) + if(cistrcmp(dom, t->dom) == 0) + goto Found; + + panic("powerup: domain %s not defined", dom); + +Found: + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0x0000FFFF; + + gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] |= t->mask; + while(gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] & t->mask) + ; + + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0; +} diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index c3ab44a37..15a10d544 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -39,19 +39,6 @@ enum { GPIO_EDGE_SEL = 0x1C/4, }; -/* power gating controller registers */ -enum { - GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, - GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, - - GPC_A53_PU_PGC_PUP_STATUS0 = 0x1C4/4, - GPC_A53_PU_PGC_PUP_STATUS1 = 0x1C8/4, - GPC_A53_PU_PGC_PUP_STATUS2 = 0x1CC/4, - DISP_SW_PUP_REQ = 1<<10, - HDMI_SW_PUP_REQ = 1<<9, - MIPI_SW_PUP_REQ = 1<<0, -}; - /* system reset controller registers */ enum { SRC_MIPIPHY_RCR = 0x28/4, @@ -393,7 +380,6 @@ static u32int *gpio3 = (u32int*)(VIRTIO + 0x220000); static u32int *pwm2 = (u32int*)(VIRTIO + 0x670000); static u32int *resetc= (u32int*)(VIRTIO + 0x390000); -static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); static u32int *dsi = (u32int*)(VIRTIO + 0xA00000); static u32int *dphy = (u32int*)(VIRTIO + 0xA00300); @@ -875,11 +861,7 @@ lcdinit(void) bridge->subaddr = 1; /* power on mipi dsi */ - wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0x0000FFFF); - mr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ, MIPI_SW_PUP_REQ, MIPI_SW_PUP_REQ); - while(rr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ) & MIPI_SW_PUP_REQ) - ; - wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0); + powerup("mipi"); mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_N); mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_PCLK_RESET_N); diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index 64a012e7d..ff00d402c 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -36,6 +36,7 @@ ip ipmux misc ccm + gpc gic uartimx lcd diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index 18b6efc00..ea08d002e 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1808,26 +1808,6 @@ hubreset(int on) gpio1[GPIO_DR] &= ~(1<<14); } -static void -powerup(int i) -{ - /* power gating controller registers */ - enum { - GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, - GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, - USB_OTG1_SW_PUP_REQ = 1<<2, - }; - static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); - - gpc[GPC_PGC_CPU_0_1_MAPPING] = 0x0000FFFF; - - gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] |= (USB_OTG1_SW_PUP_REQ<<i); - while(gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] & (USB_OTG1_SW_PUP_REQ<<i)) - ; - - gpc[GPC_PGC_CPU_0_1_MAPPING] = 0; -} - static void phyinit(u32int *reg) { @@ -1874,6 +1854,7 @@ coreinit(u32int *reg) static int reset(Hci *hp) { + static char *powerdom[] = { "usb_otg1", "usb_otg2" }; static Ctlr ctlrs[2]; Ctlr *ctlr; int i; @@ -1915,7 +1896,7 @@ Found: setclkrate("ccm_usb_phy_ref_clk_root", "system_pll1_div8", 100*Mhz); i = 0; } - powerup(i); + powerup(powerdom[i]); clkenable(i, 1); phyinit(&ctlr->mmio[0xF0040/4]); coreinit(ctlr->mmio); From 90428d0561d8848917c81a4b6ac53067b009eb2f Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 19:06:00 +0000 Subject: [PATCH 26/58] imx8: add iomuxpad() helper for pad and mux control --- sys/src/9/imx8/fns.h | 3 + sys/src/9/imx8/iomux.c | 1125 +++++++++++++++++++++++++++++++++++ sys/src/9/imx8/lcd.c | 20 +- sys/src/9/imx8/reform | 1 + sys/src/9/imx8/usbxhciimx.c | 12 +- 5 files changed, 1139 insertions(+), 22 deletions(-) create mode 100644 sys/src/9/imx8/iomux.c diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 17ff2ec49..d0f276a53 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -150,3 +150,6 @@ extern void powerup(char *dom); /* lcd */ extern void lcdinit(void); + +/* iomuc */ +extern void iomuxpad(char *pads, char *sel, char *cfg); diff --git a/sys/src/9/imx8/iomux.c b/sys/src/9/imx8/iomux.c new file mode 100644 index 000000000..73184e74e --- /dev/null +++ b/sys/src/9/imx8/iomux.c @@ -0,0 +1,1125 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); + +enum { + IOMUXC_SW_MUX_CTL_PAD_PMIC_STBY_REQ = 0x014/4, + SION = 1<<4, + MUX_MODE = 7, + + IOMUXC_SW_PAD_CTL_PAD_TEST_MODE = 0x254/4, + + IOMUXC_CCM_PMIC_READY_SELECT_INPUT = 0x4BC/4, +}; + +enum { + /* pads without muxes */ + PAD_TEST_MODE = 0, + + PAD_BOOT_MODE0, PAD_BOOT_MODE1, + + PAD_JTAG_MOD, PAD_JTAG_TRST_B, PAD_JTAG_TDI, PAD_JTAG_TMS, + PAD_JTAG_TCK, PAD_JTAG_TDO, + + PAD_RTC, + + PAD_PMIC_STBY_REQ, PAD_PMIC_ON_REQ, + PAD_ONOFF, PAD_POR_B, PAD_RTC_RESET_B, + + /* pads with muxes */ + PAD_GPIO1_IO00, PAD_GPIO1_IO01, PAD_GPIO1_IO02, PAD_GPIO1_IO03, + PAD_GPIO1_IO04, PAD_GPIO1_IO05, PAD_GPIO1_IO06, PAD_GPIO1_IO07, + PAD_GPIO1_IO08, PAD_GPIO1_IO09, PAD_GPIO1_IO10, PAD_GPIO1_IO11, + PAD_GPIO1_IO12, PAD_GPIO1_IO13, PAD_GPIO1_IO14, PAD_GPIO1_IO15, + + PAD_ENET_MDC, PAD_ENET_MDIO, + PAD_ENET_TD3, PAD_ENET_TD2, PAD_ENET_TD1, PAD_ENET_TD0, + PAD_ENET_TX_CTL, PAD_ENET_TXC, PAD_ENET_RX_CTL, PAD_ENET_RXC, + PAD_ENET_RD0, PAD_ENET_RD1, PAD_ENET_RD2, PAD_ENET_RD3, + + PAD_SD1_CLK, PAD_SD1_CMD, PAD_SD1_DATA0, PAD_SD1_DATA1, + PAD_SD1_DATA2, PAD_SD1_DATA3, PAD_SD1_DATA4, PAD_SD1_DATA5, + PAD_SD1_DATA6, PAD_SD1_DATA7, PAD_SD1_RESET_B, PAD_SD1_STROBE, + + PAD_SD2_CD_B, PAD_SD2_CLK, PAD_SD2_CMD, PAD_SD2_DATA0, + PAD_SD2_DATA1, PAD_SD2_DATA2, PAD_SD2_DATA3, + PAD_SD2_RESET_B, PAD_SD2_WP, + + PAD_NAND_ALE, PAD_NAND_CE0_B, PAD_NAND_CE1_B, PAD_NAND_CE2_B, + PAD_NAND_CE3_B, PAD_NAND_CLE, PAD_NAND_DATA0, PAD_NAND_DATA1, + PAD_NAND_DATA2, PAD_NAND_DATA3, PAD_NAND_DATA4, + PAD_NAND_DATA5, PAD_NAND_DATA6, PAD_NAND_DATA7, PAD_NAND_DQS, + PAD_NAND_RE_B, PAD_NAND_READY_B, PAD_NAND_WE_B, PAD_NAND_WP_B, + + PAD_SAI5_RXFS, PAD_SAI5_RXC, PAD_SAI5_RXD0, PAD_SAI5_RXD1, + PAD_SAI5_RXD2, PAD_SAI5_RXD3, PAD_SAI5_MCLK, + + PAD_SAI1_RXFS, PAD_SAI1_RXC, PAD_SAI1_RXD0, PAD_SAI1_RXD1, + PAD_SAI1_RXD2, PAD_SAI1_RXD3, PAD_SAI1_RXD4, PAD_SAI1_RXD5, + PAD_SAI1_RXD6, PAD_SAI1_RXD7, PAD_SAI1_TXFS, PAD_SAI1_TXC, + PAD_SAI1_TXD0, PAD_SAI1_TXD1, PAD_SAI1_TXD2, PAD_SAI1_TXD3, + PAD_SAI1_TXD4, PAD_SAI1_TXD5, PAD_SAI1_TXD6, PAD_SAI1_TXD7, + PAD_SAI1_MCLK, + + PAD_SAI2_RXFS, PAD_SAI2_RXC, PAD_SAI2_RXD0, PAD_SAI2_TXFS, + PAD_SAI2_TXC, PAD_SAI2_TXD0, PAD_SAI2_MCLK, + + PAD_SAI3_RXFS, PAD_SAI3_RXC, PAD_SAI3_RXD, PAD_SAI3_TXFS, + PAD_SAI3_TXC, PAD_SAI3_TXD, PAD_SAI3_MCLK, + + PAD_SPDIF_TX, PAD_SPDIF_RX, PAD_SPDIF_EXT_CLK, + + PAD_ECSPI1_SCLK, PAD_ECSPI1_MOSI, PAD_ECSPI1_MISO, PAD_ECSPI1_SS0, + PAD_ECSPI2_SCLK, PAD_ECSPI2_MOSI, PAD_ECSPI2_MISO, PAD_ECSPI2_SS0, + + PAD_I2C1_SCL, PAD_I2C1_SDA, + PAD_I2C2_SCL, PAD_I2C2_SDA, + PAD_I2C3_SCL, PAD_I2C3_SDA, + PAD_I2C4_SCL, PAD_I2C4_SDA, + + PAD_UART1_RXD, PAD_UART1_TXD, + PAD_UART2_RXD, PAD_UART2_TXD, + PAD_UART3_RXD, PAD_UART3_TXD, + PAD_UART4_RXD, PAD_UART4_TXD, +}; + +enum { + /* signals with input muxes (must be first for daisytab) */ + CCM_PMIC_READY = 0, + ENET1_MDIO, + PCIE1_CLKREQ_B, PCIE2_CLKREQ_B, + SAI1_RX_BCLK, SAI1_RX_SYNC, SAI1_TX_SYNC, + SAI5_MCLK, SAI5_RXD0, SAI5_RXD1, SAI5_RXD2, SAI5_RXD3, + SAI5_RX_BCLK, SAI5_RX_SYNC, SAI5_TX_BLCK, SAI5_TX_SYNC, + SAI6_MCLK, SAI6_RXD0, SAI6_RX_BCLK, SAI6_RX_SYNC, + SAI6_TX_BCLK, SAY6_TX_SYNC, + UART1_RTS_B, UART1_RXD, + UART2_RTS_B, UART2_RXD, + UART3_RTS_B, UART3_RXD, + UART4_RTS_B, UART4_RXD, + + /* signals without input muxes */ + ANAMIX_REF_CLK_25M, + ANAMIX_REF_CLK_32K, + CCM_CLKO1, + CCM_CLKO2, + CCM_ENET_PHY_REF_CLK_ROOT, + CCM_EXT_CLK1, + CCM_EXT_CLK2, + CCM_EXT_CLK3, + CCM_EXT_CLK4, + + CORESIGHT_EVENTI, CORESIGHT_EVENTO, CORESIGHT_TRACE0, + CORESIGHT_TRACE1, CORESIGHT_TRACE10, CORESIGHT_TRACE11, + CORESIGHT_TRACE12, CORESIGHT_TRACE13, CORESIGHT_TRACE14, + CORESIGHT_TRACE15, CORESIGHT_TRACE2, CORESIGHT_TRACE3, + CORESIGHT_TRACE4, CORESIGHT_TRACE5, CORESIGHT_TRACE6, + CORESIGHT_TRACE7, CORESIGHT_TRACE8, CORESIGHT_TRACE9, + CORESIGHT_TRACE_CLK, CORESIGHT_TRACE_CTL, + + ECSPI1_MISO, ECSPI1_MOSI, ECSPI1_SCLK, ECSPI1_SS0, + ECSPI2_MISO, ECSPI2_MOSI, ECSPI2_SCLK, ECSPI2_SS0, + ECSPI3_MISO, ECSPI3_MOSI, ECSPI3_SCLK, ECSPI3_SS0, + ENET1_1588_EVENT0_IN, ENET1_1588_EVENT0_OUT, + ENET1_1588_EVENT1_IN, ENET1_1588_EVENT1_OUT, + ENET1_MDC, ENET1_RGMII_RD0, ENET1_RGMII_RD1, ENET1_RGMII_RD2, + ENET1_RGMII_RD3, ENET1_RGMII_RXC, ENET1_RGMII_RX_CTL, + ENET1_RGMII_TD0, ENET1_RGMII_TD1, ENET1_RGMII_TD2, + ENET1_RGMII_TD3, ENET1_RGMII_TXC, ENET1_RGMII_TX_CTL, + ENET1_RX_ER, ENET1_TX_CLK, ENET1_TX_ER, + + GPIO1_IO00, GPIO1_IO01, GPIO1_IO02, GPIO1_IO03, GPIO1_IO04, + GPIO1_IO05, GPIO1_IO06, GPIO1_IO07, GPIO1_IO08, GPIO1_IO09, + GPIO1_IO10, GPIO1_IO11, GPIO1_IO12, GPIO1_IO13, GPIO1_IO14, + GPIO1_IO15, GPIO1_IO16, GPIO1_IO17, GPIO1_IO18, GPIO1_IO19, + GPIO1_IO20, GPIO1_IO21, GPIO1_IO22, GPIO1_IO23, GPIO1_IO24, + GPIO1_IO25, GPIO1_IO26, GPIO1_IO27, GPIO1_IO28, GPIO1_IO29, + + GPIO2_IO00, GPIO2_IO01, GPIO2_IO02, GPIO2_IO03, GPIO2_IO04, + GPIO2_IO05, GPIO2_IO06, GPIO2_IO07, GPIO2_IO08, GPIO2_IO09, + GPIO2_IO10, GPIO2_IO11, GPIO2_IO12, GPIO2_IO13, GPIO2_IO14, + GPIO2_IO15, GPIO2_IO16, GPIO2_IO17, GPIO2_IO18, GPIO2_IO19, + GPIO2_IO20, + + GPIO3_IO00, GPIO3_IO01, GPIO3_IO02, GPIO3_IO03, GPIO3_IO04, + GPIO3_IO05, GPIO3_IO06, GPIO3_IO07, GPIO3_IO08, GPIO3_IO09, + GPIO3_IO10, GPIO3_IO11, GPIO3_IO12, GPIO3_IO13, GPIO3_IO14, + GPIO3_IO15, GPIO3_IO16, GPIO3_IO17, GPIO3_IO18, GPIO3_IO19, + GPIO3_IO20, GPIO3_IO21, GPIO3_IO22, GPIO3_IO23, GPIO3_IO24, + GPIO3_IO25, + + GPIO4_IO00, GPIO4_IO01, GPIO4_IO02, GPIO4_IO03, GPIO4_IO04, + GPIO4_IO05, GPIO4_IO06, GPIO4_IO07, GPIO4_IO08, GPIO4_IO09, + GPIO4_IO10, GPIO4_IO11, GPIO4_IO12, GPIO4_IO13, GPIO4_IO14, + GPIO4_IO15, GPIO4_IO16, GPIO4_IO17, GPIO4_IO18, GPIO4_IO19, + GPIO4_IO20, GPIO4_IO21, GPIO4_IO22, GPIO4_IO23, GPIO4_IO24, + GPIO4_IO25, GPIO4_IO26, GPIO4_IO27, GPIO4_IO28, GPIO4_IO29, + GPIO4_IO31, + + GPIO5_IO00, GPIO5_IO01, GPIO5_IO02, GPIO5_IO03, GPIO5_IO04, + GPIO5_IO05, GPIO5_IO06, GPIO5_IO07, GPIO5_IO08, GPIO5_IO09, + GPIO5_IO10, GPIO5_IO11, GPIO5_IO12, GPIO5_IO13, GPIO5_IO14, + GPIO5_IO15, GPIO5_IO16, GPIO5_IO17, GPIO5_IO18, GPIO5_IO19, + GPIO5_IO20, GPIO5_IO21, GPIO5_IO22, GPIO5_IO23, GPIO5_IO24, + GPIO5_IO25, GPIO5_IO26, GPIO5_IO27, GPIO5_IO28, GPIO5_IO29, + + GPT1_CAPTURE1, GPT1_CAPTURE2, GPT1_COMPARE1, GPT1_COMPARE2, + GPT1_COMPARE3, GPT1_CLK, GPT2_CLK, GPT3_CLK, + + I2C1_SCL, I2C1_SDA, + I2C2_SCL, I2C2_SDA, + I2C3_SCL, I2C3_SDA, + I2C4_SCL, I2C4_SDA, + M4_NMI, + PCIE_CLKREQ_B, + PWM1_OUT, PWM2_OUT, PWM3_OUT, PWM4_OUT, + + QSPI_A_DATA0, QSPI_A_DATA1, QSPI_A_DATA2, QSPI_A_DATA3, + QSPI_A_DQS, QSPI_A_SCLK, QSPI_A_SS0_B, QSPI_A_SS1_B, + + QSPI_B_DATA0, QSPI_B_DATA1, QSPI_B_DATA2, QSPI_B_DATA3, + QSPI_B_DQS, QSPI_B_SCLK, QSPI_B_SS0_B, QSPI_B_SS1_B, + + RAWNAND_ALE, RAWNAND_CE0_B, RAWNAND_CE1_B, RAWNAND_CE2_B, + RAWNAND_CE3_B, RAWNAND_CLE, RAWNAND_DATA00, RAWNAND_DATA01, + RAWNAND_DATA02, RAWNAND_DATA03, RANWNAD_DATA04, + RAWNAND_DATA05, RAWNAND_DATA06, RAWNAND_DATA07, RAWNAND_DQS, + RAWNAND_READY_B, RAWNAND_RE_B, RAWNAND_WE_B, RAWNAND_WP_B, + + SAI1_MCLK, SAI1_RX_DATA0, SAI1_RX_DATA1, SAI1_RX_DATA2, + SAI1_RX_DATA3, SAI1_RX_DATA4, SAI1_RX_DATA5, SAI1_RX_DATA6, + SAI1_RX_DATA7, SAI1_TX_BCLK, SAI1_TX_DATA0, SAI1_TX_DATA1, + SAI1_TX_DATA2, SAI1_TX_DATA3, SAI1_TX_DATA4, SAI1_TX_DATA5, + SAI1_TX_DATA6, SAI1_TX_DATA7, + + SAI2_MCLK, SAI2_RX_BCLK, SAI2_RX_DATA0, SAI2_RX_SYNC, + SAI2_TX_BCLK, SAI2_TX_DATA0, SAI2_TX_SYNC, + SAI3_MCLK, SAI3_RX_BCLK, SAI3_RX_DATA0, SAI3_RX_SYNC, + SAI3_TX_BCLK, SAI3_TX_DATA0, SAI3_TX_SYNC, + + SAI4_MCLK, + + SAI5_RX_DATA0, SAI5_RX_DATA1, SAI5_RX_DATA2, SAI5_RX_DATA3, + SAI5_TX_BCLK, SAI5_TX_DATA0, SAI5_TX_DATA1, SAI5_TX_DATA2, + SAI5_TX_DATA3, + + SAI6_RC_BCLK, SAI6_RX_DATA0, SAI6_TX_DATA0, SAI6_TX_SYNC, + + SDMA1_EXT_EVENT0, SDMA1_EXT_EVENT1, + SDMA2_EXT_EVENT0, SDMA2_EXT_EVENT1, + + SJC_DE_B, + + SPDIF1_EXT_CLK, SPDIF1_IN, SPDIF1_OUT, + + SRC_BOOT_CFG0, SRC_BOOT_CFG1, SRC_BOOT_CFG2, SRC_BOOT_CFG3, + SRC_BOOT_CFG4, SRC_BOOT_CFG5, SRC_BOOT_CFG6, SRC_BOOT_CFG7, + SRC_BOOT_CFG8, SRC_BOOT_CFG9, SRC_BOOT_CFG10, SRC_BOOT_CFG11, + SRC_BOOT_CFG12, SRC_BOOT_CFG13, SRC_BOOT_CFG14, SRC_BOOT_CFG15, + + UART1_CTS_B, UART1_RX, UART1_TX, + UART2_CTS_B, UART2_RX, UART2_TX, + UART3_CTS_B, UART3_RX, UART3_TX, + UART4_CTS_B, UART4_RX, UART4_TX, + + USB1_OTG_ID, USB1_OTG_OC, USB1_OTG_PWR, + USB2_OTG_ID, USB2_OTG_OC, USB2_OTG_PWR, + + USDHC1_CD_B, USDHC1_CLK, USDHC1_CMD, USDHC1_DATA0, + USDHC1_DATA1, USDHC1_DATA2, USDHC1_DATA3, USDHC1_DATA4, + USDHC1_DATA5, USDHC1_DATA6, USDHC1_DATA7, USDHC1_RESET_B, + USDHC1_STROBE, USDHC1_VSELECT, USDHC1_WP, + + USDHC2_CD_B, USDHC2_CLK, USDHC2_CMD, USDHC2_DATA0, + USDHC2_DATA1, USDHC2_DATA2, USDHC2_DATA3, USDHC2_RESET_B, + USDHC2_VSELECT, USDHC2_WP, + + WDOG1_WDOG_ANY, WDOG1_WDOG_B, +}; + +#define DAISY(x) (0x8000|(((x)&7)<<12)) +#define DAISY_VAL(x) (((x)>>12)&7) +#define DAISY_ID(x) ((x) & ~DAISY(7)) + +static ushort daisytab[] = { + [CCM_PMIC_READY] 0 | DAISY(1), + [ENET1_MDIO] 1 | DAISY(3), + [PCIE1_CLKREQ_B] 26 | DAISY(1), + [PCIE2_CLKREQ_B] 27 | DAISY(1), + [SAI1_RX_BCLK] 3 | DAISY(3), + [SAI1_RX_SYNC] 2 | DAISY(1), + [SAI1_TX_SYNC] 4 | DAISY(7), + [SAI5_MCLK] 28 | DAISY(3), + [SAI5_RXD0] 6 | DAISY(3), + [SAI5_RXD1] 7 | DAISY(3), + [SAI5_RXD2] 8 | DAISY(3), + [SAI5_RXD3] 9 | DAISY(3), + [SAI5_RX_BCLK] 5 | DAISY(3), + [SAI5_RX_SYNC] 10 | DAISY(3), + [SAI5_TX_BLCK] 11 | DAISY(3), + [SAI5_TX_SYNC] 12 | DAISY(3), + [SAI6_MCLK] 29 | DAISY(1), + [SAI6_RXD0] 22 | DAISY(1), + [SAI6_RX_BCLK] 21 | DAISY(1), + [SAI6_RX_SYNC] 23 | DAISY(1), + [SAI6_TX_BCLK] 24 | DAISY(1), + [SAY6_TX_SYNC] 25 | DAISY(1), + [UART1_RTS_B] 13 | DAISY(1), + [UART1_RXD] 14 | DAISY(1), + [UART2_RTS_B] 15 | DAISY(1), + [UART2_RXD] 16 | DAISY(1), + [UART3_RTS_B] 17 | DAISY(1), + [UART3_RXD] 18 | DAISY(3), + [UART4_RTS_B] 19 | DAISY(1), + [UART4_RXD] 20 | DAISY(3), +}; + +static ushort padmux[] = { + [PAD_GPIO1_IO00*8] GPIO1_IO00, CCM_ENET_PHY_REF_CLK_ROOT, 0, 0, 0, ANAMIX_REF_CLK_32K, CCM_EXT_CLK1, 0, + [PAD_GPIO1_IO01*8] GPIO1_IO01, PWM1_OUT, 0, 0, 0, ANAMIX_REF_CLK_25M, CCM_EXT_CLK2, 0, + [PAD_GPIO1_IO02*8] GPIO1_IO02, WDOG1_WDOG_B, 0, 0, 0, WDOG1_WDOG_ANY, 0, SJC_DE_B, + [PAD_GPIO1_IO03*8] GPIO1_IO03, USDHC1_VSELECT, 0, 0, 0, SDMA1_EXT_EVENT0, 0, 0, + [PAD_GPIO1_IO04*8] GPIO1_IO04, USDHC2_VSELECT, 0, 0, 0, SDMA1_EXT_EVENT1, 0, 0, + [PAD_GPIO1_IO05*8] GPIO1_IO05, M4_NMI, 0, 0, 0, CCM_PMIC_READY|DAISY(0), 0, 0, + [PAD_GPIO1_IO06*8] GPIO1_IO06, ENET1_MDC, 0, 0, 0, USDHC1_CD_B, CCM_EXT_CLK3, 0, + [PAD_GPIO1_IO07*8] GPIO1_IO07, ENET1_MDIO|DAISY(0), 0, 0, 0, USDHC1_WP, CCM_EXT_CLK4, 0, + [PAD_GPIO1_IO08*8] GPIO1_IO08, ENET1_1588_EVENT0_IN, 0, 0, 0, USDHC2_RESET_B, 0, 0, + [PAD_GPIO1_IO09*8] GPIO1_IO09, ENET1_1588_EVENT0_OUT, 0, 0, 0, SDMA2_EXT_EVENT0, 0, 0, + [PAD_GPIO1_IO10*8] GPIO1_IO10, USB1_OTG_ID, 0, 0, 0, 0, 0, 0, + [PAD_GPIO1_IO11*8] GPIO1_IO11, USB2_OTG_ID, 0, 0, 0, CCM_PMIC_READY|DAISY(1), 0, 0, + [PAD_GPIO1_IO12*8] GPIO1_IO12, USB1_OTG_PWR, 0, 0, 0, SDMA2_EXT_EVENT1, 0, 0, + [PAD_GPIO1_IO13*8] GPIO1_IO13, USB1_OTG_OC, 0, 0, 0, PWM2_OUT, 0, 0, + [PAD_GPIO1_IO14*8] GPIO1_IO14, USB2_OTG_PWR, 0, 0, 0, PWM3_OUT, CCM_CLKO1, 0, + [PAD_GPIO1_IO15*8] GPIO1_IO15, USB2_OTG_OC, 0, 0, 0, PWM4_OUT, CCM_CLKO2, 0, + [PAD_ENET_MDC*8] ENET1_MDC, 0, 0, 0, 0, GPIO1_IO16, 0, 0, + [PAD_ENET_MDIO*8] ENET1_MDIO|DAISY(1), 0, 0, 0, 0, GPIO1_IO17, 0, 0, + [PAD_ENET_TD3*8] ENET1_RGMII_TD3, 0, 0, 0, 0, GPIO1_IO18, 0, 0, + [PAD_ENET_TD2*8] ENET1_RGMII_TD2, ENET1_TX_CLK, 0, 0, 0, GPIO1_IO19, 0, 0, + [PAD_ENET_TD1*8] ENET1_RGMII_TD1, 0, 0, 0, 0, GPIO1_IO20, 0, 0, + [PAD_ENET_TD0*8] ENET1_RGMII_TD0, 0, 0, 0, 0, GPIO1_IO21, 0, 0, + [PAD_ENET_TX_CTL*8] ENET1_RGMII_TX_CTL, 0, 0, 0, 0, GPIO1_IO22, 0, 0, + [PAD_ENET_TXC*8] ENET1_RGMII_TXC, ENET1_TX_ER, 0, 0, 0, GPIO1_IO23, 0, 0, + [PAD_ENET_RX_CTL*8] ENET1_RGMII_RX_CTL, 0, 0, 0, 0, GPIO1_IO24, 0, 0, + [PAD_ENET_RXC*8] ENET1_RGMII_RXC, ENET1_RX_ER, 0, 0, 0, GPIO1_IO25, 0, 0, + [PAD_ENET_RD0*8] ENET1_RGMII_RD0, 0, 0, 0, 0, GPIO1_IO26, 0, 0, + [PAD_ENET_RD1*8] ENET1_RGMII_RD1, 0, 0, 0, 0, GPIO1_IO27, 0, 0, + [PAD_ENET_RD2*8] ENET1_RGMII_RD2, 0, 0, 0, 0, GPIO1_IO28, 0, 0, + [PAD_ENET_RD3*8] ENET1_RGMII_RD3, 0, 0, 0, 0, GPIO1_IO29, 0, 0, + [PAD_SD1_CLK*8] USDHC1_CLK, 0, 0, 0, 0, GPIO2_IO00, 0, 0, + [PAD_SD1_CMD*8] USDHC1_CMD, 0, 0, 0, 0, GPIO2_IO01, 0, 0, + [PAD_SD1_DATA0*8] USDHC1_DATA0, 0, 0, 0, 0, GPIO2_IO02, 0, 0, + [PAD_SD1_DATA1*8] USDHC1_DATA1, 0, 0, 0, 0, GPIO2_IO03, 0, 0, + [PAD_SD1_DATA2*8] USDHC1_DATA2, 0, 0, 0, 0, GPIO2_IO04, 0, 0, + [PAD_SD1_DATA3*8] USDHC1_DATA3, 0, 0, 0, 0, GPIO2_IO05, 0, 0, + [PAD_SD1_DATA4*8] USDHC1_DATA4, 0, 0, 0, 0, GPIO2_IO06, 0, 0, + [PAD_SD1_DATA5*8] USDHC1_DATA5, 0, 0, 0, 0, GPIO2_IO07, 0, 0, + [PAD_SD1_DATA6*8] USDHC1_DATA6, 0, 0, 0, 0, GPIO2_IO08, 0, 0, + [PAD_SD1_DATA7*8] USDHC1_DATA7, 0, 0, 0, 0, GPIO2_IO09, 0, 0, + [PAD_SD1_RESET_B*8] USDHC1_RESET_B, 0, 0, 0, 0, GPIO2_IO10, 0, 0, + [PAD_SD1_STROBE*8] USDHC1_STROBE, 0, 0, 0, 0, GPIO2_IO11, 0, 0, + [PAD_SD2_CD_B*8] USDHC2_CD_B, 0, 0, 0, 0, GPIO2_IO12, 0, 0, + [PAD_SD2_CLK*8] USDHC2_CLK, 0, 0, 0, 0, GPIO2_IO13, 0, 0, + [PAD_SD2_CMD*8] USDHC2_CMD, 0, 0, 0, 0, GPIO2_IO14, 0, 0, + [PAD_SD2_DATA0*8] USDHC2_DATA0, 0, 0, 0, 0, GPIO2_IO15, 0, 0, + [PAD_SD2_DATA1*8] USDHC2_DATA1, 0, 0, 0, 0, GPIO2_IO16, 0, 0, + [PAD_SD2_DATA2*8] USDHC2_DATA2, 0, 0, 0, 0, GPIO2_IO17, 0, 0, + [PAD_SD2_DATA3*8] USDHC2_DATA3, 0, 0, 0, 0, GPIO2_IO18, 0, 0, + [PAD_SD2_RESET_B*8] USDHC2_RESET_B, 0, 0, 0, 0, GPIO2_IO19, 0, 0, + [PAD_SD2_WP*8] USDHC2_WP, 0, 0, 0, 0, GPIO2_IO20, 0, 0, + [PAD_NAND_ALE*8] RAWNAND_ALE, QSPI_A_SCLK, 0, 0, 0, GPIO3_IO00, 0, 0, + [PAD_NAND_CE0_B*8] RAWNAND_CE0_B, QSPI_A_SS0_B, 0, 0, 0, GPIO3_IO01, 0, 0, + [PAD_NAND_CE1_B*8] RAWNAND_CE1_B, QSPI_A_SS1_B, 0, 0, 0, GPIO3_IO02, 0, 0, + [PAD_NAND_CE2_B*8] RAWNAND_CE2_B, QSPI_B_SS0_B, 0, 0, 0, GPIO3_IO03, 0, 0, + [PAD_NAND_CE3_B*8] RAWNAND_CE3_B, QSPI_B_SS1_B, 0, 0, 0, GPIO3_IO04, 0, 0, + [PAD_NAND_CLE*8] RAWNAND_CLE, QSPI_B_SCLK, 0, 0, 0, GPIO3_IO05, 0, 0, + [PAD_NAND_DATA0*8] RAWNAND_DATA00, QSPI_A_DATA0, 0, 0, 0, GPIO3_IO06, 0, 0, + [PAD_NAND_DATA1*8] RAWNAND_DATA01, QSPI_A_DATA1, 0, 0, 0, GPIO3_IO07, 0, 0, + [PAD_NAND_DATA2*8] RAWNAND_DATA02, QSPI_A_DATA2, 0, 0, 0, GPIO3_IO08, 0, 0, + [PAD_NAND_DATA3*8] RAWNAND_DATA03, QSPI_A_DATA3, 0, 0, 0, GPIO3_IO09, 0, 0, + [PAD_NAND_DATA4*8] RANWNAD_DATA04, QSPI_B_DATA0, 0, 0, 0, GPIO3_IO10, 0, 0, + [PAD_NAND_DATA5*8] RAWNAND_DATA05, QSPI_B_DATA1, 0, 0, 0, GPIO3_IO11, 0, 0, + [PAD_NAND_DATA6*8] RAWNAND_DATA06, QSPI_B_DATA2, 0, 0, 0, GPIO3_IO12, 0, 0, + [PAD_NAND_DATA7*8] RAWNAND_DATA07, QSPI_B_DATA3, 0, 0, 0, GPIO3_IO13, 0, 0, + [PAD_NAND_DQS*8] RAWNAND_DQS, QSPI_A_DQS, 0, 0, 0, GPIO3_IO14, 0, 0, + [PAD_NAND_RE_B*8] RAWNAND_RE_B, QSPI_B_DQS, 0, 0, 0, GPIO3_IO15, 0, 0, + [PAD_NAND_READY_B*8] RAWNAND_READY_B, 0, 0, 0, 0, GPIO3_IO16, 0, 0, + [PAD_NAND_WE_B*8] RAWNAND_WE_B, 0, 0, 0, 0, GPIO3_IO17, 0, 0, + [PAD_NAND_WP_B*8] RAWNAND_WP_B, 0, 0, 0, 0, GPIO3_IO18, 0, 0, + [PAD_SAI5_RXFS*8] SAI5_RX_SYNC|DAISY(0), SAI1_TX_DATA0, 0, 0, 0, GPIO3_IO19, 0, 0, + [PAD_SAI5_RXC*8] SAI5_RX_BCLK|DAISY(0), SAI1_TX_DATA1, 0, 0, 0, GPIO3_IO20, 0, 0, + [PAD_SAI5_RXD0*8] SAI5_RX_DATA0, SAI1_TX_DATA2, 0, 0, 0, GPIO3_IO21, 0, 0, + [PAD_SAI5_RXD1*8] SAI5_RX_DATA1, SAI1_TX_DATA3, SAI1_TX_SYNC|DAISY(0), SAI5_TX_SYNC|DAISY(0), 0, GPIO3_IO22, 0, 0, + [PAD_SAI5_RXD2*8] SAI5_RX_DATA2, SAI1_TX_DATA4, SAI1_TX_SYNC|DAISY(1), SAI5_TX_BCLK, 0, GPIO3_IO23, 0, 0, + [PAD_SAI5_RXD3*8] SAI5_RX_DATA3, SAI1_TX_DATA5, 0, SAI5_TX_DATA0, 0, GPIO3_IO24, 0, 0, + [PAD_SAI5_MCLK*8] SAI5_MCLK|DAISY(0), SAI1_TX_BCLK, SAI4_MCLK, 0, 0, GPIO3_IO25, 0, 0, + [PAD_SAI1_RXFS*8] SAI1_RX_SYNC|DAISY(0), SAI5_RX_SYNC|DAISY(1), 0, 0, CORESIGHT_TRACE_CLK, GPIO4_IO00, 0, 0, + [PAD_SAI1_RXC*8] SAI1_RX_BCLK, SAI5_RX_BCLK|DAISY(1), 0, 0, CORESIGHT_TRACE_CTL, GPIO4_IO01, 0, 0, + [PAD_SAI1_RXD0*8] SAI1_RX_DATA0, SAI5_RX_DATA0, 0, 0, CORESIGHT_TRACE0, GPIO4_IO02, SRC_BOOT_CFG0, 0, + [PAD_SAI1_RXD1*8] SAI1_RX_DATA1, SAI5_RX_DATA1, 0, 0, CORESIGHT_TRACE1, GPIO4_IO03, SRC_BOOT_CFG1, 0, + [PAD_SAI1_RXD2*8] SAI1_RX_DATA2, SAI5_RX_DATA2, 0, 0, CORESIGHT_TRACE2, GPIO4_IO04, SRC_BOOT_CFG2, 0, + [PAD_SAI1_RXD3*8] SAI1_RX_DATA3, SAI5_RX_DATA3, 0, 0, CORESIGHT_TRACE3, GPIO4_IO05, SRC_BOOT_CFG3, 0, + [PAD_SAI1_RXD4*8] SAI1_RX_DATA4, SAI6_TX_BCLK|DAISY(0), SAI6_RX_BCLK|DAISY(0), 0, CORESIGHT_TRACE4, GPIO4_IO06, SRC_BOOT_CFG4, 0, + [PAD_SAI1_RXD5*8] SAI1_RX_DATA5, SAI6_TX_DATA0, SAI6_RX_DATA0, SAI1_RX_SYNC|DAISY(1), CORESIGHT_TRACE5, GPIO4_IO07, SRC_BOOT_CFG5, 0, + [PAD_SAI1_RXD6*8] SAI1_RX_DATA6, SAI6_TX_SYNC, SAI6_RX_SYNC|DAISY(0), 0, CORESIGHT_TRACE6, GPIO4_IO08, SRC_BOOT_CFG6, 0, + [PAD_SAI1_RXD7*8] SAI1_RX_DATA7, SAI6_MCLK|DAISY(0), SAI1_TX_SYNC|DAISY(4), SAI1_TX_DATA4, CORESIGHT_TRACE7, GPIO4_IO09, SRC_BOOT_CFG7, 0, + [PAD_SAI1_TXFS*8] SAI1_TX_SYNC|DAISY(3), SAI5_TX_SYNC|DAISY(1), 0, 0, CORESIGHT_EVENTO, GPIO4_IO10, 0, 0, + [PAD_SAI1_TXC*8] SAI1_TX_BCLK, SAI5_TX_BCLK, 0, 0, CORESIGHT_EVENTI, GPIO4_IO11, 0, 0, + [PAD_SAI1_TXD0*8] SAI1_TX_DATA0, SAI5_TX_DATA0, 0, 0, CORESIGHT_TRACE8, GPIO4_IO12, SRC_BOOT_CFG8, 0, + [PAD_SAI1_TXD1*8] SAI1_TX_DATA1, SAI5_TX_DATA1, 0, 0, CORESIGHT_TRACE9, GPIO4_IO13, SRC_BOOT_CFG9, 0, + [PAD_SAI1_TXD2*8] SAI1_TX_DATA2, SAI5_TX_DATA2, 0, 0, CORESIGHT_TRACE10, GPIO4_IO14, SRC_BOOT_CFG10, 0, + [PAD_SAI1_TXD3*8] SAI1_TX_DATA3, SAI5_TX_DATA3, 0, 0, CORESIGHT_TRACE11, GPIO4_IO15, SRC_BOOT_CFG11, 0, + [PAD_SAI1_TXD4*8] SAI1_TX_DATA4, SAI6_RC_BCLK, SAI6_TX_BCLK|DAISY(1), 0, CORESIGHT_TRACE12, GPIO4_IO16, SRC_BOOT_CFG12, 0, + [PAD_SAI1_TXD5*8] SAI1_TX_DATA5, SAI6_RX_DATA0, SAI6_TX_DATA0, 0, CORESIGHT_TRACE13, GPIO4_IO17, SRC_BOOT_CFG13, 0, + [PAD_SAI1_TXD6*8] SAI1_TX_DATA6, SAI6_RX_SYNC|DAISY(1), SAI6_TX_SYNC, 0, CORESIGHT_TRACE14, GPIO4_IO18, SRC_BOOT_CFG14, 0, + [PAD_SAI1_TXD7*8] SAI1_TX_DATA7, SAI6_MCLK|DAISY(1), 0, 0, CORESIGHT_TRACE15, GPIO4_IO19, SRC_BOOT_CFG15, 0, + [PAD_SAI1_MCLK*8] SAI1_MCLK, SAI5_MCLK|DAISY(1), SAI1_TX_BCLK, 0, 0, GPIO4_IO20, 0, 0, + [PAD_SAI2_RXFS*8] SAI2_RX_SYNC, SAI5_TX_SYNC|DAISY(2), 0, 0, 0, GPIO4_IO21, 0, 0, + [PAD_SAI2_RXC*8] SAI2_RX_BCLK, SAI5_TX_BCLK, 0, 0, 0, GPIO4_IO22, 0, 0, + [PAD_SAI2_RXD0*8] SAI2_RX_DATA0, SAI5_TX_DATA0, 0, 0, 0, GPIO4_IO23, 0, 0, + [PAD_SAI2_TXFS*8] SAI2_TX_SYNC, SAI5_TX_DATA1, 0, 0, 0, GPIO4_IO24, 0, 0, + [PAD_SAI2_TXC*8] SAI2_TX_BCLK, SAI5_TX_DATA2, 0, 0, 0, GPIO4_IO25, 0, 0, + [PAD_SAI2_TXD0*8] SAI2_TX_DATA0, SAI5_TX_DATA3, 0, 0, 0, GPIO4_IO26, 0, 0, + [PAD_SAI2_MCLK*8] SAI2_MCLK, SAI5_MCLK|DAISY(2), 0, 0, 0, GPIO4_IO27, 0, 0, + [PAD_SAI3_RXFS*8] SAI3_RX_SYNC, GPT1_CAPTURE1, SAI5_RX_SYNC|DAISY(2), 0, 0, GPIO4_IO28, 0, 0, + [PAD_SAI3_RXC*8] SAI3_RX_BCLK, GPT1_CAPTURE2, SAI5_RX_BCLK|DAISY(2), 0, 0, GPIO4_IO29, 0, 0, + [PAD_SAI3_RXD*8] SAI3_RX_DATA0, GPT1_COMPARE1, 0, 0, 0, 0, 0, 0, + [PAD_SAI3_TXFS*8] SAI3_TX_SYNC, GPT1_CLK, SAI5_RX_DATA1, 0, 0, GPIO4_IO31, 0, 0, + [PAD_SAI3_TXC*8] SAI3_TX_BCLK, GPT1_COMPARE2, SAI5_RX_DATA2, 0, 0, GPIO5_IO00, 0, 0, + [PAD_SAI3_TXD*8] SAI3_TX_DATA0, GPT1_COMPARE3, SAI5_RX_DATA3, 0, 0, GPIO5_IO01, 0, 0, + [PAD_SAI3_MCLK*8] SAI3_MCLK, PWM4_OUT, SAI5_MCLK|DAISY(3), 0, 0, GPIO5_IO02, 0, 0, + [PAD_SPDIF_TX*8] SPDIF1_OUT, PWM3_OUT, 0, 0, 0, GPIO5_IO03, 0, 0, + [PAD_SPDIF_RX*8] SPDIF1_IN, PWM2_OUT, 0, 0, 0, GPIO5_IO04, 0, 0, + [PAD_SPDIF_EXT_CLK*8] SPDIF1_EXT_CLK, PWM1_OUT, 0, 0, 0, GPIO5_IO05, 0, 0, + [PAD_ECSPI1_SCLK*8] ECSPI1_SCLK, UART3_RX, 0, 0, 0, GPIO5_IO06, 0, 0, + [PAD_ECSPI1_MOSI*8] ECSPI1_MOSI, UART3_TX, 0, 0, 0, GPIO5_IO07, 0, 0, + [PAD_ECSPI1_MISO*8] ECSPI1_MISO, UART3_CTS_B, 0, 0, 0, GPIO5_IO08, 0, 0, + [PAD_ECSPI1_SS0*8] ECSPI1_SS0, UART3_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO09, 0, 0, + [PAD_ECSPI2_SCLK*8] ECSPI2_SCLK, UART4_RX, 0, 0, 0, GPIO5_IO10, 0, 0, + [PAD_ECSPI2_MOSI*8] ECSPI2_MOSI, UART4_TX, 0, 0, 0, GPIO5_IO11, 0, 0, + [PAD_ECSPI2_MISO*8] ECSPI2_MISO, UART4_CTS_B, 0, 0, 0, GPIO5_IO12, 0, 0, + [PAD_ECSPI2_SS0*8] ECSPI2_SS0, UART4_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO13, 0, 0, + [PAD_I2C1_SCL*8] I2C1_SCL, ENET1_MDC, 0, 0, 0, GPIO5_IO14, 0, 0, + [PAD_I2C1_SDA*8] I2C1_SDA, ENET1_MDIO|DAISY(2), 0, 0, 0, GPIO5_IO15, 0, 0, + [PAD_I2C2_SCL*8] I2C2_SCL, ENET1_1588_EVENT1_IN, 0, 0, 0, GPIO5_IO16, 0, 0, + [PAD_I2C2_SDA*8] I2C2_SDA, ENET1_1588_EVENT1_OUT, 0, 0, 0, GPIO5_IO17, 0, 0, + [PAD_I2C3_SCL*8] I2C3_SCL, PWM4_OUT, GPT2_CLK, 0, 0, GPIO5_IO18, 0, 0, + [PAD_I2C3_SDA*8] I2C3_SDA, PWM3_OUT, GPT3_CLK, 0, 0, GPIO5_IO19, 0, 0, + [PAD_I2C4_SCL*8] I2C4_SCL, PWM2_OUT, PCIE_CLKREQ_B, 0, 0, GPIO5_IO20, 0, 0, + [PAD_I2C4_SDA*8] I2C4_SDA, PWM1_OUT, PCIE2_CLKREQ_B|DAISY(0), 0, 0, GPIO5_IO21, 0, 0, + [PAD_UART1_RXD*8] UART1_RX, ECSPI3_SCLK, 0, 0, 0, GPIO5_IO22, 0, 0, + [PAD_UART1_TXD*8] UART1_TX, ECSPI3_MOSI, 0, 0, 0, GPIO5_IO23, 0, 0, + [PAD_UART2_RXD*8] UART2_RX, ECSPI3_MISO, 0, 0, 0, GPIO5_IO24, 0, 0, + [PAD_UART2_TXD*8] UART2_TX, ECSPI3_SS0, 0, 0, 0, GPIO5_IO25, 0, 0, + [PAD_UART3_RXD*8] UART3_RX, UART1_CTS_B, 0, 0, 0, GPIO5_IO26, 0, 0, + [PAD_UART3_TXD*8] UART3_TX, UART1_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO27, 0, 0, + [PAD_UART4_RXD*8] UART4_RX, UART2_CTS_B, PCIE1_CLKREQ_B|DAISY(1), 0, 0, GPIO5_IO28, 0, 0, + [PAD_UART4_TXD*8] UART4_TX, UART2_RTS_B|DAISY(1), PCIE2_CLKREQ_B|DAISY(1), 0, 0, GPIO5_IO29, 0, 0, +}; + +static char *padname[] = { + [PAD_TEST_MODE] "pad_test_mode", + [PAD_BOOT_MODE0] "pad_boot_mode0", + [PAD_BOOT_MODE1] "pad_boot_mode1", + [PAD_JTAG_MOD] "pad_jtag_mod", + [PAD_JTAG_TRST_B] "pad_jtag_trst_b", + [PAD_JTAG_TDI] "pad_jtag_tdi", + [PAD_JTAG_TMS] "pad_jtag_tms", + [PAD_JTAG_TCK] "pad_jtag_tck", + [PAD_JTAG_TDO] "pad_jtag_tdo", + [PAD_RTC] "pad_rtc", + [PAD_PMIC_STBY_REQ] "pad_pmic_stby_req", + [PAD_PMIC_ON_REQ] "pad_pmic_on_req", + [PAD_ONOFF] "pad_onoff", + [PAD_POR_B] "pad_por_b", + [PAD_RTC_RESET_B] "pad_rtc_reset_b", + [PAD_GPIO1_IO00] "pad_gpio1_io00", + [PAD_GPIO1_IO01] "pad_gpio1_io01", + [PAD_GPIO1_IO02] "pad_gpio1_io02", + [PAD_GPIO1_IO03] "pad_gpio1_io03", + [PAD_GPIO1_IO04] "pad_gpio1_io04", + [PAD_GPIO1_IO05] "pad_gpio1_io05", + [PAD_GPIO1_IO06] "pad_gpio1_io06", + [PAD_GPIO1_IO07] "pad_gpio1_io07", + [PAD_GPIO1_IO08] "pad_gpio1_io08", + [PAD_GPIO1_IO09] "pad_gpio1_io09", + [PAD_GPIO1_IO10] "pad_gpio1_io10", + [PAD_GPIO1_IO11] "pad_gpio1_io11", + [PAD_GPIO1_IO12] "pad_gpio1_io12", + [PAD_GPIO1_IO13] "pad_gpio1_io13", + [PAD_GPIO1_IO14] "pad_gpio1_io14", + [PAD_GPIO1_IO15] "pad_gpio1_io15", + [PAD_ENET_MDC] "pad_enet_mdc", + [PAD_ENET_MDIO] "pad_enet_mdio", + [PAD_ENET_TD3] "pad_enet_td3", + [PAD_ENET_TD2] "pad_enet_td2", + [PAD_ENET_TD1] "pad_enet_td1", + [PAD_ENET_TD0] "pad_enet_td0", + [PAD_ENET_TX_CTL] "pad_enet_tx_ctl", + [PAD_ENET_TXC] "pad_enet_txc", + [PAD_ENET_RX_CTL] "pad_enet_rx_ctl", + [PAD_ENET_RXC] "pad_enet_rxc", + [PAD_ENET_RD0] "pad_enet_rd0", + [PAD_ENET_RD1] "pad_enet_rd1", + [PAD_ENET_RD2] "pad_enet_rd2", + [PAD_ENET_RD3] "pad_enet_rd3", + [PAD_SD1_CLK] "pad_sd1_clk", + [PAD_SD1_CMD] "pad_sd1_cmd", + [PAD_SD1_DATA0] "pad_sd1_data0", + [PAD_SD1_DATA1] "pad_sd1_data1", + [PAD_SD1_DATA2] "pad_sd1_data2", + [PAD_SD1_DATA3] "pad_sd1_data3", + [PAD_SD1_DATA4] "pad_sd1_data4", + [PAD_SD1_DATA5] "pad_sd1_data5", + [PAD_SD1_DATA6] "pad_sd1_data6", + [PAD_SD1_DATA7] "pad_sd1_data7", + [PAD_SD1_RESET_B] "pad_sd1_reset_b", + [PAD_SD1_STROBE] "pad_sd1_strobe", + [PAD_SD2_CD_B] "pad_sd2_cd_b", + [PAD_SD2_CLK] "pad_sd2_clk", + [PAD_SD2_CMD] "pad_sd2_cmd", + [PAD_SD2_DATA0] "pad_sd2_data0", + [PAD_SD2_DATA1] "pad_sd2_data1", + [PAD_SD2_DATA2] "pad_sd2_data2", + [PAD_SD2_DATA3] "pad_sd2_data3", + [PAD_SD2_RESET_B] "pad_sd2_reset_b", + [PAD_SD2_WP] "pad_sd2_wp", + [PAD_NAND_ALE] "pad_nand_ale", + [PAD_NAND_CE0_B] "pad_nand_ce0_b", + [PAD_NAND_CE1_B] "pad_nand_ce1_b", + [PAD_NAND_CE2_B] "pad_nand_ce2_b", + [PAD_NAND_CE3_B] "pad_nand_ce3_b", + [PAD_NAND_CLE] "pad_nand_cle", + [PAD_NAND_DATA0] "pad_nand_data0", + [PAD_NAND_DATA1] "pad_nand_data1", + [PAD_NAND_DATA2] "pad_nand_data2", + [PAD_NAND_DATA3] "pad_nand_data3", + [PAD_NAND_DATA4] "pad_nand_data4", + [PAD_NAND_DATA5] "pad_nand_data5", + [PAD_NAND_DATA6] "pad_nand_data6", + [PAD_NAND_DATA7] "pad_nand_data7", + [PAD_NAND_DQS] "pad_nand_dqs", + [PAD_NAND_RE_B] "pad_nand_re_b", + [PAD_NAND_READY_B] "pad_nand_ready_b", + [PAD_NAND_WE_B] "pad_nand_we_b", + [PAD_NAND_WP_B] "pad_nand_wp_b", + [PAD_SAI5_RXFS] "pad_sai5_rxfs", + [PAD_SAI5_RXC] "pad_sai5_rxc", + [PAD_SAI5_RXD0] "pad_sai5_rxd0", + [PAD_SAI5_RXD1] "pad_sai5_rxd1", + [PAD_SAI5_RXD2] "pad_sai5_rxd2", + [PAD_SAI5_RXD3] "pad_sai5_rxd3", + [PAD_SAI5_MCLK] "pad_sai5_mclk", + [PAD_SAI1_RXFS] "pad_sai1_rxfs", + [PAD_SAI1_RXC] "pad_sai1_rxc", + [PAD_SAI1_RXD0] "pad_sai1_rxd0", + [PAD_SAI1_RXD1] "pad_sai1_rxd1", + [PAD_SAI1_RXD2] "pad_sai1_rxd2", + [PAD_SAI1_RXD3] "pad_sai1_rxd3", + [PAD_SAI1_RXD4] "pad_sai1_rxd4", + [PAD_SAI1_RXD5] "pad_sai1_rxd5", + [PAD_SAI1_RXD6] "pad_sai1_rxd6", + [PAD_SAI1_RXD7] "pad_sai1_rxd7", + [PAD_SAI1_TXFS] "pad_sai1_txfs", + [PAD_SAI1_TXC] "pad_sai1_txc", + [PAD_SAI1_TXD0] "pad_sai1_txd0", + [PAD_SAI1_TXD1] "pad_sai1_txd1", + [PAD_SAI1_TXD2] "pad_sai1_txd2", + [PAD_SAI1_TXD3] "pad_sai1_txd3", + [PAD_SAI1_TXD4] "pad_sai1_txd4", + [PAD_SAI1_TXD5] "pad_sai1_txd5", + [PAD_SAI1_TXD6] "pad_sai1_txd6", + [PAD_SAI1_TXD7] "pad_sai1_txd7", + [PAD_SAI1_MCLK] "pad_sai1_mclk", + [PAD_SAI2_RXFS] "pad_sai2_rxfs", + [PAD_SAI2_RXC] "pad_sai2_rxc", + [PAD_SAI2_RXD0] "pad_sai2_rxd0", + [PAD_SAI2_TXFS] "pad_sai2_txfs", + [PAD_SAI2_TXC] "pad_sai2_txc", + [PAD_SAI2_TXD0] "pad_sai2_txd0", + [PAD_SAI2_MCLK] "pad_sai2_mclk", + [PAD_SAI3_RXFS] "pad_sai3_rxfs", + [PAD_SAI3_RXC] "pad_sai3_rxc", + [PAD_SAI3_RXD] "pad_sai3_rxd", + [PAD_SAI3_TXFS] "pad_sai3_txfs", + [PAD_SAI3_TXC] "pad_sai3_txc", + [PAD_SAI3_TXD] "pad_sai3_txd", + [PAD_SAI3_MCLK] "pad_sai3_mclk", + [PAD_SPDIF_TX] "pad_spdif_tx", + [PAD_SPDIF_RX] "pad_spdif_rx", + [PAD_SPDIF_EXT_CLK] "pad_spdif_ext_clk", + [PAD_ECSPI1_SCLK] "pad_ecspi1_sclk", + [PAD_ECSPI1_MOSI] "pad_ecspi1_mosi", + [PAD_ECSPI1_MISO] "pad_ecspi1_miso", + [PAD_ECSPI1_SS0] "pad_ecspi1_ss0", + [PAD_ECSPI2_SCLK] "pad_ecspi2_sclk", + [PAD_ECSPI2_MOSI] "pad_ecspi2_mosi", + [PAD_ECSPI2_MISO] "pad_ecspi2_miso", + [PAD_ECSPI2_SS0] "pad_ecspi2_ss0", + [PAD_I2C1_SCL] "pad_i2c1_scl", + [PAD_I2C1_SDA] "pad_i2c1_sda", + [PAD_I2C2_SCL] "pad_i2c2_scl", + [PAD_I2C2_SDA] "pad_i2c2_sda", + [PAD_I2C3_SCL] "pad_i2c3_scl", + [PAD_I2C3_SDA] "pad_i2c3_sda", + [PAD_I2C4_SCL] "pad_i2c4_scl", + [PAD_I2C4_SDA] "pad_i2c4_sda", + [PAD_UART1_RXD] "pad_uart1_rxd", + [PAD_UART1_TXD] "pad_uart1_txd", + [PAD_UART2_RXD] "pad_uart2_rxd", + [PAD_UART2_TXD] "pad_uart2_txd", + [PAD_UART3_RXD] "pad_uart3_rxd", + [PAD_UART3_TXD] "pad_uart3_txd", + [PAD_UART4_RXD] "pad_uart4_rxd", + [PAD_UART4_TXD] "pad_uart4_txd", +}; + +static char *signame[] = { + [CCM_PMIC_READY] "ccm_pmic_ready", + [ENET1_MDIO] "enet1_mdio", + [PCIE1_CLKREQ_B] "pcie1_clkreq_b", + [PCIE2_CLKREQ_B] "pcie2_clkreq_b", + [SAI1_RX_BCLK] "sai1_rx_bclk", + [SAI1_RX_SYNC] "sai1_rx_sync", + [SAI1_TX_SYNC] "sai1_tx_sync", + [SAI5_MCLK] "sai5_mclk", + [SAI5_RXD0] "sai5_rxd0", + [SAI5_RXD1] "sai5_rxd1", + [SAI5_RXD2] "sai5_rxd2", + [SAI5_RXD3] "sai5_rxd3", + [SAI5_RX_BCLK] "sai5_rx_bclk", + [SAI5_RX_SYNC] "sai5_rx_sync", + [SAI5_TX_BLCK] "sai5_tx_blck", + [SAI5_TX_SYNC] "sai5_tx_sync", + [SAI6_MCLK] "sai6_mclk", + [SAI6_RXD0] "sai6_rxd0", + [SAI6_RX_BCLK] "sai6_rx_bclk", + [SAI6_RX_SYNC] "sai6_rx_sync", + [SAI6_TX_BCLK] "sai6_tx_bclk", + [SAY6_TX_SYNC] "say6_tx_sync", + [UART1_RTS_B] "uart1_rts_b", + [UART1_RXD] "uart1_rxd", + [UART2_RTS_B] "uart2_rts_b", + [UART2_RXD] "uart2_rxd", + [UART3_RTS_B] "uart3_rts_b", + [UART3_RXD] "uart3_rxd", + [UART4_RTS_B] "uart4_rts_b", + [UART4_RXD] "uart4_rxd", + [ANAMIX_REF_CLK_25M] "anamix_ref_clk_25m", + [ANAMIX_REF_CLK_32K] "anamix_ref_clk_32k", + [CCM_CLKO1] "ccm_clko1", + [CCM_CLKO2] "ccm_clko2", + [CCM_ENET_PHY_REF_CLK_ROOT] "ccm_enet_phy_ref_clk_root", + [CCM_EXT_CLK1] "ccm_ext_clk1", + [CCM_EXT_CLK2] "ccm_ext_clk2", + [CCM_EXT_CLK3] "ccm_ext_clk3", + [CCM_EXT_CLK4] "ccm_ext_clk4", + [CORESIGHT_EVENTI] "coresight_eventi", + [CORESIGHT_EVENTO] "coresight_evento", + [CORESIGHT_TRACE0] "coresight_trace0", + [CORESIGHT_TRACE1] "coresight_trace1", + [CORESIGHT_TRACE10] "coresight_trace10", + [CORESIGHT_TRACE11] "coresight_trace11", + [CORESIGHT_TRACE12] "coresight_trace12", + [CORESIGHT_TRACE13] "coresight_trace13", + [CORESIGHT_TRACE14] "coresight_trace14", + [CORESIGHT_TRACE15] "coresight_trace15", + [CORESIGHT_TRACE2] "coresight_trace2", + [CORESIGHT_TRACE3] "coresight_trace3", + [CORESIGHT_TRACE4] "coresight_trace4", + [CORESIGHT_TRACE5] "coresight_trace5", + [CORESIGHT_TRACE6] "coresight_trace6", + [CORESIGHT_TRACE7] "coresight_trace7", + [CORESIGHT_TRACE8] "coresight_trace8", + [CORESIGHT_TRACE9] "coresight_trace9", + [CORESIGHT_TRACE_CLK] "coresight_trace_clk", + [CORESIGHT_TRACE_CTL] "coresight_trace_ctl", + [ECSPI1_MISO] "ecspi1_miso", + [ECSPI1_MOSI] "ecspi1_mosi", + [ECSPI1_SCLK] "ecspi1_sclk", + [ECSPI1_SS0] "ecspi1_ss0", + [ECSPI2_MISO] "ecspi2_miso", + [ECSPI2_MOSI] "ecspi2_mosi", + [ECSPI2_SCLK] "ecspi2_sclk", + [ECSPI2_SS0] "ecspi2_ss0", + [ECSPI3_MISO] "ecspi3_miso", + [ECSPI3_MOSI] "ecspi3_mosi", + [ECSPI3_SCLK] "ecspi3_sclk", + [ECSPI3_SS0] "ecspi3_ss0", + [ENET1_1588_EVENT0_IN] "enet1_1588_event0_in", + [ENET1_1588_EVENT0_OUT] "enet1_1588_event0_out", + [ENET1_1588_EVENT1_IN] "enet1_1588_event1_in", + [ENET1_1588_EVENT1_OUT] "enet1_1588_event1_out", + [ENET1_MDC] "enet1_mdc", + [ENET1_RGMII_RD0] "enet1_rgmii_rd0", + [ENET1_RGMII_RD1] "enet1_rgmii_rd1", + [ENET1_RGMII_RD2] "enet1_rgmii_rd2", + [ENET1_RGMII_RD3] "enet1_rgmii_rd3", + [ENET1_RGMII_RXC] "enet1_rgmii_rxc", + [ENET1_RGMII_RX_CTL] "enet1_rgmii_rx_ctl", + [ENET1_RGMII_TD0] "enet1_rgmii_td0", + [ENET1_RGMII_TD1] "enet1_rgmii_td1", + [ENET1_RGMII_TD2] "enet1_rgmii_td2", + [ENET1_RGMII_TD3] "enet1_rgmii_td3", + [ENET1_RGMII_TXC] "enet1_rgmii_txc", + [ENET1_RGMII_TX_CTL] "enet1_rgmii_tx_ctl", + [ENET1_RX_ER] "enet1_rx_er", + [ENET1_TX_CLK] "enet1_tx_clk", + [ENET1_TX_ER] "enet1_tx_er", + [GPIO1_IO00] "gpio1_io00", + [GPIO1_IO01] "gpio1_io01", + [GPIO1_IO02] "gpio1_io02", + [GPIO1_IO03] "gpio1_io03", + [GPIO1_IO04] "gpio1_io04", + [GPIO1_IO05] "gpio1_io05", + [GPIO1_IO06] "gpio1_io06", + [GPIO1_IO07] "gpio1_io07", + [GPIO1_IO08] "gpio1_io08", + [GPIO1_IO09] "gpio1_io09", + [GPIO1_IO10] "gpio1_io10", + [GPIO1_IO11] "gpio1_io11", + [GPIO1_IO12] "gpio1_io12", + [GPIO1_IO13] "gpio1_io13", + [GPIO1_IO14] "gpio1_io14", + [GPIO1_IO15] "gpio1_io15", + [GPIO1_IO16] "gpio1_io16", + [GPIO1_IO17] "gpio1_io17", + [GPIO1_IO18] "gpio1_io18", + [GPIO1_IO19] "gpio1_io19", + [GPIO1_IO20] "gpio1_io20", + [GPIO1_IO21] "gpio1_io21", + [GPIO1_IO22] "gpio1_io22", + [GPIO1_IO23] "gpio1_io23", + [GPIO1_IO24] "gpio1_io24", + [GPIO1_IO25] "gpio1_io25", + [GPIO1_IO26] "gpio1_io26", + [GPIO1_IO27] "gpio1_io27", + [GPIO1_IO28] "gpio1_io28", + [GPIO1_IO29] "gpio1_io29", + [GPIO2_IO00] "gpio2_io00", + [GPIO2_IO01] "gpio2_io01", + [GPIO2_IO02] "gpio2_io02", + [GPIO2_IO03] "gpio2_io03", + [GPIO2_IO04] "gpio2_io04", + [GPIO2_IO05] "gpio2_io05", + [GPIO2_IO06] "gpio2_io06", + [GPIO2_IO07] "gpio2_io07", + [GPIO2_IO08] "gpio2_io08", + [GPIO2_IO09] "gpio2_io09", + [GPIO2_IO10] "gpio2_io10", + [GPIO2_IO11] "gpio2_io11", + [GPIO2_IO12] "gpio2_io12", + [GPIO2_IO13] "gpio2_io13", + [GPIO2_IO14] "gpio2_io14", + [GPIO2_IO15] "gpio2_io15", + [GPIO2_IO16] "gpio2_io16", + [GPIO2_IO17] "gpio2_io17", + [GPIO2_IO18] "gpio2_io18", + [GPIO2_IO19] "gpio2_io19", + [GPIO2_IO20] "gpio2_io20", + [GPIO3_IO00] "gpio3_io00", + [GPIO3_IO01] "gpio3_io01", + [GPIO3_IO02] "gpio3_io02", + [GPIO3_IO03] "gpio3_io03", + [GPIO3_IO04] "gpio3_io04", + [GPIO3_IO05] "gpio3_io05", + [GPIO3_IO06] "gpio3_io06", + [GPIO3_IO07] "gpio3_io07", + [GPIO3_IO08] "gpio3_io08", + [GPIO3_IO09] "gpio3_io09", + [GPIO3_IO10] "gpio3_io10", + [GPIO3_IO11] "gpio3_io11", + [GPIO3_IO12] "gpio3_io12", + [GPIO3_IO13] "gpio3_io13", + [GPIO3_IO14] "gpio3_io14", + [GPIO3_IO15] "gpio3_io15", + [GPIO3_IO16] "gpio3_io16", + [GPIO3_IO17] "gpio3_io17", + [GPIO3_IO18] "gpio3_io18", + [GPIO3_IO19] "gpio3_io19", + [GPIO3_IO20] "gpio3_io20", + [GPIO3_IO21] "gpio3_io21", + [GPIO3_IO22] "gpio3_io22", + [GPIO3_IO23] "gpio3_io23", + [GPIO3_IO24] "gpio3_io24", + [GPIO3_IO25] "gpio3_io25", + [GPIO4_IO00] "gpio4_io00", + [GPIO4_IO01] "gpio4_io01", + [GPIO4_IO02] "gpio4_io02", + [GPIO4_IO03] "gpio4_io03", + [GPIO4_IO04] "gpio4_io04", + [GPIO4_IO05] "gpio4_io05", + [GPIO4_IO06] "gpio4_io06", + [GPIO4_IO07] "gpio4_io07", + [GPIO4_IO08] "gpio4_io08", + [GPIO4_IO09] "gpio4_io09", + [GPIO4_IO10] "gpio4_io10", + [GPIO4_IO11] "gpio4_io11", + [GPIO4_IO12] "gpio4_io12", + [GPIO4_IO13] "gpio4_io13", + [GPIO4_IO14] "gpio4_io14", + [GPIO4_IO15] "gpio4_io15", + [GPIO4_IO16] "gpio4_io16", + [GPIO4_IO17] "gpio4_io17", + [GPIO4_IO18] "gpio4_io18", + [GPIO4_IO19] "gpio4_io19", + [GPIO4_IO20] "gpio4_io20", + [GPIO4_IO21] "gpio4_io21", + [GPIO4_IO22] "gpio4_io22", + [GPIO4_IO23] "gpio4_io23", + [GPIO4_IO24] "gpio4_io24", + [GPIO4_IO25] "gpio4_io25", + [GPIO4_IO26] "gpio4_io26", + [GPIO4_IO27] "gpio4_io27", + [GPIO4_IO28] "gpio4_io28", + [GPIO4_IO29] "gpio4_io29", + [GPIO4_IO31] "gpio4_io31", + [GPIO5_IO00] "gpio5_io00", + [GPIO5_IO01] "gpio5_io01", + [GPIO5_IO02] "gpio5_io02", + [GPIO5_IO03] "gpio5_io03", + [GPIO5_IO04] "gpio5_io04", + [GPIO5_IO05] "gpio5_io05", + [GPIO5_IO06] "gpio5_io06", + [GPIO5_IO07] "gpio5_io07", + [GPIO5_IO08] "gpio5_io08", + [GPIO5_IO09] "gpio5_io09", + [GPIO5_IO10] "gpio5_io10", + [GPIO5_IO11] "gpio5_io11", + [GPIO5_IO12] "gpio5_io12", + [GPIO5_IO13] "gpio5_io13", + [GPIO5_IO14] "gpio5_io14", + [GPIO5_IO15] "gpio5_io15", + [GPIO5_IO16] "gpio5_io16", + [GPIO5_IO17] "gpio5_io17", + [GPIO5_IO18] "gpio5_io18", + [GPIO5_IO19] "gpio5_io19", + [GPIO5_IO20] "gpio5_io20", + [GPIO5_IO21] "gpio5_io21", + [GPIO5_IO22] "gpio5_io22", + [GPIO5_IO23] "gpio5_io23", + [GPIO5_IO24] "gpio5_io24", + [GPIO5_IO25] "gpio5_io25", + [GPIO5_IO26] "gpio5_io26", + [GPIO5_IO27] "gpio5_io27", + [GPIO5_IO28] "gpio5_io28", + [GPIO5_IO29] "gpio5_io29", + [GPT1_CAPTURE1] "gpt1_capture1", + [GPT1_CAPTURE2] "gpt1_capture2", + [GPT1_COMPARE1] "gpt1_compare1", + [GPT1_COMPARE2] "gpt1_compare2", + [GPT1_COMPARE3] "gpt1_compare3", + [GPT1_CLK] "gpt1_clk", + [GPT2_CLK] "gpt2_clk", + [GPT3_CLK] "gpt3_clk", + [I2C1_SCL] "i2c1_scl", + [I2C1_SDA] "i2c1_sda", + [I2C2_SCL] "i2c2_scl", + [I2C2_SDA] "i2c2_sda", + [I2C3_SCL] "i2c3_scl", + [I2C3_SDA] "i2c3_sda", + [I2C4_SCL] "i2c4_scl", + [I2C4_SDA] "i2c4_sda", + [M4_NMI] "m4_nmi", + [PCIE_CLKREQ_B] "pcie_clkreq_b", + [PWM1_OUT] "pwm1_out", + [PWM2_OUT] "pwm2_out", + [PWM3_OUT] "pwm3_out", + [PWM4_OUT] "pwm4_out", + [QSPI_A_DATA0] "qspi_a_data0", + [QSPI_A_DATA1] "qspi_a_data1", + [QSPI_A_DATA2] "qspi_a_data2", + [QSPI_A_DATA3] "qspi_a_data3", + [QSPI_A_DQS] "qspi_a_dqs", + [QSPI_A_SCLK] "qspi_a_sclk", + [QSPI_A_SS0_B] "qspi_a_ss0_b", + [QSPI_A_SS1_B] "qspi_a_ss1_b", + [QSPI_B_DATA0] "qspi_b_data0", + [QSPI_B_DATA1] "qspi_b_data1", + [QSPI_B_DATA2] "qspi_b_data2", + [QSPI_B_DATA3] "qspi_b_data3", + [QSPI_B_DQS] "qspi_b_dqs", + [QSPI_B_SCLK] "qspi_b_sclk", + [QSPI_B_SS0_B] "qspi_b_ss0_b", + [QSPI_B_SS1_B] "qspi_b_ss1_b", + [RAWNAND_ALE] "rawnand_ale", + [RAWNAND_CE0_B] "rawnand_ce0_b", + [RAWNAND_CE1_B] "rawnand_ce1_b", + [RAWNAND_CE2_B] "rawnand_ce2_b", + [RAWNAND_CE3_B] "rawnand_ce3_b", + [RAWNAND_CLE] "rawnand_cle", + [RAWNAND_DATA00] "rawnand_data00", + [RAWNAND_DATA01] "rawnand_data01", + [RAWNAND_DATA02] "rawnand_data02", + [RAWNAND_DATA03] "rawnand_data03", + [RANWNAD_DATA04] "ranwnad_data04", + [RAWNAND_DATA05] "rawnand_data05", + [RAWNAND_DATA06] "rawnand_data06", + [RAWNAND_DATA07] "rawnand_data07", + [RAWNAND_DQS] "rawnand_dqs", + [RAWNAND_READY_B] "rawnand_ready_b", + [RAWNAND_RE_B] "rawnand_re_b", + [RAWNAND_WE_B] "rawnand_we_b", + [RAWNAND_WP_B] "rawnand_wp_b", + [SAI1_MCLK] "sai1_mclk", + [SAI1_RX_DATA0] "sai1_rx_data0", + [SAI1_RX_DATA1] "sai1_rx_data1", + [SAI1_RX_DATA2] "sai1_rx_data2", + [SAI1_RX_DATA3] "sai1_rx_data3", + [SAI1_RX_DATA4] "sai1_rx_data4", + [SAI1_RX_DATA5] "sai1_rx_data5", + [SAI1_RX_DATA6] "sai1_rx_data6", + [SAI1_RX_DATA7] "sai1_rx_data7", + [SAI1_TX_BCLK] "sai1_tx_bclk", + [SAI1_TX_DATA0] "sai1_tx_data0", + [SAI1_TX_DATA1] "sai1_tx_data1", + [SAI1_TX_DATA2] "sai1_tx_data2", + [SAI1_TX_DATA3] "sai1_tx_data3", + [SAI1_TX_DATA4] "sai1_tx_data4", + [SAI1_TX_DATA5] "sai1_tx_data5", + [SAI1_TX_DATA6] "sai1_tx_data6", + [SAI1_TX_DATA7] "sai1_tx_data7", + [SAI2_MCLK] "sai2_mclk", + [SAI2_RX_BCLK] "sai2_rx_bclk", + [SAI2_RX_DATA0] "sai2_rx_data0", + [SAI2_RX_SYNC] "sai2_rx_sync", + [SAI2_TX_BCLK] "sai2_tx_bclk", + [SAI2_TX_DATA0] "sai2_tx_data0", + [SAI2_TX_SYNC] "sai2_tx_sync", + [SAI3_MCLK] "sai3_mclk", + [SAI3_RX_BCLK] "sai3_rx_bclk", + [SAI3_RX_DATA0] "sai3_rx_data0", + [SAI3_RX_SYNC] "sai3_rx_sync", + [SAI3_TX_BCLK] "sai3_tx_bclk", + [SAI3_TX_DATA0] "sai3_tx_data0", + [SAI3_TX_SYNC] "sai3_tx_sync", + [SAI4_MCLK] "sai4_mclk", + [SAI5_RX_DATA0] "sai5_rx_data0", + [SAI5_RX_DATA1] "sai5_rx_data1", + [SAI5_RX_DATA2] "sai5_rx_data2", + [SAI5_RX_DATA3] "sai5_rx_data3", + [SAI5_TX_BCLK] "sai5_tx_bclk", + [SAI5_TX_DATA0] "sai5_tx_data0", + [SAI5_TX_DATA1] "sai5_tx_data1", + [SAI5_TX_DATA2] "sai5_tx_data2", + [SAI5_TX_DATA3] "sai5_tx_data3", + [SAI6_RC_BCLK] "sai6_rc_bclk", + [SAI6_RX_DATA0] "sai6_rx_data0", + [SAI6_TX_DATA0] "sai6_tx_data0", + [SAI6_TX_SYNC] "sai6_tx_sync", + [SDMA1_EXT_EVENT0] "sdma1_ext_event0", + [SDMA1_EXT_EVENT1] "sdma1_ext_event1", + [SDMA2_EXT_EVENT0] "sdma2_ext_event0", + [SDMA2_EXT_EVENT1] "sdma2_ext_event1", + [SJC_DE_B] "sjc_de_b", + [SPDIF1_EXT_CLK] "spdif1_ext_clk", + [SPDIF1_IN] "spdif1_in", + [SPDIF1_OUT] "spdif1_out", + [SRC_BOOT_CFG0] "src_boot_cfg0", + [SRC_BOOT_CFG1] "src_boot_cfg1", + [SRC_BOOT_CFG2] "src_boot_cfg2", + [SRC_BOOT_CFG3] "src_boot_cfg3", + [SRC_BOOT_CFG4] "src_boot_cfg4", + [SRC_BOOT_CFG5] "src_boot_cfg5", + [SRC_BOOT_CFG6] "src_boot_cfg6", + [SRC_BOOT_CFG7] "src_boot_cfg7", + [SRC_BOOT_CFG8] "src_boot_cfg8", + [SRC_BOOT_CFG9] "src_boot_cfg9", + [SRC_BOOT_CFG10] "src_boot_cfg10", + [SRC_BOOT_CFG11] "src_boot_cfg11", + [SRC_BOOT_CFG12] "src_boot_cfg12", + [SRC_BOOT_CFG13] "src_boot_cfg13", + [SRC_BOOT_CFG14] "src_boot_cfg14", + [SRC_BOOT_CFG15] "src_boot_cfg15", + [UART1_CTS_B] "uart1_cts_b", + [UART1_RX] "uart1_rx", + [UART1_TX] "uart1_tx", + [UART2_CTS_B] "uart2_cts_b", + [UART2_RX] "uart2_rx", + [UART2_TX] "uart2_tx", + [UART3_CTS_B] "uart3_cts_b", + [UART3_RX] "uart3_rx", + [UART3_TX] "uart3_tx", + [UART4_CTS_B] "uart4_cts_b", + [UART4_RX] "uart4_rx", + [UART4_TX] "uart4_tx", + [USB1_OTG_ID] "usb1_otg_id", + [USB1_OTG_OC] "usb1_otg_oc", + [USB1_OTG_PWR] "usb1_otg_pwr", + [USB2_OTG_ID] "usb2_otg_id", + [USB2_OTG_OC] "usb2_otg_oc", + [USB2_OTG_PWR] "usb2_otg_pwr", + [USDHC1_CD_B] "usdhc1_cd_b", + [USDHC1_CLK] "usdhc1_clk", + [USDHC1_CMD] "usdhc1_cmd", + [USDHC1_DATA0] "usdhc1_data0", + [USDHC1_DATA1] "usdhc1_data1", + [USDHC1_DATA2] "usdhc1_data2", + [USDHC1_DATA3] "usdhc1_data3", + [USDHC1_DATA4] "usdhc1_data4", + [USDHC1_DATA5] "usdhc1_data5", + [USDHC1_DATA6] "usdhc1_data6", + [USDHC1_DATA7] "usdhc1_data7", + [USDHC1_RESET_B] "usdhc1_reset_b", + [USDHC1_STROBE] "usdhc1_strobe", + [USDHC1_VSELECT] "usdhc1_vselect", + [USDHC1_WP] "usdhc1_wp", + [USDHC2_CD_B] "usdhc2_cd_b", + [USDHC2_CLK] "usdhc2_clk", + [USDHC2_CMD] "usdhc2_cmd", + [USDHC2_DATA0] "usdhc2_data0", + [USDHC2_DATA1] "usdhc2_data1", + [USDHC2_DATA2] "usdhc2_data2", + [USDHC2_DATA3] "usdhc2_data3", + [USDHC2_RESET_B] "usdhc2_reset_b", + [USDHC2_VSELECT] "usdhc2_vselect", + [USDHC2_WP] "usdhc2_wp", + [WDOG1_WDOG_ANY] "wdog1_wdog_any", + [WDOG1_WDOG_B] "wdog1_wdog_b", +}; + +struct padopt { + char *s; + u32int m; + u32int v; +}; + +static struct padopt padopts[] = { + "VSEL_0", 7<<11, 0<<11, + "VSEL_1", 7<<11, 1<<11, + "VSEL_2", 7<<11, 2<<11, + "VSEL_3", 7<<11, 3<<11, + "VSEL_4", 7<<11, 4<<11, + "VSEL_5", 7<<11, 5<<11, + "VSEL_6", 7<<11, 6<<11, + "VSEL_7", 7<<11, 7<<11, + + "LVTTL_OFF", 1<<8, 0<<8, + "LVTTL", 1<<8, 1<<8, + + "HYS_OFF", 1<<7, 0<<7, + "HYS", 1<<7, 1<<7, + + "PUE", 1<<6, 1<<6, + "PUD", 1<<6, 0<<6, + + "ODE", 1<<5, 1<<5, + "ODD", 1<<5, 0<<5, + + "SLOW", 3<<3, 0<<3, + "MEDIUM", 3<<3, 1<<3, + "FAST", 3<<3, 2<<3, + "MAX", 3<<3, 3<<3, + + /* DSE */ + "HI-Z", 7, 0, + "255_OHM", 7, 1, + "105_OHM", 7, 2, + "75_OHM", 7, 3, + "85_OHM", 7, 4, + "65_OHM", 7, 5, + "45_OHM", 7, 6, + "40_OHM", 7, 7, + + nil, +}; + +void +iomuxpad(char *pads, char *sel, char *cfg) +{ + int pad, sig, mux, alt, daisy; + u32int val, mask, *reg; + + for(pad = 0; pad < nelem(padname); pad++) + if(padname[pad] != nil && cistrcmp(pads, padname[pad]) == 0) + goto Padok; + + panic("iomuxpad: %s not defined", pads); + return; +Padok: + val = 0; + mask = 0; + mux = 0; + sig = 0; + + if(cfg != nil){ + struct padopt *o; + + for(o = padopts; o->s != nil; o++) { + if(strstr(cfg, o->s) != nil){ + val |= o->v; + mask |= o->m; + } + } + if(mask != 0){ + reg = &iomuxc[IOMUXC_SW_PAD_CTL_PAD_TEST_MODE + pad]; +// iprint("iomuxpad: pad_ctl_%s %p <= %.8ux & %.8ux\n", padname[pad], PADDR(reg), val, mask); + *reg = (*reg & ~mask) | val; + } + + val = 0; + mask = 0; + if(strstr(cfg, "SION") != nil){ + val |= SION; + mask |= SION; + } + if(strstr(cfg, "SIOFF") != nil){ + val &= ~SION; + mask |= SION; + } + } + + if(sel != nil){ + if(pad < PAD_GPIO1_IO00 || pad >= nelem(padmux)/8) + panic("iomuxpad: %s is not muxed", pads); + + /* find the mux value for the signal */ + for(alt = 0; alt < 8; alt++){ + mux = padmux[pad*8 + alt]; + if(mux == 0) + continue; + + sig = mux & ~DAISY(7); + if(signame[sig] != nil && cistrcmp(sel, signame[sig]) == 0) + goto Muxok; + } + panic("iomuxpad: %s not muxable to %s", pads, sel); + return; +Muxok: + val = (val & ~MUX_MODE) | alt; + mask |= MUX_MODE; + } + + if(mask == 0) + return; + + if(pad < PAD_PMIC_STBY_REQ){ + panic("iomuxpad: %s has no mux control", pads); + return; + } + + reg = &iomuxc[IOMUXC_SW_MUX_CTL_PAD_PMIC_STBY_REQ + (pad - PAD_PMIC_STBY_REQ)]; +// iprint("iomuxpad: mux_ctl_%s %p <= %.8ux & %.8ux (%s)\n", padname[pad], PADDR(reg), val, mask, signame[sig]); + *reg = (*reg & ~mask) | val; + + if((mux & DAISY(0)) == 0) + return; + + val = DAISY_VAL(mux); + + /* configure daisy input mux */ + assert(sig < nelem(daisytab)); + daisy = daisytab[sig]; + assert(daisy != 0); + mask = DAISY_VAL(daisy); + assert((mask & (mask+1)) == 0); + daisy &= ~DAISY(7); + + reg = &iomuxc[IOMUXC_CCM_PMIC_READY_SELECT_INPUT + daisy]; +// iprint("iomuxpad: %s_input_select %p <= %.8ux & %.8ux\n", signame[sig], PADDR(reg), val, mask); + *reg = (*reg & ~mask) | val; +} diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index 15a10d544..686ee9aa8 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -16,12 +16,6 @@ extern Memimage *gscreen; /* pinmux registers */ enum { - IOMUXC_CTL_PAD_SAI5_RXC = 0x144/4, /* for gpio3 20 */ - IOMUXC_CTL_PAD_SPDIF_RX = 0x1EC/4, /* for pwm2 */ - IOMUXC_CTL_PAD_GPIO1_IO10 = 0x50/4, /* for gpio1 10 */ - SION = 1<<4, - MUX_MODE = 7, - IOMUXC_GPR_GPR13 = 0x10034/4, /* GPR13 for MIPI_MUX_SEL */ MIPI_MUX_SEL = 1<<2, MIPI_MUX_INV = 1<<3, @@ -825,13 +819,15 @@ lcdinit(void) I2Cdev *bridge; char *err; - /* gpio3 20 for sn65dsi86 bridge */ - mr(iomuxc, IOMUXC_CTL_PAD_SAI5_RXC, 5, MUX_MODE); - /* gpio1 10 pad for panel */ - mr(iomuxc, IOMUXC_CTL_PAD_GPIO1_IO10, 0, MUX_MODE); - /* pwm2 pad */ - mr(iomuxc, IOMUXC_CTL_PAD_SPDIF_RX, 1, MUX_MODE); + /* gpio3_io20: sn65dsi86 bridge */ + iomuxpad("pad_sai5_rxc", "gpio3_io20", nil); + /* gpio1_io10: for panel */ + iomuxpad("pad_gpio1_io10", "gpio1_io10", nil); + + /* pwm2_out: for panel backlight */ + iomuxpad("pad_spdif_rx", "pwm2_out", nil); + /* lcdif to dpi=0, dcss=1 */ mr(iomuxc, IOMUXC_GPR_GPR13, 0, MIPI_MUX_SEL); diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index ff00d402c..65191bfa9 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -40,6 +40,7 @@ misc gic uartimx lcd + iomux port int cpuserver = 0; bootdir diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index ea08d002e..1dd2f6537 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1875,16 +1875,8 @@ reset(Hci *hp) Found: if(i == 0){ - static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); - enum { - IOMUXC_CTL_PAD_GPIO1_IO13 = 0x5C/4, /* for gpio1 13 */ - IOMUXC_CTL_PAD_GPIO1_IO14 = 0x60/4, /* for gpio1 14 */ - - IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14 = 0x2C8/4, - }; - iomuxc[IOMUXC_CTL_PAD_GPIO1_IO13] = 1; - iomuxc[IOMUXC_CTL_PAD_GPIO1_IO14] = 0; - iomuxc[IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14] = 0x16; + iomuxpad("pad_gpio1_io13", "usb1_otg_oc", nil); + iomuxpad("pad_gpio1_io14", "gpio1_io14", "FAST 45_OHM"); hubreset(0); microdelay(500); From 5388575c149445928b2eb98794998225ecf1ccfa Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 19:18:50 +0000 Subject: [PATCH 27/58] imx8: better syntax for iomuxpad() options using ~ for negation --- sys/src/9/imx8/iomux.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/src/9/imx8/iomux.c b/sys/src/9/imx8/iomux.c index 73184e74e..b023649c5 100644 --- a/sys/src/9/imx8/iomux.c +++ b/sys/src/9/imx8/iomux.c @@ -998,24 +998,19 @@ static struct padopt padopts[] = { "VSEL_6", 7<<11, 6<<11, "VSEL_7", 7<<11, 7<<11, - "LVTTL_OFF", 1<<8, 0<<8, "LVTTL", 1<<8, 1<<8, - "HYS_OFF", 1<<7, 0<<7, "HYS", 1<<7, 1<<7, "PUE", 1<<6, 1<<6, - "PUD", 1<<6, 0<<6, "ODE", 1<<5, 1<<5, - "ODD", 1<<5, 0<<5, "SLOW", 3<<3, 0<<3, "MEDIUM", 3<<3, 1<<3, "FAST", 3<<3, 2<<3, "MAX", 3<<3, 3<<3, - /* DSE */ "HI-Z", 7, 0, "255_OHM", 7, 1, "105_OHM", 7, 2, @@ -1048,10 +1043,15 @@ Padok: if(cfg != nil){ struct padopt *o; + char *x; for(o = padopts; o->s != nil; o++) { - if(strstr(cfg, o->s) != nil){ - val |= o->v; + x = strstr(cfg, o->s); + if(x != nil){ + if(x > cfg && x[-1] == '~') + val &= ~o->v; + else + val |= o->v; mask |= o->m; } } @@ -1063,12 +1063,12 @@ Padok: val = 0; mask = 0; - if(strstr(cfg, "SION") != nil){ - val |= SION; - mask |= SION; - } - if(strstr(cfg, "SIOFF") != nil){ - val &= ~SION; + x = strstr(cfg, "SION"); + if(x != nil){ + if(x > cfg && x[-1] == '~') + val &= ~SION; + else + val |= SION; mask |= SION; } } From 8dd05d041ed65e8c74c23baccaf99ba6ad424c39 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 19:48:01 +0000 Subject: [PATCH 28/58] imx8: provide iomuxgpr() function to access iomuxc's gpr's --- sys/src/9/imx8/fns.h | 3 ++- sys/src/9/imx8/iomux.c | 14 ++++++++++++++ sys/src/9/imx8/lcd.c | 13 ++----------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index d0f276a53..d6f27ea11 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -151,5 +151,6 @@ extern void powerup(char *dom); /* lcd */ extern void lcdinit(void); -/* iomuc */ +/* iomux */ extern void iomuxpad(char *pads, char *sel, char *cfg); +extern uint iomuxgpr(int gpr, uint set, uint mask); diff --git a/sys/src/9/imx8/iomux.c b/sys/src/9/imx8/iomux.c index b023649c5..9aed7562c 100644 --- a/sys/src/9/imx8/iomux.c +++ b/sys/src/9/imx8/iomux.c @@ -15,6 +15,8 @@ enum { IOMUXC_SW_PAD_CTL_PAD_TEST_MODE = 0x254/4, IOMUXC_CCM_PMIC_READY_SELECT_INPUT = 0x4BC/4, + + IOMUXC_GPR_GPR0 = 0x10000/4, }; enum { @@ -1123,3 +1125,15 @@ Muxok: // iprint("iomuxpad: %s_input_select %p <= %.8ux & %.8ux\n", signame[sig], PADDR(reg), val, mask); *reg = (*reg & ~mask) | val; } + +uint +iomuxgpr(int gpr, uint set, uint mask) +{ + u32int *reg = &iomuxc[IOMUXC_GPR_GPR0 + gpr]; + + if(mask == 0) + return *reg; + +// iprint("iomuxgpr: gpr%d %p <= %.8ux & %.8ux\n", gpr, PADDR(reg), set, mask); + return *reg = (*reg & ~mask) | (set & mask); +} diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index 686ee9aa8..0fa2ab65c 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -14,13 +14,6 @@ extern Memimage *gscreen; -/* pinmux registers */ -enum { - IOMUXC_GPR_GPR13 = 0x10034/4, /* GPR13 for MIPI_MUX_SEL */ - MIPI_MUX_SEL = 1<<2, - MIPI_MUX_INV = 1<<3, -}; - /* gpio registers */ enum { GPIO_DR = 0x00/4, @@ -366,8 +359,6 @@ struct dsi_cfg { /* base addresses, VIRTIO is at 0x30000000 physical */ -static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); - static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); static u32int *gpio3 = (u32int*)(VIRTIO + 0x220000); @@ -828,8 +819,8 @@ lcdinit(void) /* pwm2_out: for panel backlight */ iomuxpad("pad_spdif_rx", "pwm2_out", nil); - /* lcdif to dpi=0, dcss=1 */ - mr(iomuxc, IOMUXC_GPR_GPR13, 0, MIPI_MUX_SEL); + /* GPR13[MIPI_MUX_SEL]: 0 = LCDIF, 1 = DCSS */ + iomuxgpr(13, 0, 1<<2); setclkgate("gpio1.ipg_clk_s", 1); setclkgate("gpio3.ipg_clk_s", 1); From fe033ae81611a7a98d51b38ca5a8e9bc5638b996 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 23:00:06 +0000 Subject: [PATCH 29/58] imx8: add gpio helper gpioout()/gpioin() --- sys/src/9/imx8/fns.h | 5 +++ sys/src/9/imx8/gpio.c | 78 +++++++++++++++++++++++++++++++++++++ sys/src/9/imx8/lcd.c | 63 +++++++++++++----------------- sys/src/9/imx8/reform | 1 + sys/src/9/imx8/usbxhciimx.c | 28 ++----------- 5 files changed, 113 insertions(+), 62 deletions(-) create mode 100644 sys/src/9/imx8/gpio.c diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index d6f27ea11..f518bc8ff 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -154,3 +154,8 @@ extern void lcdinit(void); /* iomux */ extern void iomuxpad(char *pads, char *sel, char *cfg); extern uint iomuxgpr(int gpr, uint set, uint mask); + +/* gpio */ +#define GPIO_PIN(n, m) (((n)-1)<<5 | (m)) +extern void gpioout(uint pin, int set); +extern int gpioin(uint pin); diff --git a/sys/src/9/imx8/gpio.c b/sys/src/9/imx8/gpio.c new file mode 100644 index 000000000..5c527fb3d --- /dev/null +++ b/sys/src/9/imx8/gpio.c @@ -0,0 +1,78 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +/* gpio registers */ +enum { + GPIO_DR = 0x00/4, + GPIO_GDIR = 0x04/4, + GPIO_PSR = 0x08/4, + GPIO_ICR1 = 0x0C/4, + GPIO_ICR2 = 0x10/4, + GPIO_IMR = 0x14/4, + GPIO_ISR = 0x18/4, + GPIO_EDGE_SEL = 0x1C/4, +}; + +typedef struct Ctlr Ctlr; +struct Ctlr +{ + u32int *reg; + char *clk; + u32int dir; + int enabled; +}; + +static Ctlr ctlrs[5] = { + {(u32int*)(VIRTIO + 0x200000), "gpio1.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x210000), "gpio2.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x220000), "gpio3.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x230000), "gpio4.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x240000), "gpio5.ipg_clk_s" }, +}; + +static Ctlr* +enable(uint pin) +{ + Ctlr *ctlr = &ctlrs[pin/32]; + + assert(ctlr < &ctlrs[nelem(ctlrs)]); + + if(!ctlr->enabled){ + setclkgate(ctlr->clk, 1); + ctlr->reg[GPIO_IMR] = 0; + ctlr->dir = ctlr->reg[GPIO_GDIR]; + ctlr->enabled = 1; + } + + return ctlr; +} + +void +gpioout(uint pin, int set) +{ + int bit = 1 << (pin % 32); + Ctlr *ctlr = enable(pin); + + if((ctlr->dir & bit) == 0) + ctlr->reg[GPIO_GDIR] = ctlr->dir |= bit; + if(set) + ctlr->reg[GPIO_DR] |= bit; + else + ctlr->reg[GPIO_DR] &= ~bit; +} + +int +gpioin(uint pin) +{ + int bit = 1 << (pin % 32); + Ctlr *ctlr = enable(pin); + + if(ctlr->dir & bit) + ctlr->reg[GPIO_GDIR] = ctlr->dir &= ~bit; + return (ctlr->reg[GPIO_DR] & bit) != 0; +} diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index 0fa2ab65c..6053be39f 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -14,18 +14,6 @@ extern Memimage *gscreen; -/* gpio registers */ -enum { - GPIO_DR = 0x00/4, - GPIO_GDIR = 0x04/4, - GPIO_PSR = 0x08/4, - GPIO_ICR1 = 0x0C/4, - GPIO_ICR2 = 0x10/4, - GPIO_IMR = 0x14/4, - GPIO_ISR = 0x18/4, - GPIO_EDGE_SEL = 0x1C/4, -}; - /* system reset controller registers */ enum { SRC_MIPIPHY_RCR = 0x28/4, @@ -359,9 +347,6 @@ struct dsi_cfg { /* base addresses, VIRTIO is at 0x30000000 physical */ -static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); -static u32int *gpio3 = (u32int*)(VIRTIO + 0x220000); - static u32int *pwm2 = (u32int*)(VIRTIO + 0x670000); static u32int *resetc= (u32int*)(VIRTIO + 0x390000); @@ -802,6 +787,22 @@ dpiinit(struct video_mode *mode) wr(dsi, DSI_HOST_CFG_DPI_VFP, mode->vso); } +static void +backlighton(void) +{ + /* pwm2_out: for panel backlight */ + iomuxpad("pad_spdif_rx", "pwm2_out", nil); + + setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); + setclkgate("pwm2.ipg_clk_high_freq", 1); + + wr(pwm2, PWMIR, 0); + wr(pwm2, PWMCR, CR_STOPEN | CR_DOZEN | CR_WAITEN | CR_DBGEN | CR_CLKSRC_HIGHFREQ | 0<<CR_PRESCALER_SHIFT); + wr(pwm2, PWMSAR, Pwmsrcclk/150000); + wr(pwm2, PWMPR, (Pwmsrcclk/100000)-2); + mr(pwm2, PWMCR, CR_EN, CR_EN); +} + void lcdinit(void) { @@ -810,37 +811,25 @@ lcdinit(void) I2Cdev *bridge; char *err; + /* GPR13[MIPI_MUX_SEL]: 0 = LCDIF, 1 = DCSS */ + iomuxgpr(13, 0, 1<<2); + /* gpio3_io20: sn65dsi86 bridge */ iomuxpad("pad_sai5_rxc", "gpio3_io20", nil); /* gpio1_io10: for panel */ iomuxpad("pad_gpio1_io10", "gpio1_io10", nil); - - /* pwm2_out: for panel backlight */ - iomuxpad("pad_spdif_rx", "pwm2_out", nil); - /* GPR13[MIPI_MUX_SEL]: 0 = LCDIF, 1 = DCSS */ - iomuxgpr(13, 0, 1<<2); + /* gpio1_io10 low: panel off */ + gpioout(GPIO_PIN(1, 10), 0); - setclkgate("gpio1.ipg_clk_s", 1); - setclkgate("gpio3.ipg_clk_s", 1); + backlighton(); - setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); - setclkgate("pwm2.ipg_clk_high_freq", 1); + /* gpio1_io10 high: panel on */ + gpioout(GPIO_PIN(1, 10), 1); - mr(gpio1, GPIO_GDIR, 1<<10, 1<<10); /* gpio1 10 output */ - mr(gpio1, GPIO_DR, 0<<10, 1<<10); /* gpio1 10 low: panel off */ - - wr(pwm2, PWMIR, 0); - wr(pwm2, PWMCR, CR_STOPEN | CR_DOZEN | CR_WAITEN | CR_DBGEN | CR_CLKSRC_HIGHFREQ | 0<<CR_PRESCALER_SHIFT); - wr(pwm2, PWMSAR, Pwmsrcclk/150000); - wr(pwm2, PWMPR, (Pwmsrcclk/100000)-2); - mr(pwm2, PWMCR, CR_EN, CR_EN); - - mr(gpio1, GPIO_DR, 1<<10, 1<<10); /* gpio1 10 high: panel on */ - - mr(gpio3, GPIO_GDIR, 1<<20, 1<<20); /* gpio3 20 output */ - mr(gpio3, GPIO_DR, 1<<20, 1<<20); /* gpio3 20 high: bridge on */ + /* gpio3_io20 high: bridge on */ + gpioout(GPIO_PIN(3, 20), 1); bridge = i2cdev(i2cbus("i2c4"), 0x2C); if(bridge == nil) diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index 65191bfa9..baedcac24 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -37,6 +37,7 @@ ip misc ccm gpc + gpio gic uartimx lcd diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index 1dd2f6537..fb422926a 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1785,29 +1785,6 @@ clkenable(int i, int on) setclkgate(clk, on); } -static void -hubreset(int on) -{ - /* gpio registers */ - enum { - GPIO_DR = 0x00/4, - GPIO_GDIR = 0x04/4, - GPIO_PSR = 0x08/4, - GPIO_ICR1 = 0x0C/4, - GPIO_ICR2 = 0x10/4, - GPIO_IMR = 0x14/4, - GPIO_ISR = 0x18/4, - GPIO_EDGE_SEL = 0x1C/4, - }; - static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); - - gpio1[GPIO_GDIR] |= 1<<14; /* output */ - if(on) - gpio1[GPIO_DR] |= 1<<14; - else - gpio1[GPIO_DR] &= ~(1<<14); -} - static void phyinit(u32int *reg) { @@ -1878,9 +1855,10 @@ Found: iomuxpad("pad_gpio1_io13", "usb1_otg_oc", nil); iomuxpad("pad_gpio1_io14", "gpio1_io14", "FAST 45_OHM"); - hubreset(0); + /* gpio1_io14: hub reset */ + gpioout(GPIO_PIN(1, 14), 0); microdelay(500); - hubreset(1); + gpioout(GPIO_PIN(1, 14), 1); for(i = 0; i < nelem(ctlrs); i++) clkenable(i, 0); setclkrate("ccm_usb_bus_clk_root", "system_pll2_div2", 500*Mhz); From 04d1e6ffe92da311d1dd6463dfa347ad7db14c2d Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 23:24:14 +0000 Subject: [PATCH 30/58] imx8/gpio: allow 0 as "no-op" gpio pin as the gpio controller number starts at 1, we can use 0 to mean "no pin", so passing 0 to gpioout() or gpioin() pin argument will have no effect. --- sys/src/9/imx8/fns.h | 2 +- sys/src/9/imx8/gpio.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index f518bc8ff..735225372 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -156,6 +156,6 @@ extern void iomuxpad(char *pads, char *sel, char *cfg); extern uint iomuxgpr(int gpr, uint set, uint mask); /* gpio */ -#define GPIO_PIN(n, m) (((n)-1)<<5 | (m)) +#define GPIO_PIN(n, m) ((n)<<5 | (m)) extern void gpioout(uint pin, int set); extern int gpioin(uint pin); diff --git a/sys/src/9/imx8/gpio.c b/sys/src/9/imx8/gpio.c index 5c527fb3d..09f35ed5c 100644 --- a/sys/src/9/imx8/gpio.c +++ b/sys/src/9/imx8/gpio.c @@ -38,17 +38,19 @@ static Ctlr ctlrs[5] = { static Ctlr* enable(uint pin) { - Ctlr *ctlr = &ctlrs[pin/32]; + Ctlr *ctlr; - assert(ctlr < &ctlrs[nelem(ctlrs)]); + pin /= 32; + if(pin < 1 || pin > nelem(ctlrs)) + return nil; + ctlr = &ctlrs[pin-1]; if(!ctlr->enabled){ setclkgate(ctlr->clk, 1); ctlr->reg[GPIO_IMR] = 0; ctlr->dir = ctlr->reg[GPIO_GDIR]; ctlr->enabled = 1; } - return ctlr; } @@ -57,7 +59,8 @@ gpioout(uint pin, int set) { int bit = 1 << (pin % 32); Ctlr *ctlr = enable(pin); - + if(ctlr == nil) + return; if((ctlr->dir & bit) == 0) ctlr->reg[GPIO_GDIR] = ctlr->dir |= bit; if(set) @@ -71,7 +74,8 @@ gpioin(uint pin) { int bit = 1 << (pin % 32); Ctlr *ctlr = enable(pin); - + if(ctlr == nil) + return -1; if(ctlr->dir & bit) ctlr->reg[GPIO_GDIR] = ctlr->dir &= ~bit; return (ctlr->reg[GPIO_DR] & bit) != 0; From 176206fb02ce775b21ca6e1503da7ff7a8692b20 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Mon, 13 Jun 2022 23:26:14 +0000 Subject: [PATCH 31/58] imx8/gpio: use u32int for bit mask --- sys/src/9/imx8/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/imx8/gpio.c b/sys/src/9/imx8/gpio.c index 09f35ed5c..0fdb3aefd 100644 --- a/sys/src/9/imx8/gpio.c +++ b/sys/src/9/imx8/gpio.c @@ -57,7 +57,7 @@ enable(uint pin) void gpioout(uint pin, int set) { - int bit = 1 << (pin % 32); + u32int bit = 1 << (pin % 32); Ctlr *ctlr = enable(pin); if(ctlr == nil) return; @@ -72,7 +72,7 @@ gpioout(uint pin, int set) int gpioin(uint pin) { - int bit = 1 << (pin % 32); + u32int bit = 1 << (pin % 32); Ctlr *ctlr = enable(pin); if(ctlr == nil) return -1; From 96cc6335db6c2cd288f19ad09f69e8304e1cfd62 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 14 Jun 2022 07:02:44 +0000 Subject: [PATCH 32/58] kernel: devskel: use RWlock --- sys/src/9/port/devskel.c | 130 ++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/sys/src/9/port/devskel.c b/sys/src/9/port/devskel.c index 95e5b6038..90aa2dae6 100644 --- a/sys/src/9/port/devskel.c +++ b/sys/src/9/port/devskel.c @@ -9,15 +9,15 @@ typedef struct Skel Skel; struct Skel { + RWlock; int ref; - QLock lk; char name[KNAMELEN]; char mode; }; struct { - QLock lk; + QLock; ulong path; } skelalloc; @@ -36,19 +36,26 @@ skelattach(char *spec) c = devattach('z', spec); - f = smalloc(sizeof *f); - if(spec != nil && spec[0] != '\0' && strchr("de", spec[0]) != nil) - f->mode = spec[0]; - else + f = mallocz(sizeof *f, 1); + if(f == nil) + exhausted("memory"); + if(waserror()){ + free(f); + nexterror(); + } + + if(spec == nil) f->mode = 'f'; + else + f->mode = spec[0]; - f->ref = 1; - - qlock(&skelalloc.lk); + eqlock(&skelalloc); path = skelalloc.path++; - qunlock(&skelalloc.lk); + qunlock(&skelalloc); - mkqid(&c->qid, NETQID(path, Qroot), 0, QTDIR); + poperror(); + mkqid(&c->qid, NETQID(path, Qroot), path, QTDIR); + f->ref = 1; c->aux = f; return c; } @@ -59,19 +66,25 @@ step(Chan *c, Dir *dp, int direction) Skel *f; Qid qid; ulong perm; - uvlong path; + int path; char *name; perm = 0555|DMDIR; path = NETTYPE(c->qid.path); f = c->aux; + rlock(f); + if(waserror()){ + runlock(f); + return -1; + } name = f->name; path += direction; - if(!f->name[0] && path != Qroot) - return -1; + if(!f->name[0] && path > Qroot) + error(Enonexist); switch(path){ + case Qroot-1: case Qroot: mkqid(&qid, Qroot, 0, QTDIR); name = "#z"; @@ -92,27 +105,39 @@ step(Chan *c, Dir *dp, int direction) } break; default: - return -1; + error(Enonexist); } - qid.path = NETQID(NETID(c->qid.path), qid.path); + qid.vers = NETID(c->qid.path); + qid.path = NETQID(qid.vers, qid.path); devdir(c, qid, name, 0, eve, perm, dp); + runlock(f); + poperror(); return 1; } static int -skelgen(Chan *c, char *name, Dirtab *, int, int s, Dir *dp) +skelgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Skel *f; - f = c->aux; - //First walk away from root - if(name && !f->name[0] && f->mode != 'e' && NETTYPE(c->qid.path) == Qroot) - utfecpy(f->name, &f->name[sizeof f->name-1], name); - - if(s != DEVDOTDOT) + switch(s){ + case DEVDOTDOT: + break; + case 0: s++; + break; + default: + return -1; + } + f = c->aux; + if(name && NETTYPE(c->qid.path) == Qroot){ + wlock(f); + if(!f->name[0] && f->mode != 'e') + utfecpy(f->name, &f->name[sizeof f->name-1], name); + wunlock(f); + } return step(c, dp, s); } @@ -123,21 +148,16 @@ skelwalk(Chan *c, Chan *nc, char **name, int nname) Walkqid *wq; Skel *f; - f = c->aux; - qlock(&f->lk); - if(waserror()){ - qunlock(&f->lk); - nexterror(); - } - wq = devwalk(c, nc, name, nname, nil, 0, skelgen); - if(wq != nil && wq->clone != nil && wq->clone != c){ - if(f->ref <= 0) - panic("devskel ref"); - f->ref++; - } - qunlock(&f->lk); - poperror(); + if(wq == nil || wq->clone == nil) + return wq; + + f = c->aux; + wlock(f); + if(f->ref <= 0) + panic("devskel ref"); + f->ref++; + wunlock(f); return wq; } @@ -161,53 +181,35 @@ skelclose(Chan *c) Skel *f; f = c->aux; - qlock(&f->lk); + wlock(f); f->ref--; if(f->ref == 0){ - qunlock(&f->lk); + wunlock(f); free(f); } else - qunlock(&f->lk); + wunlock(f); } static long skelread(Chan *c, void *va, long n, vlong) { - Skel *f; - long nout; - - if(!(c->qid.type & QTDIR)) - error(Eperm); - - f = c->aux; - qlock(&f->lk); - if(waserror()){ - qunlock(&f->lk); - nexterror(); - } - nout = devdirread(c, va, n, nil, 0, skelgen); - qunlock(&f->lk); - poperror(); - return nout; + return devdirread(c, va, n, nil, 0, skelgen); } static long -skelwrite(Chan *, void *, long, vlong) +skelwrite(Chan*, void*, long, vlong) { - error(Eperm); - return 0; + error(Ebadusefd); + return -1; } static int skelstat(Chan *c, uchar *db, int n) { - Skel *f; Dir dir; - f = c->aux; - qlock(&f->lk); - step(c, &dir, 0); - qunlock(&f->lk); + if(step(c, &dir, 0) < 0) + error(Enonexist); n = convD2M(&dir, db, n); if(n < BIT16SZ) From 28709be9a68beaff12f7227f49fae1fc49be0660 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 14 Jun 2022 07:22:58 +0000 Subject: [PATCH 33/58] kernel: devwalk: correct debug print nc is not yet tied to the device that called us --- sys/src/9/port/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/port/dev.c b/sys/src/9/port/dev.c index 185d7ffd0..6d6e157fc 100644 --- a/sys/src/9/port/dev.c +++ b/sys/src/9/port/dev.c @@ -262,7 +262,7 @@ devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen if(strcmp(n, "..") == 0){ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ print("devgen walk .. in dev%s %llux broken\n", - devtab[nc->type]->name, nc->qid.path); + devtab[c->type]->name, c->qid.path); error("broken devgen"); } nc->qid = dir.qid; From be1789d78bcf1be0cc48cd036942969824dacfa5 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 14 Jun 2022 08:16:57 +0000 Subject: [PATCH 34/58] kernel: bootrc: add bootloop= --- sys/man/8/plan9.ini | 6 ++++++ sys/src/9/boot/bootrc | 5 +++++ sys/src/9/boot/reboot.rc | 1 + 3 files changed, 12 insertions(+) diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index 8be2e4f47..8d9ad93a5 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -712,6 +712,12 @@ Suppress the prompt and use .I value as the answer instead. +.SS \fLbootloop=\fIvalue\fP +Always use +.I value +as the answer to the +.L bootargs +prompt, retrying if unsuccessful. .SS \fLrootdir=\fB/root/\fIdir\fP .SS \fLrootspec=\fIspec\fP Changes the mount arguments for the root file server diff --git a/sys/src/9/boot/bootrc b/sys/src/9/boot/bootrc index c0823e6f4..49a936381 100755 --- a/sys/src/9/boot/bootrc +++ b/sys/src/9/boot/bootrc @@ -68,6 +68,11 @@ mt=() fn main{ mp=() while(~ $#mp 0){ + if(! ~ $#bootloop 0){ + nobootprompt=$bootloop + # 'flatten' for the next boot + echo -n $bootloop > '#ec/bootloop' + } if(~ $#nobootprompt 0){ echo showlocaldevs diff --git a/sys/src/9/boot/reboot.rc b/sys/src/9/boot/reboot.rc index 536ac2009..e2521b768 100755 --- a/sys/src/9/boot/reboot.rc +++ b/sys/src/9/boot/reboot.rc @@ -32,6 +32,7 @@ fn connectreboot { # set new kernel parameters echo -n $bootargs > '#ec/bootargs' + rm -f '#ec/bootloop' # remove part of our temporary root /mnt/broot/$cputype/bin/unmount /$cputype/bin /bin From 28f3dc822457fefb28af11849c38c8996b39dd6e Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Tue, 14 Jun 2022 23:53:03 +0000 Subject: [PATCH 35/58] imx8: port usdhc driver (from bcm/sdhc) for external sdcard this is a total hack, only works up to 25MHz for now. --- sys/src/9/imx8/io.h | 3 + sys/src/9/imx8/reform | 6 +- sys/src/9/imx8/usdhc.c | 530 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 537 insertions(+), 2 deletions(-) create mode 100644 sys/src/9/imx8/usdhc.c diff --git a/sys/src/9/imx8/io.h b/sys/src/9/imx8/io.h index ddd558ad9..38a1ce0f3 100644 --- a/sys/src/9/imx8/io.h +++ b/sys/src/9/imx8/io.h @@ -7,6 +7,9 @@ enum { IRQcntps = PPI+13, IRQcntpns = PPI+14, + IRQusdhc1 = SPI+22, + IRQusdhc2 = SPI+23, + IRQuart1 = SPI+26, IRQuart2 = SPI+27, IRQuart3 = SPI+28, diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index baedcac24..747451665 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -19,6 +19,7 @@ dev uart usb i2c + sd link usbxhciimx @@ -36,12 +37,13 @@ ip ipmux misc ccm + gic gpc gpio - gic - uartimx lcd + uartimx iomux + sdmmc usdhc port int cpuserver = 0; bootdir diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c new file mode 100644 index 000000000..a6ed1f702 --- /dev/null +++ b/sys/src/9/imx8/usdhc.c @@ -0,0 +1,530 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/sd.h" + +#define USDHC1 (VIRTIO+0xB40000) +#define USDHC2 (VIRTIO+0xB50000) + +#define EMMCREGS USDHC2 + +enum { + Initfreq = 400000, /* initialisation frequency for MMC */ + SDfreq = 25*Mhz, /* standard SD frequency */ + DTO = 14, /* data timeout exponent (guesswork) */ + + GoIdle = 0, /* mmc/sdio go idle state */ + MMCSelect = 7, /* mmc/sd card select command */ + Setbuswidth = 6, /* mmc/sd set bus width command */ + Switchfunc = 6, /* mmc/sd switch function command */ + Voltageswitch = 11, /* md/sdio switch to 1.8V */ + IORWdirect = 52, /* sdio read/write direct command */ + IORWextended = 53, /* sdio read/write extended command */ + Appcmd = 55, /* mmc/sd application command prefix */ +}; + +enum { + /* Controller registers */ + SDMAaddr = 0x00>>2, + Blksizecnt = 0x04>>2, + Arg1 = 0x08>>2, + Cmdtm = 0x0c>>2, + Resp0 = 0x10>>2, + Resp1 = 0x14>>2, + Resp2 = 0x18>>2, + Resp3 = 0x1c>>2, + Data = 0x20>>2, + Status = 0x24>>2, + + Control0 = 0x28>>2, + Control1 = 0x2c>>2, + + Interrupt = 0x30>>2, + Irptmask = 0x34>>2, + Irpten = 0x38>>2, + + Control2 = 0x3c>>2, + Capability = 0x40>>2, + + Mixctrl = 0x48>>2, + + Forceirpt = 0x50>>2, + Dmadesc = 0x58>>2, + + Vendorspec = 0xC0>>2, + + /* Vendorspec */ + ClkEn = 1<<14, + PerEn = 1<<13, + HclkEn = 1<<12, + IpgEn = 1<<11, + Vsel = 1<<1, + + /* Control0 (PROT_CTRL) */ + Dmaselect = 3<<8, + DmaSDMA = 0<<8, + DmaADMA1 = 1<<8, + DmaADMA2 = 2<<8, + + BE = 0<<4, + HBE = 1<<4, + LE = 2<<4, + + DwidthMask = 3<<1, + Dwidth8 = 2<<1, + Dwidth4 = 1<<1, + Dwidth1 = 0<<1, + LED = 1<<0, + + /* Control1 (SYS_CTRL) */ + Srstdata = 1<<26, /* reset data circuit */ + Srstcmd = 1<<25, /* reset command circuit */ + Srsthc = 1<<24, /* reset complete host controller */ + Datatoshift = 16, /* data timeout unit exponent */ + Datatomask = 0xF0000, + SDCLKFSshift = 8, + DVSshift = 4, + + /* Cmdtm */ + Indexshift = 24, + Suspend = 1<<22, + Resume = 2<<22, + Abort = 3<<22, + Isdata = 1<<21, + Ixchken = 1<<20, + Crcchken = 1<<19, + Respmask = 3<<16, + Respnone = 0<<16, + Resp136 = 1<<16, + Resp48 = 2<<16, + Resp48busy = 3<<16, + + /* Mixctrl */ + Autocmd23 = 1<<7, + Multiblock = 1<<5, + Host2card = 0<<4, + Card2host = 1<<4, + DdrEn = 1<<3, + Autocmd12 = 1<<2, + Blkcnten = 1<<1, + Dmaen = 1<<0, + MixCmdMask = 0xFF ^ DdrEn, + + /* Interrupt */ + Admaerr = 1<<28, + Acmderr = 1<<24, + Denderr = 1<<22, + Dcrcerr = 1<<21, + Dtoerr = 1<<20, + Cbaderr = 1<<19, + Cenderr = 1<<18, + Ccrcerr = 1<<17, + Ctoerr = 1<<16, + Err = Admaerr|Acmderr|Denderr|Dcrcerr|Dtoerr|Cbaderr|Cenderr|Ccrcerr|Ctoerr, + + Cardintr = 1<<8, + Cardinsert = 1<<6, + Readrdy = 1<<5, + Writerdy = 1<<4, + Dmaintr = 1<<3, + Datadone = 1<<1, + Cmddone = 1<<0, + + /* Status */ + Bufread = 1<<11, + Bufwrite = 1<<10, + Readtrans = 1<<9, + Writetrans = 1<<8, + + Clkstable = 1<<3, + + Datactive = 1<<2, + Datinhibit = 1<<1, + Cmdinhibit = 1<<0, +}; + +static int cmdinfo[64] = { +[0] Ixchken, +[2] Resp136, +[3] Resp48 | Ixchken | Crcchken, +[5] Resp48, +[6] Resp48 | Ixchken | Crcchken, +[7] Resp48 | Ixchken | Crcchken, +[8] Resp48 | Ixchken | Crcchken, +[9] Resp136, +[11] Resp48 | Ixchken | Crcchken, +[12] Resp48busy | Ixchken | Crcchken, +[13] Resp48 | Ixchken | Crcchken, +[16] Resp48, +[17] Resp48 | Isdata | Card2host | Ixchken | Crcchken, +[18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken | Autocmd12, +[24] Resp48 | Isdata | Host2card | Ixchken | Crcchken, +[25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken | Autocmd12, +[41] Resp48, +[52] Resp48 | Ixchken | Crcchken, +[53] Resp48 | Ixchken | Crcchken | Isdata, +[55] Resp48 | Ixchken | Crcchken, +}; + +typedef struct Adma Adma; +typedef struct Ctlr Ctlr; + +/* + * ADMA2 descriptor + * See SD Host Controller Simplified Specification Version 2.00 + */ + +struct Adma { + u32int desc; + u32int addr; +}; + +enum { + /* desc fields */ + Valid = 1<<0, + End = 1<<1, + Int = 1<<2, + Nop = 0<<4, + Tran = 2<<4, + Link = 3<<4, + OLength = 16, + /* maximum value for Length field */ + Maxdma = 1<<12, +}; + +struct Ctlr { + Rendez r; + int fastclock; + uint extclk; + int appcmd; + Adma *dma; +}; + +static Ctlr emmc; + +static void mmcinterrupt(Ureg*, void*); + +static void +WR(int reg, u32int val) +{ + u32int *r = (u32int*)EMMCREGS; + + if(0)print("WR %2.2ux %ux\n", reg<<2, val); + coherence(); + r[reg] = val; +} + +static Adma* +dmaalloc(void *addr, int len) +{ + int n; + uintptr a; + Adma *adma, *p; + + a = (uintptr)addr; + n = (len + Maxdma-1) / Maxdma; + adma = sdmalloc(n * sizeof(Adma)); + for(p = adma; len > 0; p++){ + p->desc = Valid | Tran; + if(n == 1) + p->desc |= len<<OLength | End | Int; + else + p->desc |= Maxdma<<OLength; + p->addr = PADDR(a); + a += Maxdma; + len -= Maxdma; + n--; + } + cachedwbse(adma, (char*)p - (char*)adma); + return adma; +} + +static void +emmcclk(uint freq) +{ + u32int *r = (u32int*)EMMCREGS; + uint pre_div = 1, post_div = 1, clk = emmc.extclk; + + while(clk / (pre_div * 16) > freq && pre_div < 256) + pre_div <<= 1; + + while(clk / (pre_div * post_div) > freq && post_div < 16) + post_div++; + + WR(Vendorspec, r[Vendorspec] & ~ClkEn); + WR(Control1, (pre_div>>1)<<SDCLKFSshift | (post_div-1)<<DVSshift | DTO<<Datatoshift); + delay(10); + WR(Vendorspec, r[Vendorspec] | ClkEn | PerEn); + while((r[Status] & Clkstable) == 0) + ; +} + +static int +datadone(void*) +{ + int i; + + u32int *r = (u32int*)EMMCREGS; + i = r[Interrupt]; + return i & (Datadone|Err); +} + +static int +emmcinit(void) +{ + u32int *r = (u32int*)EMMCREGS; + + setclkgate("usdhc2.ipg_clk", 1); + setclkgate("usdhc2.ipg_clk_perclk", 1); + emmc.extclk = getclkrate("usdhc2.ipg_clk_perclk"); + if(emmc.extclk <= 0){ + print("emmc: usdhc2.ipg_clk_perclk not enabled\n"); + return -1; + } + if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n", + r[Control0], r[Control1], r[Control2]); + WR(Control1, Srsthc); + delay(10); + while(r[Control1] & Srsthc) + ; + WR(Control1, Srstdata); + delay(10); + WR(Control1, 0); + return 0; +} + +static int +emmcinquiry(char *inquiry, int inqlen) +{ + return snprint(inquiry, inqlen, "USDHC Host Controller"); +} + +static void +emmcenable(void) +{ + u32int *r = (u32int*)EMMCREGS; + + WR(Control0, 0); + delay(1); + WR(Vendorspec, r[Vendorspec] & ~Vsel); + WR(Control0, LE | Dwidth1 | DmaADMA2); + WR(Control1, 0); + delay(1); + WR(Vendorspec, r[Vendorspec] | HclkEn | IpgEn); + emmcclk(Initfreq); + WR(Irpten, 0); + WR(Irptmask, ~(Cardintr|Dmaintr)); + WR(Interrupt, ~0); + intrenable(IRQusdhc2, mmcinterrupt, nil, BUSUNKNOWN, "usdhc2"); +} + +static int +emmccmd(u32int cmd, u32int arg, u32int *resp) +{ + u32int *r = (u32int*)EMMCREGS; + u32int c; + int i; + ulong now; + + /* using Autocmd12 */ + if(cmd == 12) + return 0; + + assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0); + c = (cmd << Indexshift) | cmdinfo[cmd]; + /* + * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix + */ + if(cmd == Switchfunc && !emmc.appcmd) + c |= Isdata|Card2host; + if(c & Isdata) + c |= Dmaen; + if(cmd == IORWextended){ + if(arg & (1<<31)) + c |= Host2card; + else + c |= Card2host; + if((r[Blksizecnt]&0xFFFF0000) != 0x10000) + c |= Multiblock | Blkcnten; + } + /* + * GoIdle indicates new card insertion: reset bus width & speed + */ + if(cmd == GoIdle){ + WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); + emmcclk(Initfreq); + } + if(r[Status] & Cmdinhibit){ + print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n", + r[Interrupt], r[Status]); + WR(Control1, r[Control1] | Srstcmd); + while(r[Control1] & Srstcmd) + ; + while(r[Status] & Cmdinhibit) + ; + } + if((r[Status] & Datinhibit) && + ((c & Isdata) || (c & Respmask) == Resp48busy)){ + print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n", + r[Interrupt], r[Status]); + WR(Control1, r[Control1] | Srstdata); + while(r[Control1] & Srstdata) + ; + while(r[Status] & Datinhibit) + ; + } + while(r[Status] & Datactive) + ; + WR(Arg1, arg); + if((i = (r[Interrupt] & ~Cardintr)) != 0){ + if(i != Cardinsert) + print("emmc: before command, intr was %ux\n", i); + WR(Interrupt, i); + } + WR(Mixctrl, (r[Mixctrl] & ~MixCmdMask) | (c & MixCmdMask)); + WR(Cmdtm, c & ~0xFFFF); + + now = MACHP(0)->ticks; + while(((i=r[Interrupt])&(Cmddone|Err)) == 0) + if(MACHP(0)->ticks - now > HZ) + break; + if((i&(Cmddone|Err)) != Cmddone){ + if((i&~(Err|Cardintr)) != Ctoerr) + print("emmc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); + WR(Interrupt, i); + if(r[Status]&Cmdinhibit){ + WR(Control1, r[Control1]|Srstcmd); + while(r[Control1]&Srstcmd) + ; + } + error(Eio); + } + WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy)); + switch(c & Respmask){ + case Resp136: + resp[0] = r[Resp0]<<8; + resp[1] = r[Resp0]>>24 | r[Resp1]<<8; + resp[2] = r[Resp1]>>24 | r[Resp2]<<8; + resp[3] = r[Resp2]>>24 | r[Resp3]<<8; + break; + case Resp48: + case Resp48busy: + resp[0] = r[Resp0]; + break; + case Respnone: + resp[0] = 0; + break; + } + if((c & Respmask) == Resp48busy){ + WR(Irpten, r[Irpten]|Datadone|Err); + tsleep(&emmc.r, datadone, 0, 1000); + i = r[Interrupt]; + if((i & Datadone) == 0) + print("emmcio: no Datadone in %x after CMD%d\n", i, cmd); + if(i & Err) + print("emmcio: CMD%d error interrupt %ux\n", + cmd, r[Interrupt]); + if(i != 0) WR(Interrupt, i); + } + /* + * Once card is selected, use faster clock + */ + if(cmd == MMCSelect){ + emmcclk(SDfreq); + emmc.fastclock = 1; + } + if(cmd == Setbuswidth){ + if(emmc.appcmd){ + /* + * If card bus width changes, change host bus width + */ + switch(arg){ + case 0: + WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); + break; + case 2: + WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth4); + break; + } + } + }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ + switch(arg & 0x3){ + case 0: + WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); + break; + case 2: + WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth4); + break; + } + } + emmc.appcmd = (cmd == Appcmd); + return 0; +} + +static void +emmciosetup(int write, void *buf, int bsize, int bcount) +{ + int len; + + len = bsize * bcount; + assert(((uintptr)buf&3) == 0); + assert((len&3) == 0); + assert(bsize <= 2048); + WR(Blksizecnt, bcount<<16 | bsize); + if(emmc.dma) + sdfree(emmc.dma); + emmc.dma = dmaalloc(buf, len); + if(write) + cachedwbse(buf, len); + else + cachedwbinvse(buf, len); + WR(Dmadesc, PADDR(emmc.dma)); +} + +static void +emmcio(int write, uchar *buf, int len) +{ + u32int *r = (u32int*)EMMCREGS; + int i; + + WR(Irpten, r[Irpten] | Datadone|Err); + tsleep(&emmc.r, datadone, 0, 3000); + WR(Irpten, r[Irpten] & ~(Datadone|Err)); + i = r[Interrupt]; + if((i & (Datadone|Err)) != Datadone){ + print("sdhc: %s error intr %ux stat %ux\n", + write? "write" : "read", i, r[Status]); + WR(Interrupt, i); + error(Eio); + } + WR(Interrupt, i); + if(!write) + cachedinvse(buf, len); +} + +static void +mmcinterrupt(Ureg*, void*) +{ + u32int *r; + int i; + + r = (u32int*)EMMCREGS; + i = r[Interrupt]; + if(i&(Datadone|Err)) + wakeup(&emmc.r); + WR(Irpten, r[Irpten] & ~i); +} + +SDio sdio = { + "usdhc", + emmcinit, + emmcenable, + emmcinquiry, + emmccmd, + emmciosetup, + emmcio, +}; From c12022fd8c434860accb237b9bad9bd7cd9ed2db Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Wed, 15 Jun 2022 06:42:05 +0000 Subject: [PATCH 36/58] =?UTF-8?q?skel(3)=20=E2=86=92=20skelfs(4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original intention was to put devskel in to the kernel to detach what it provides from devsrv. That is not a good reason, just move it to userspace. auth/box has been changed to exec skelfs instead of relying on '#z'. --- sys/man/3/skel | 35 ------ sys/man/4/skelfs | 65 ++++++++++ sys/src/9/pc/pc | 1 - sys/src/9/pc64/pc64 | 1 - sys/src/9/port/devskel.c | 239 ------------------------------------- sys/src/cmd/auth/box.c | 42 +++++-- sys/src/cmd/skelfs.c | 251 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 351 insertions(+), 283 deletions(-) delete mode 100644 sys/man/3/skel create mode 100644 sys/man/4/skelfs delete mode 100644 sys/src/9/port/devskel.c create mode 100644 sys/src/cmd/skelfs.c diff --git a/sys/man/3/skel b/sys/man/3/skel deleted file mode 100644 index cc8dfbc17..000000000 --- a/sys/man/3/skel +++ /dev/null @@ -1,35 +0,0 @@ -.TH SKEL 3 -.SH NAME -skel \- skeleton builder -.SH SYNOPSIS -.B bind #z/\fIskel\fR -.I dir -.PP -.B bind #zd/\fIskel\fR -.I dir -.PP -.B bind #ze/ -.I dir -.SH DESCRIPTION -.PP -This device serves a single child directory with a single empty child -file. The name of these files is determined by the first walk away -from the root. After which, the hierarchy for that attached session -becomes stable. The -.B d -attach option causes the child file to be an empty directory. The -.B e -attach option presents a completly empty root directory. -.SH EXAMPLES -Skeleton files can be used for constructing arbitrary bind targets. -.EX -.IP -bind -b '#zd/newroot' / -bind '#zd/bin' /newroot -bind '#z/walk' /newroot/bin -bind /bin/walk /newroot/bin/walk -bind /newroot / -walk / -.EE -.SH SOURCE -.B /sys/src/9/port/devskel.c diff --git a/sys/man/4/skelfs b/sys/man/4/skelfs new file mode 100644 index 000000000..7168c92f3 --- /dev/null +++ b/sys/man/4/skelfs @@ -0,0 +1,65 @@ +.TH SKELFS 4 +.SH NAME +skelfs \- build directory skeletons +.SH SYNOPSIS +.B skelfs +[ +.B -i +] +[ +.B -t +.I mode +] +[ +.B -s +.I service +] +[ +.I mnt +] +.SH DESCRIPTION +.I Skelfs +generates directory skeletons +to assist in building namespaces. +Skeletons are generated on demand +by walking through the root directory. +A skeleon is a directory containing a single empty child. +The name of this child is defined by the first walk taken +away from the root. For example the hierarchy for a skeleton +named 'echo' would be: +.PP +.EX + / + /echo/ + /echo/echo +.EE +.PP +The +.I mode +dictates what form the innermost child file takes. The +.B file +and +.B dir +modes cause the child to be an empty file or directory +respecively. The +.B empty +mode instead serves no skeletons, causing the root +directory to always be empty. +A client may override the mode by providing +its own selection as an attach option. If a +mode is not provided, +.B file +is assumed. +.PP +The skeletons generated by +.I skelfs +are anonmyous. Clients will never see the +skeletons of other clients, nor can a client revisit +a previous skeleton. +.PP +.SH "SEE ALSO" +.B auth/box +in +.IR auth (8). +.SH SOURCE +.B /sys/src/cmd/skelfs.c diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 3581fe207..2cacee652 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -18,7 +18,6 @@ dev kprof fs dtracy - skel ether netif bridge netif log diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index e78a2d47f..bafda3d72 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -41,7 +41,6 @@ dev segment vmx dtracy - skel link # devpccard pci diff --git a/sys/src/9/port/devskel.c b/sys/src/9/port/devskel.c deleted file mode 100644 index 90aa2dae6..000000000 --- a/sys/src/9/port/devskel.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#include "netif.h" - -typedef struct Skel Skel; -struct Skel { - RWlock; - int ref; - char name[KNAMELEN]; - char mode; -}; - -struct -{ - QLock; - ulong path; -} skelalloc; - -enum{ - Qroot, - Qdir, - Qskel, -}; - -static Chan* -skelattach(char *spec) -{ - Chan *c; - Skel *f; - uvlong path; - - c = devattach('z', spec); - - f = mallocz(sizeof *f, 1); - if(f == nil) - exhausted("memory"); - if(waserror()){ - free(f); - nexterror(); - } - - if(spec == nil) - f->mode = 'f'; - else - f->mode = spec[0]; - - eqlock(&skelalloc); - path = skelalloc.path++; - qunlock(&skelalloc); - - poperror(); - mkqid(&c->qid, NETQID(path, Qroot), path, QTDIR); - f->ref = 1; - c->aux = f; - return c; -} - -static int -step(Chan *c, Dir *dp, int direction) -{ - Skel *f; - Qid qid; - ulong perm; - int path; - char *name; - - perm = 0555|DMDIR; - path = NETTYPE(c->qid.path); - f = c->aux; - rlock(f); - if(waserror()){ - runlock(f); - return -1; - } - name = f->name; - - path += direction; - if(!f->name[0] && path > Qroot) - error(Enonexist); - - switch(path){ - case Qroot-1: - case Qroot: - mkqid(&qid, Qroot, 0, QTDIR); - name = "#z"; - break; - case Qdir: - mkqid(&qid, Qdir, 0, QTDIR); - break; - case Qskel: - switch(f->mode){ - case 'd': - mkqid(&qid, Qskel, 0, QTDIR); - break; - case 'f': - default: - mkqid(&qid, Qskel, 0, QTFILE); - perm = 0666; - break; - } - break; - default: - error(Enonexist); - } - - qid.vers = NETID(c->qid.path); - qid.path = NETQID(qid.vers, qid.path); - devdir(c, qid, name, 0, eve, perm, dp); - runlock(f); - poperror(); - return 1; -} - - -static int -skelgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) -{ - Skel *f; - - switch(s){ - case DEVDOTDOT: - break; - case 0: - s++; - break; - default: - return -1; - } - f = c->aux; - if(name && NETTYPE(c->qid.path) == Qroot){ - wlock(f); - if(!f->name[0] && f->mode != 'e') - utfecpy(f->name, &f->name[sizeof f->name-1], name); - wunlock(f); - } - - return step(c, dp, s); -} - -static Walkqid* -skelwalk(Chan *c, Chan *nc, char **name, int nname) -{ - Walkqid *wq; - Skel *f; - - wq = devwalk(c, nc, name, nname, nil, 0, skelgen); - if(wq == nil || wq->clone == nil) - return wq; - - f = c->aux; - wlock(f); - if(f->ref <= 0) - panic("devskel ref"); - f->ref++; - wunlock(f); - return wq; -} - -static Chan* -skelopen(Chan *c, int omode) -{ - if(!(c->qid.type & QTDIR)) - error(Eperm); - if(omode != OREAD) - error(Ebadarg); - - c->mode = omode; - c->flag |= COPEN; - c->offset = 0; - return c; -} - -static void -skelclose(Chan *c) -{ - Skel *f; - - f = c->aux; - wlock(f); - f->ref--; - if(f->ref == 0){ - wunlock(f); - free(f); - } else - wunlock(f); -} - -static long -skelread(Chan *c, void *va, long n, vlong) -{ - return devdirread(c, va, n, nil, 0, skelgen); -} - -static long -skelwrite(Chan*, void*, long, vlong) -{ - error(Ebadusefd); - return -1; -} - -static int -skelstat(Chan *c, uchar *db, int n) -{ - Dir dir; - - if(step(c, &dir, 0) < 0) - error(Enonexist); - - n = convD2M(&dir, db, n); - if(n < BIT16SZ) - error(Eshortstat); - return n; -} - -Dev skeldevtab = { - 'z', - "skel", - - devreset, - devinit, - devshutdown, - skelattach, - skelwalk, - skelstat, - skelopen, - devcreate, - skelclose, - skelread, - devbread, - skelwrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c index 30eedce7d..4f01e43de 100644 --- a/sys/src/cmd/auth/box.c +++ b/sys/src/cmd/auth/box.c @@ -29,7 +29,7 @@ binderr(char *new, char *old, int flag) dash[1] = 'a'; break; } - print("bind %s %s %s\n", dash, new, old); + fprint(2, "bind %s %s %s\n", dash, new, old); } if(bind(new, old, flag) < 0) sysfatal("bind: %r"); @@ -72,10 +72,10 @@ sandbox(char **names, int *flags, int nname) Dir *d; int i, j, n; - snprint(rootskel, sizeof rootskel, "#zd/newroot.%d", getpid()); + snprint(rootskel, sizeof rootskel, "/mnt/d/newroot.%d", getpid()); binderr(rootskel, "/", MBEFORE); - newroot = rootskel + strlen("#zd"); + newroot = rootskel + strlen("/mnt/d"); for(j = 0; j < nname; j++){ if(names[j] == nil) @@ -97,9 +97,9 @@ sandbox(char **names, int *flags, int nname) if(d == nil) continue; if(d->mode & DMDIR) - snprint(skel, sizeof skel, "#zd/%s", parts[i]); + snprint(skel, sizeof skel, "/mnt/d/%s", parts[i]); else - snprint(skel, sizeof skel, "#zf/%s", parts[i]); + snprint(skel, sizeof skel, "/mnt/f/%s", parts[i]); free(d); binderr(skel, dir, MBEFORE); } @@ -108,6 +108,31 @@ sandbox(char **names, int *flags, int nname) binderr(newroot, "/", MREPL); } +void +skelfs(void) +{ + int p[2]; + int dfd; + + pipe(p); + switch(rfork(RFFDG|RFREND|RFPROC|RFNAMEG)){ + case -1: + sysfatal("fork"); + case 0: + close(p[1]); + dup(p[0], 0); + dup(p[0], 1); + execl("/bin/skelfs", "skelfs", debug > 1 ? "-Di" : "-i", nil); + sysfatal("exec /bin/skelfs: %r"); + } + close(p[0]); + dfd = dup(p[1], -1); + if(mount(p[1], -1, "/mnt/f", MREPL, "file") < 0) + sysfatal("/mnt/f mount setup: %r"); + if(mount(dfd, -1, "/mnt/d", MREPL, "dir") < 0) + sysfatal("/mnt/d mount setup: %r"); +} + void usage(void) { @@ -129,8 +154,10 @@ main(int argc, char **argv) nparts = 0; memset(devs, 0, sizeof devs); ARGBEGIN{ + case 'D': + debug++; case 'd': - debug = 1; + debug++; break; case 'r': parts[nparts] = EARGF(usage()); @@ -164,6 +191,7 @@ main(int argc, char **argv) argv[0] = b; rfork(RFNAMEG|RFFDG); + skelfs(); dfd = open("/dev/drivers", OWRITE|OCEXEC); if(dfd < 0) sysfatal("could not /dev/drivers: %r"); @@ -172,7 +200,7 @@ main(int argc, char **argv) sandbox(parts, mflags, nparts); if(debug) - print("chdev %s\n", devs); + fprint(2, "chdev %s\n", devs); if(devs[0] != '\0'){ if(fprint(dfd, "chdev & %s", devs) <= 0) diff --git a/sys/src/cmd/skelfs.c b/sys/src/cmd/skelfs.c new file mode 100644 index 000000000..137e19397 --- /dev/null +++ b/sys/src/cmd/skelfs.c @@ -0,0 +1,251 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> + +typedef struct Skel Skel; +struct Skel { + char name[64]; + char mode; +}; + +static uvlong sessions; +static char defmode; + +enum{ + Qroot, + Qdir, + Qskel, +}; + +#define qtype(x) (((ulong)x)&0x1f) +#define qsess(x) ((((ulong)x))>>5) +#define mkqid(i,t) ((((ulong)i)<<5)|(t)) + +static int +step(Fid *f, int way, Qid *res, Dir *dp) +{ + Skel *s; + int path; + char *name; + ulong perm; + + s = f->aux; + name = s->name; + perm = 0550|DMDIR; + path = qtype(f->qid.path) + way; + if(!name[0] && way > 0) + return -1; + + if(path < 0) + goto Root; + switch(path){ + Root: + case Qroot: + name = "/"; + /* fallthrough */ + case Qdir: + res->type = QTDIR; + break; + case Qskel: + switch(s->mode){ + case 'd': + res->type = QTDIR; + break; + case 'f': + default: + res->type = QTFILE; + perm = 0; + break; + } + break; + default: + return -1; + } + res->vers = qsess(f->qid.path); + res->path = mkqid(res->vers, path); + if(dp){ + dp->mode = perm; + dp->name = estrdup9p(name); + dp->uid = estrdup9p("sys"); + dp->gid = estrdup9p("sys"); + dp->qid = *res; + dp->length = 0; + } + return 1; +} + +static int +dirgen(int i, Dir *d, void *a) +{ + Fid *f; + Qid q; + + if(i > 0) + return -1; + f = a; + return step(f, 1, &q, d); +} + +static void +fidclunk(Fid *fid) +{ + free(fid->aux); +} + +static char* +fsclone(Fid *old, Fid *new, void*) +{ + Skel *s, *s2; + + s = old->aux; + s2 = emalloc9p(sizeof *s2); + if(s2 == nil) + return "out of memory"; + memset(s2, 0, sizeof *s2); + + s2->mode = s->mode; + utfecpy(s2->name, &s2->name[sizeof s2->name-1], s->name); + new->aux = s2; + return nil; +} + +static char* +fswalk1(Fid *old, char *name, void*) +{ + Skel *s; + + if(strcmp("..", name) == 0){ + step(old, -1, &old->qid, nil); + return nil; + } + + s = old->aux; + if(!s->name[0] && qtype(old->qid.path) == Qroot && s->mode != 'e'){ + utfecpy(s->name, &s->name[sizeof s->name-1], name); + old->qid.vers = sessions++; + old->qid.path = mkqid(old->qid.vers, qtype(old->qid.path)); + } else if(strcmp(name, s->name) != 0) + return "does not exist"; + + if(step(old, 1, &old->qid, nil) < 0) + return "does not exist"; + + return nil; +} + +static void +fswalk(Req *r) +{ + walkandclone(r, fswalk1, fsclone, nil); +} + +static void +fsattach(Req *r) +{ + Skel s; + Fid root; + char *spec; + Qid *q; + + spec = r->ifcall.aname; + if(spec && spec[0] != '\0') + s.mode = spec[0]; + else + s.mode = defmode; + + q = &r->fid->qid; + q->vers = sessions++; + q->path = mkqid(q->vers, Qroot); + q->type = QTDIR; + r->ofcall.qid = *q; + + s.name[0] = '\0'; + root.aux = &s; + respond(r, fsclone(&root, r->fid, nil)); +} + +static void +fsstat(Req *r) +{ + Qid q; + + if(step(r->fid, 0, &q, &r->d) < 0) + respond(r, "does not exist"); + respond(r, nil); +} + +static void +fsread(Req *r) +{ + dirread9p(r, dirgen, r->fid); + respond(r, nil); +} + +static void +fsopen(Req *r) +{ + r->ofcall.mode = r->ifcall.mode; + if(r->ifcall.mode != OREAD) + respond(r, "permission denied"); + else + respond(r, nil); +} + +Srv fs= +{ +.attach= fsattach, +.open= fsopen, +.read= fsread, +.stat= fsstat, +.walk= fswalk, +.destroyfid= fidclunk +}; + +void +usage(void) +{ + fprint(2, "usage: %s [ -Di ] [ -s service ] [ -t mode ] [ mntpt ]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *s, *mode; + int stdio; + + s = nil; + stdio = 0; + defmode = 'f'; + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 's': + s = EARGF(usage()); + break; + case 'i': + stdio = 1; + break; + case 't': + mode = EARGF(usage()); + defmode = mode[0]; + break; + default: + usage(); + }ARGEND + + if(argc > 1) + usage(); + + if(stdio == 0){ + postmountsrv(&fs, s, argc ? argv[0] : "/mnt/skel", MREPL); + exits(nil); + } + fs.infd = 0; + fs.outfd = 1; + srv(&fs); + exits(nil); +} From 227a46e47d5a778bd9866cb50aacf05fa340da5f Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Thu, 16 Jun 2022 02:29:36 +0000 Subject: [PATCH 37/58] ip/dhcpd: quiet up syslog the packet prints can be found through -d now. --- sys/src/cmd/ip/dhcpd/dhcpd.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/sys/src/cmd/ip/dhcpd/dhcpd.c b/sys/src/cmd/ip/dhcpd/dhcpd.c index c5b708aa9..387a3c77a 100644 --- a/sys/src/cmd/ip/dhcpd/dhcpd.c +++ b/sys/src/cmd/ip/dhcpd/dhcpd.c @@ -64,8 +64,6 @@ int mute, mutestat; int minlease = MinLease; int staticlease = StaticLease; -uvlong start; - static int v6opts; /* option magic */ @@ -196,15 +194,6 @@ void termopt(Req*); int validip(uchar*); void vectoropt(Req*, int, uchar*, int); -void -timestamp(char *tag) -{ - uvlong t; - - t = nsec()/1000; - syslog(0, blog, "%s %lludµs", tag, t - start); -} - void usage(void) { @@ -317,7 +306,6 @@ main(int argc, char **argv) n = readlast(r.fd, r.buf, sizeof(r.buf)); if(n < Udphdrsize) fatal("error reading requests: %r"); - start = nsec()/1000; op = optbuf; *op = 0; proto(&r, n); @@ -409,7 +397,6 @@ proto(Req *rp, int n) dhcp(rp); else bootp(rp); - timestamp("done"); } static void @@ -1689,6 +1676,9 @@ logdhcp(Req *rp) char *p, *e; int i; + if(!debug) + return; + p = buf; e = buf + sizeof(buf); if(rp->dhcptype > 0 && rp->dhcptype <= Inform) @@ -1718,13 +1708,15 @@ logdhcp(Req *rp) p = seprint(p, e, ")"); USED(p); - syslog(0, blog, "%s", buf); + fprint(2, "%s\n", buf); } void logdhcpout(Req *rp, char *type) { - syslog(0, blog, "%s(%I->%I)id(%s)ci(%V)gi(%V)yi(%V)si(%V) %s", + if(!debug) + return; + fprint(2, "%s(%I->%I)id(%s)ci(%V)gi(%V)yi(%V)si(%V) %s\n", type, rp->up->laddr, rp->up->raddr, rp->id, rp->bp->ciaddr, rp->bp->giaddr, rp->bp->yiaddr, rp->bp->siaddr, optbuf); } From 15140dcce2b1670af6f4d78ddb5cf52444107aee Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Fri, 17 Jun 2022 02:25:15 +0000 Subject: [PATCH 38/58] kernel: add dev dtracy provider. --- sys/src/9/pc/pc | 1 + sys/src/9/pc64/pc64 | 1 + sys/src/9/port/dtracydev.c | 384 +++++++++++++++++++++++++++++++++++++ sys/src/9/port/portmkfile | 2 +- 4 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 sys/src/9/port/dtracydev.c diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 2cacee652..6ba1323ed 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -147,6 +147,7 @@ misc dtracysys dtracytimer + dtracydev ip tcp diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index bafda3d72..e385be7a6 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -144,6 +144,7 @@ misc dtracysys dtracytimer + dtracydev ip tcp diff --git a/sys/src/9/port/dtracydev.c b/sys/src/9/port/dtracydev.c new file mode 100644 index 000000000..b9a616cd0 --- /dev/null +++ b/sys/src/9/port/dtracydev.c @@ -0,0 +1,384 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include <dtracy.h> + +enum{ + Dwalk, + Dstat, + Dopen, + Dcreate, + Dclose, + Dread, + Dbread, + Dwrite, + Dbwrite, + Dremove, + Dwstat, + + Dend +}; + +static char *optab[] = { + [Dwalk] "walk", + [Dstat] "stat", + [Dopen] "open", + [Dcreate] "create", + [Dclose] "close", + [Dread] "read", + [Dbread] "bread", + [Dwrite] "write", + [Dbwrite] "bwrite", + [Dremove] "remove", + [Dwstat] "wstat", +}; + +struct { + DTProbe *in[Dend]; + DTProbe *out[Dend]; + Dev clean; +} ledger[256]; + +static Walkqid* +wrapwalk(Chan *c, Chan *nc, char **names, int nname) +{ + DTTrigInfo info; + Walkqid *wq; + + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)nc; + info.arg[2] = (uvlong)names; + info.arg[3] = (uvlong)nname; + dtptrigger(ledger[c->type].in[Dwalk], &info); + + wq = ledger[c->type].clean.walk(c, nc, names, nname); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)wq; + dtptrigger(ledger[c->type].out[Dwalk], &info); + return wq; +} + +static int +wrapstat(Chan *c, uchar *b, int n) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + dtptrigger(ledger[c->type].in[Dstat], &info); + + n = ledger[c->type].clean.stat(c, b, n); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dstat], &info); + return n; +} + +static Chan* +wrapopen(Chan *c, int mode) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)mode; + dtptrigger(ledger[c->type].in[Dopen], &info); + + c = ledger[c->type].clean.open(c, mode); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)c; + dtptrigger(ledger[c->type].out[Dopen], &info); + return c; +} + +static Chan* +wrapcreate(Chan *c, char *name, int mode, ulong perm) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)name; + info.arg[2] = (uvlong)mode; + info.arg[3] = (uvlong)perm; + dtptrigger(ledger[c->type].in[Dcreate], &info); + + c = ledger[c->type].clean.create(c, name, mode, perm); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)c; + dtptrigger(ledger[c->type].out[Dcreate], &info); + return c; +} + +static void +wrapclose(Chan *c) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + dtptrigger(ledger[c->type].in[Dclose], &info); + + ledger[c->type].clean.close(c); + + memset(&info, 0, sizeof info); + dtptrigger(ledger[c->type].out[Dclose], &info); +} + +static long +wrapread(Chan *c, void *b, long n, vlong off) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + info.arg[3] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dread], &info); + + n = ledger[c->type].clean.read(c, b, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dread], &info); + return n; +} + +static Block* +wrapbread(Chan *c, long n, ulong off) +{ + Block *b; + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)n; + info.arg[2] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dbread], &info); + + b = ledger[c->type].clean.bread(c, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)b; + dtptrigger(ledger[c->type].out[Dbread], &info); + return b; +} + +static long +wrapwrite(Chan *c, void *b, long n, vlong off) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + info.arg[3] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dwrite], &info); + + n = ledger[c->type].clean.write(c, b, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dwrite], &info); + return n; +} + +static long +wrapbwrite(Chan *c, Block *b, ulong off) +{ + long n; + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dbwrite], &info); + + n = ledger[c->type].clean.bwrite(c, b, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dbwrite], &info); + return n; +} + +void +wrapremove(Chan *c) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + dtptrigger(ledger[c->type].in[Dremove], &info); + + ledger[c->type].clean.remove(c); + + memset(&info, 0, sizeof info); + dtptrigger(ledger[c->type].out[Dremove], &info); +} + +int +wrapwstat(Chan *c, uchar *b, int n) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + dtptrigger(ledger[c->type].in[Dwstat], &info); + + n = ledger[c->type].clean.wstat(c, b, n); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dwstat], &info); + return n; +} + +static void +devprovide(DTProvider *prov) +{ + uint i, j; + uint path; + char pname[32]; + char buf[32]; + + for(i = 0; devtab[i] != nil; i++){ + memmove(&ledger[i].clean, devtab[i], sizeof(Dev)); + for(j = 0; j < Dend; j++){ + path = (i<<16) | j; + snprint(buf, sizeof buf, "dev:%s:%s", devtab[i]->name, optab[j]); + snprint(pname, sizeof pname, "%s:entry", buf); + ledger[i].in[j] = dtpnew(pname, prov, (void *) path); + snprint(pname, sizeof pname, "%s:return", buf); + ledger[i].out[j] = dtpnew(pname, prov, (void *) path); + } + } +} + +static int +devenable(DTProbe *p) +{ + uint i, j; + uint path; + Dev *d; + + path = (uint)(uintptr)p->aux; + i = path>>16; + j = path & ((1<<16)-1); + assert(i < 256); + assert(j < Dend); + + d = devtab[i]; + switch(j){ + case Dwalk: + d->walk = wrapwalk; + break; + case Dstat: + d->stat = wrapstat; + break; + case Dopen: + d->open = wrapopen; + break; + case Dcreate: + d->create = wrapcreate; + break; + case Dclose: + d->close = wrapclose; + break; + case Dread: + d->read = wrapread; + break; + case Dbread: + d->bread = wrapbread; + break; + case Dwrite: + d->write = wrapwrite; + break; + case Dbwrite: + d->bwrite = wrapbwrite; + break; + case Dremove: + d->remove = wrapremove; + break; + case Dwstat: + d->wstat = wrapwstat; + break; + } + return 0; +} + +static void +devdisable(DTProbe *p) +{ + uint i, j; + uint path; + Dev *d, *clean; + + path = (uint)(uintptr)p->aux; + i = path>>16; + j = path & ((1<<16)-1); + assert(i < 256); + assert(j < Dend); + + d = devtab[i]; + clean = &ledger[i].clean; + switch(j){ + case Dwalk: + d->walk = clean->walk; + break; + case Dstat: + d->stat = clean->stat; + break; + case Dopen: + d->open = clean->open; + break; + case Dcreate: + d->create = clean->create; + break; + case Dclose: + d->close = clean->close; + break; + case Dread: + d->read = clean->read; + break; + case Dbread: + d->bread = clean->bread; + break; + case Dwrite: + d->write = clean->write; + break; + case Dbwrite: + d->bwrite = clean->bwrite; + break; + case Dremove: + d->remove = clean->remove; + break; + case Dwstat: + d->wstat = clean->wstat; + break; + } +} + +DTProvider dtracydevprov = { + .name = "dev", + .provide = devprovide, + .enable = devenable, + .disable = devdisable, +}; diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index 119147e8e..aae30db94 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -88,7 +88,7 @@ devpipe.$O: ../port/netif.h netif.$O: ../port/netif.h devuart.$O: ../port/netif.h devbridge.$O: ../port/netif.h ../ip/ip.h ../ip/ipv6.h -devdtracy.$O dtracysys.$O dtracytimer.$O: /sys/include/dtracy.h +devdtracy.$O dtracysys.$O dtracytimer.$O dtracydev.$O: /sys/include/dtracy.h devdraw.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/memlayer.h /sys/include/cursor.h devmouse.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h swcursor.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h From 63092af6a94b6dc6032c35d8b0e89c1ee1cc1b33 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 12:45:39 +0000 Subject: [PATCH 39/58] imx8/usdhc: cleanup, set pad configuration --- sys/src/9/imx8/usdhc.c | 233 ++++++++++++++++++++--------------------- 1 file changed, 112 insertions(+), 121 deletions(-) diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c index a6ed1f702..01ea685d6 100644 --- a/sys/src/9/imx8/usdhc.c +++ b/sys/src/9/imx8/usdhc.c @@ -7,11 +7,6 @@ #include "io.h" #include "../port/sd.h" -#define USDHC1 (VIRTIO+0xB40000) -#define USDHC2 (VIRTIO+0xB50000) - -#define EMMCREGS USDHC2 - enum { Initfreq = 400000, /* initialisation frequency for MMC */ SDfreq = 25*Mhz, /* standard SD frequency */ @@ -21,10 +16,10 @@ enum { MMCSelect = 7, /* mmc/sd card select command */ Setbuswidth = 6, /* mmc/sd set bus width command */ Switchfunc = 6, /* mmc/sd switch function command */ - Voltageswitch = 11, /* md/sdio switch to 1.8V */ - IORWdirect = 52, /* sdio read/write direct command */ - IORWextended = 53, /* sdio read/write extended command */ - Appcmd = 55, /* mmc/sd application command prefix */ + Voltageswitch = 11, /* md/sdio switch to 1.8V */ + IORWdirect = 52, /* sdio read/write direct command */ + IORWextended = 53, /* sdio read/write extended command */ + Appcmd = 55, /* mmc/sd application command prefix */ }; enum { @@ -69,11 +64,10 @@ enum { DmaSDMA = 0<<8, DmaADMA1 = 1<<8, DmaADMA2 = 2<<8, - + EMODE = 3<<4, BE = 0<<4, HBE = 1<<4, LE = 2<<4, - DwidthMask = 3<<1, Dwidth8 = 2<<1, Dwidth4 = 1<<1, @@ -157,7 +151,6 @@ static int cmdinfo[64] = { [8] Resp48 | Ixchken | Crcchken, [9] Resp136, [11] Resp48 | Ixchken | Crcchken, -[12] Resp48busy | Ixchken | Crcchken, [13] Resp48 | Ixchken | Crcchken, [16] Resp48, [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken, @@ -177,7 +170,6 @@ typedef struct Ctlr Ctlr; * ADMA2 descriptor * See SD Host Controller Simplified Specification Version 2.00 */ - struct Adma { u32int desc; u32int addr; @@ -204,18 +196,19 @@ struct Ctlr { Adma *dma; }; -static Ctlr emmc; +static Ctlr usdhc; -static void mmcinterrupt(Ureg*, void*); +static void usdhcinterrupt(Ureg*, void*); + +static u32int *regs = (u32int*)(VIRTIO+0xB50000); /* USDHC2 */ +#define RR(reg) (regs[reg]) static void WR(int reg, u32int val) { - u32int *r = (u32int*)EMMCREGS; - if(0)print("WR %2.2ux %ux\n", reg<<2, val); coherence(); - r[reg] = val; + regs[reg] = val; } static Adma* @@ -244,10 +237,9 @@ dmaalloc(void *addr, int len) } static void -emmcclk(uint freq) +usdhcclk(uint freq) { - u32int *r = (u32int*)EMMCREGS; - uint pre_div = 1, post_div = 1, clk = emmc.extclk; + uint pre_div = 1, post_div = 1, clk = usdhc.extclk; while(clk / (pre_div * 16) > freq && pre_div < 256) pre_div <<= 1; @@ -255,41 +247,48 @@ emmcclk(uint freq) while(clk / (pre_div * post_div) > freq && post_div < 16) post_div++; - WR(Vendorspec, r[Vendorspec] & ~ClkEn); + WR(Vendorspec, RR(Vendorspec) & ~ClkEn); WR(Control1, (pre_div>>1)<<SDCLKFSshift | (post_div-1)<<DVSshift | DTO<<Datatoshift); delay(10); - WR(Vendorspec, r[Vendorspec] | ClkEn | PerEn); - while((r[Status] & Clkstable) == 0) + WR(Vendorspec, RR(Vendorspec) | ClkEn | PerEn); + while((RR(Status) & Clkstable) == 0) ; } static int datadone(void*) { - int i; - - u32int *r = (u32int*)EMMCREGS; - i = r[Interrupt]; - return i & (Datadone|Err); + return RR(Interrupt) & (Datadone|Err); } static int -emmcinit(void) +usdhcinit(void) { - u32int *r = (u32int*)EMMCREGS; + iomuxpad("pad_sd2_clk", "usdhc2_clk", "~LVTTL ~HYS ~PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_sd2_cmd", "usdhc2_cmd", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_sd2_data0", "usdhc2_data0", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_sd2_data1", "usdhc2_data1", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_sd2_data2", "usdhc2_data2", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_sd2_data3", "usdhc2_data3", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); - setclkgate("usdhc2.ipg_clk", 1); + setclkgate("usdhc2.ipg_clk", 0); + setclkgate("usdhc2.ipg_clk_perclk", 0); + setclkrate("usdhc2.ipg_clk_perclk", "system_pll1_clk", 200*Mhz); setclkgate("usdhc2.ipg_clk_perclk", 1); - emmc.extclk = getclkrate("usdhc2.ipg_clk_perclk"); - if(emmc.extclk <= 0){ - print("emmc: usdhc2.ipg_clk_perclk not enabled\n"); + setclkgate("usdhc2.ipg_clk", 1); + + usdhc.extclk = getclkrate("usdhc2.ipg_clk_perclk"); + if(usdhc.extclk <= 0){ + print("usdhc: usdhc2.ipg_clk_perclk not enabled\n"); return -1; } - if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n", - r[Control0], r[Control1], r[Control2]); + + if(0)print("usdhc control %8.8ux %8.8ux %8.8ux\n", + RR(Control0), RR(Control1), RR(Control2)); + WR(Control1, Srsthc); delay(10); - while(r[Control1] & Srsthc) + while(RR(Control1) & Srsthc) ; WR(Control1, Srstdata); delay(10); @@ -298,34 +297,31 @@ emmcinit(void) } static int -emmcinquiry(char *inquiry, int inqlen) +usdhcinquiry(char *inquiry, int inqlen) { return snprint(inquiry, inqlen, "USDHC Host Controller"); } static void -emmcenable(void) +usdhcenable(void) { - u32int *r = (u32int*)EMMCREGS; - WR(Control0, 0); delay(1); - WR(Vendorspec, r[Vendorspec] & ~Vsel); + WR(Vendorspec, RR(Vendorspec) & ~Vsel); WR(Control0, LE | Dwidth1 | DmaADMA2); WR(Control1, 0); delay(1); - WR(Vendorspec, r[Vendorspec] | HclkEn | IpgEn); - emmcclk(Initfreq); + WR(Vendorspec, RR(Vendorspec) | HclkEn | IpgEn); + usdhcclk(Initfreq); WR(Irpten, 0); WR(Irptmask, ~(Cardintr|Dmaintr)); WR(Interrupt, ~0); - intrenable(IRQusdhc2, mmcinterrupt, nil, BUSUNKNOWN, "usdhc2"); + intrenable(IRQusdhc2, usdhcinterrupt, nil, BUSUNKNOWN, "usdhc2"); } static int -emmccmd(u32int cmd, u32int arg, u32int *resp) +usdhccmd(u32int cmd, u32int arg, u32int *resp) { - u32int *r = (u32int*)EMMCREGS; u32int c; int i; ulong now; @@ -339,7 +335,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) /* * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix */ - if(cmd == Switchfunc && !emmc.appcmd) + if(cmd == Switchfunc && !usdhc.appcmd) c |= Isdata|Card2host; if(c & Isdata) c |= Dmaen; @@ -348,57 +344,57 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) c |= Host2card; else c |= Card2host; - if((r[Blksizecnt]&0xFFFF0000) != 0x10000) + if((RR(Blksizecnt)&0xFFFF0000) != 0x10000) c |= Multiblock | Blkcnten; } /* * GoIdle indicates new card insertion: reset bus width & speed */ if(cmd == GoIdle){ - WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); - emmcclk(Initfreq); + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); + usdhcclk(Initfreq); } - if(r[Status] & Cmdinhibit){ - print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n", - r[Interrupt], r[Status]); - WR(Control1, r[Control1] | Srstcmd); - while(r[Control1] & Srstcmd) + if(RR(Status) & Cmdinhibit){ + print("usdhccmd: need to reset Cmdinhibit intr %ux stat %ux\n", + RR(Interrupt), RR(Status)); + WR(Control1, RR(Control1) | Srstcmd); + while(RR(Control1) & Srstcmd) ; - while(r[Status] & Cmdinhibit) + while(RR(Status) & Cmdinhibit) ; } - if((r[Status] & Datinhibit) && + if((RR(Status) & Datinhibit) && ((c & Isdata) || (c & Respmask) == Resp48busy)){ - print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n", - r[Interrupt], r[Status]); - WR(Control1, r[Control1] | Srstdata); - while(r[Control1] & Srstdata) + print("usdhccmd: need to reset Datinhibit intr %ux stat %ux\n", + RR(Interrupt), RR(Status)); + WR(Control1, RR(Control1) | Srstdata); + while(RR(Control1) & Srstdata) ; - while(r[Status] & Datinhibit) + while(RR(Status) & Datinhibit) ; } - while(r[Status] & Datactive) + while(RR(Status) & Datactive) ; WR(Arg1, arg); - if((i = (r[Interrupt] & ~Cardintr)) != 0){ + if((i = (RR(Interrupt) & ~Cardintr)) != 0){ if(i != Cardinsert) - print("emmc: before command, intr was %ux\n", i); + print("usdhc: before command, intr was %ux\n", i); WR(Interrupt, i); } - WR(Mixctrl, (r[Mixctrl] & ~MixCmdMask) | (c & MixCmdMask)); + WR(Mixctrl, (RR(Mixctrl) & ~MixCmdMask) | (c & MixCmdMask)); WR(Cmdtm, c & ~0xFFFF); now = MACHP(0)->ticks; - while(((i=r[Interrupt])&(Cmddone|Err)) == 0) + while(((i=RR(Interrupt))&(Cmddone|Err)) == 0) if(MACHP(0)->ticks - now > HZ) break; if((i&(Cmddone|Err)) != Cmddone){ if((i&~(Err|Cardintr)) != Ctoerr) - print("emmc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); + print("usdhc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, RR(Status)); WR(Interrupt, i); - if(r[Status]&Cmdinhibit){ - WR(Control1, r[Control1]|Srstcmd); - while(r[Control1]&Srstcmd) + if(RR(Status)&Cmdinhibit){ + WR(Control1, RR(Control1)|Srstcmd); + while(RR(Control1)&Srstcmd) ; } error(Eio); @@ -406,98 +402,95 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy)); switch(c & Respmask){ case Resp136: - resp[0] = r[Resp0]<<8; - resp[1] = r[Resp0]>>24 | r[Resp1]<<8; - resp[2] = r[Resp1]>>24 | r[Resp2]<<8; - resp[3] = r[Resp2]>>24 | r[Resp3]<<8; + resp[0] = RR(Resp0)<<8; + resp[1] = RR(Resp0)>>24 | RR(Resp1)<<8; + resp[2] = RR(Resp1)>>24 | RR(Resp2)<<8; + resp[3] = RR(Resp2)>>24 | RR(Resp3)<<8; break; case Resp48: case Resp48busy: - resp[0] = r[Resp0]; + resp[0] = RR(Resp0); break; case Respnone: resp[0] = 0; break; } if((c & Respmask) == Resp48busy){ - WR(Irpten, r[Irpten]|Datadone|Err); - tsleep(&emmc.r, datadone, 0, 1000); - i = r[Interrupt]; + WR(Irpten, RR(Irpten)|Datadone|Err); + tsleep(&usdhc.r, datadone, 0, 1000); + i = RR(Interrupt); if((i & Datadone) == 0) - print("emmcio: no Datadone in %x after CMD%d\n", i, cmd); + print("usdhcio: no Datadone in %x after CMD%d\n", i, cmd); if(i & Err) - print("emmcio: CMD%d error interrupt %ux\n", - cmd, r[Interrupt]); + print("usdhcio: CMD%d error interrupt %ux\n", + cmd, RR(Interrupt)); if(i != 0) WR(Interrupt, i); } /* * Once card is selected, use faster clock */ if(cmd == MMCSelect){ - emmcclk(SDfreq); - emmc.fastclock = 1; + usdhcclk(SDfreq); + usdhc.fastclock = 1; } if(cmd == Setbuswidth){ - if(emmc.appcmd){ + if(usdhc.appcmd){ /* * If card bus width changes, change host bus width */ switch(arg){ case 0: - WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); break; case 2: - WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth4); + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); break; } } }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ switch(arg & 0x3){ case 0: - WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth1); + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); break; case 2: - WR(Control0, (r[Control0] & ~DwidthMask) | Dwidth4); + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); break; } } - emmc.appcmd = (cmd == Appcmd); + usdhc.appcmd = (cmd == Appcmd); return 0; } static void -emmciosetup(int write, void *buf, int bsize, int bcount) +usdhciosetup(int write, void *buf, int bsize, int bcount) { - int len; - - len = bsize * bcount; + int len = bsize * bcount; assert(((uintptr)buf&3) == 0); assert((len&3) == 0); assert(bsize <= 2048); WR(Blksizecnt, bcount<<16 | bsize); - if(emmc.dma) - sdfree(emmc.dma); - emmc.dma = dmaalloc(buf, len); + if(usdhc.dma) + sdfree(usdhc.dma); + usdhc.dma = dmaalloc(buf, len); if(write) cachedwbse(buf, len); else cachedwbinvse(buf, len); - WR(Dmadesc, PADDR(emmc.dma)); + WR(Dmadesc, PADDR(usdhc.dma)); } static void -emmcio(int write, uchar *buf, int len) +usdhcio(int write, uchar *buf, int len) { - u32int *r = (u32int*)EMMCREGS; - int i; + u32int i; - WR(Irpten, r[Irpten] | Datadone|Err); - tsleep(&emmc.r, datadone, 0, 3000); - WR(Irpten, r[Irpten] & ~(Datadone|Err)); - i = r[Interrupt]; + WR(Irpten, RR(Irpten) | Datadone|Err); + tsleep(&usdhc.r, datadone, 0, 3000); + WR(Irpten, RR(Irpten) & ~(Datadone|Err)); + i = RR(Interrupt); if((i & (Datadone|Err)) != Datadone){ print("sdhc: %s error intr %ux stat %ux\n", - write? "write" : "read", i, r[Status]); + write? "write" : "read", i, RR(Status)); WR(Interrupt, i); error(Eio); } @@ -507,24 +500,22 @@ emmcio(int write, uchar *buf, int len) } static void -mmcinterrupt(Ureg*, void*) +usdhcinterrupt(Ureg*, void*) { - u32int *r; - int i; + u32int i; - r = (u32int*)EMMCREGS; - i = r[Interrupt]; + i = RR(Interrupt); if(i&(Datadone|Err)) - wakeup(&emmc.r); - WR(Irpten, r[Irpten] & ~i); + wakeup(&usdhc.r); + WR(Irpten, RR(Irpten) & ~i); } SDio sdio = { "usdhc", - emmcinit, - emmcenable, - emmcinquiry, - emmccmd, - emmciosetup, - emmcio, + usdhcinit, + usdhcenable, + usdhcinquiry, + usdhccmd, + usdhciosetup, + usdhcio, }; From 476e7341d52f8d893d942d14343033edc0781e12 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 12:46:18 +0000 Subject: [PATCH 40/58] etherimx: set iomux pad configiguration --- sys/src/9/imx8/etherimx.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index 893b04455..2f3d8ed28 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -688,6 +688,23 @@ pnp(Ether *edev) edev->mbps = 1000; edev->maxmtu = Maxtu; + iomuxpad("pad_enet_mdc", "enet1_mdc", "~LVTTL ~HYS ~PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_enet_mdio", "enet1_mdio", "~LVTTL ~HYS ~PUE ODE SLOW 75_OHM"); + + iomuxpad("pad_enet_td3", "enet1_rgmii_td3", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td2", "enet1_rgmii_td2", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td1", "enet1_rgmii_td1", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td0", "enet1_rgmii_td0", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_tx_ctl", "enet1_rgmii_tx_ctl", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM VSEL_0"); + iomuxpad("pad_enet_txc", "enet1_rgmii_txc", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + + iomuxpad("pad_enet_rxc", "enet1_rgmii_rxc", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rx_ctl", "enet1_rgmii_rx_ctl", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd0", "enet1_rgmii_rd0", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd1", "enet1_rgmii_rd1", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd2", "enet1_rgmii_rd2", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd3", "enet1_rgmii_rd3", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + setclkgate("enet1.ipp_ind_mac0_txclk", 0); setclkgate("sim_enet.mainclk", 0); From a23e9ac65d85d31ebc6155050070546fa3a26df6 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 12:48:26 +0000 Subject: [PATCH 41/58] imx8: add i2c bus driver --- sys/src/9/imx8/i2cimx.c | 270 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 sys/src/9/imx8/i2cimx.c diff --git a/sys/src/9/imx8/i2cimx.c b/sys/src/9/imx8/i2cimx.c new file mode 100644 index 000000000..41e297697 --- /dev/null +++ b/sys/src/9/imx8/i2cimx.c @@ -0,0 +1,270 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/i2c.h" + +enum { + Moduleclk = 25*Mhz, + + I2C_IADR = 0x00, + I2C_IFDR = 0x04, + I2C_I2CR = 0x08, + I2CR_IEN = 1<<7, + I2CR_IIEN = 1<<6, + I2CR_MSTA = 1<<5, + I2CR_MTX = 1<<4, + I2CR_TXAK = 1<<3, + I2CR_RSTA = 1<<2, + I2C_I2SR = 0x0C, + I2SR_ICF = 1<<7, + I2SR_IAAS = 1<<6, + I2SR_IBB = 1<<5, + I2SR_IAL = 1<<4, + I2SR_SRW = 1<<2, + I2SR_IIF = 1<<1, + I2SR_RXAK = 1<<0, + I2C_I2DR = 0x10, +}; + +typedef struct Ctlr Ctlr; +struct Ctlr +{ + void *regs; + int irq; + + Rendez; +}; + +static void +interrupt(Ureg*, void *arg) +{ + I2Cbus *bus = arg; + Ctlr *ctlr = bus->ctlr; + wakeup(ctlr); +} + +static int +haveirq(void *arg) +{ + uchar *regs = arg; + return regs[I2C_I2SR] & (I2SR_IAL|I2SR_IIF); +} + +static int +waitsr(Ctlr *ctlr, int inv, int mask) +{ + uchar *regs = ctlr->regs; + int sr; + + for(;;){ + sr = regs[I2C_I2SR]; + if(sr & I2SR_IAL){ + regs[I2C_I2SR] = sr & ~(I2SR_IAL|I2SR_IIF); + break; + } + if(sr & I2SR_IIF) + regs[I2C_I2SR] = sr & ~I2SR_IIF; + if((sr ^ inv) & mask) + break; + + /* polling mode */ + if(up == nil || !islo()) + continue; + + tsleep(ctlr, haveirq, regs, 1); + } + return sr ^ inv; +} + +static uchar dummy; + +static int +io(I2Cbus *bus, uchar *pkt, int olen, int ilen) +{ + Ctlr *ctlr = bus->ctlr; + uchar *regs = ctlr->regs; + int cr, sr, alen, o, i; + + cr = regs[I2C_I2CR]; + if((cr & I2CR_IEN) == 0) + return -1; + + o = 0; + if(olen <= 0) + goto Stop; + + alen = 1; + if((pkt[0] & 0xF8) == 0xF0 && olen > alen) + alen++; + + regs[I2C_IADR] = (pkt[0]&0xFE)^0xFE; /* make sure doesnt match */ + + /* wait for bus idle */ + waitsr(ctlr, I2SR_IBB, I2SR_IBB); + + /* start */ + cr |= I2CR_MSTA | I2CR_MTX | I2CR_TXAK | I2CR_IIEN; + regs[I2C_I2CR] = cr; + + /* wait for bus busy */ + if(waitsr(ctlr, 0, I2SR_IBB) & I2SR_IAL) + goto Err; + + if(olen > alen) + pkt[0] &= ~1; + + for(o=0; o<olen; o++){ + regs[I2C_I2DR] = pkt[o]; + sr = waitsr(ctlr, 0, I2SR_IIF); + if(sr & I2SR_IAL) + goto Err; + if(sr & I2SR_RXAK) + goto Stop; + } + + if(ilen <= 0) + goto Stop; + + if((pkt[0]&1) == 0){ + regs[I2C_I2CR] = cr | I2CR_RSTA; + + pkt[0] |= 1; + for(i=0; i<alen; i++){ + regs[I2C_I2DR] = pkt[i]; + sr = waitsr(ctlr, 0, I2SR_IIF); + if(sr & I2SR_IAL) + goto Err; + if(sr & I2SR_RXAK) + goto Stop; + } + } + + cr &= ~(I2CR_MTX | I2CR_TXAK); + if(ilen == 1) cr |= I2CR_TXAK; + regs[I2C_I2CR] = cr; + dummy = regs[I2C_I2DR]; /* start the next read */ + + for(i=1; i<=ilen; i++){ + sr = waitsr(ctlr, I2SR_ICF, I2SR_IIF); + if(sr & I2SR_IAL) + goto Err; + if(sr & I2SR_ICF) + goto Stop; + if(i == ilen){ + cr &= ~(I2CR_MSTA|I2CR_IIEN); + regs[I2C_I2CR] = cr; + } + else if(i == ilen-1){ + cr |= I2CR_TXAK; + regs[I2C_I2CR] = cr; + } + pkt[o++] = regs[I2C_I2DR]; + } + + return o; +Err: + o = -1; +Stop: + cr &= ~(I2CR_MTX|I2CR_MSTA|I2CR_RSTA|I2CR_IIEN); + regs[I2C_I2CR] = cr; + return o; +} + +static int +divindex(int v) +{ + static int tab[] = { + /* 0x00 */ 30, 32, 36, 42, 48, 52, 60, 72, + /* 0x08 */ 80, 88, 104, 128, 144, 160, 192, 240, + /* 0x10 */ 288, 320, 384, 480, 576, 640, 768, 960, + /* 0x18 */1152,1280,1536,1920,2304,2560,3072,3840, + /* 0x20 */ 22, 24, 26, 28, 32, 36, 40, 44, + /* 0x28 */ 48, 56, 64, 72, 80, 96, 112, 128, + /* 0x30 */ 160, 192, 224, 256, 320, 384, 448, 512, + /* 0x38 */ 640, 768, 896,1024,1280,1536,1792,2048, + }; + int i, x = -1; + for(i = 0; i < nelem(tab); i++){ + if(tab[i] < v) + continue; + if(x < 0 || tab[i] < tab[x]){ + x = i; + if(tab[i] == v) + break; + } + } + return x; +} + +static void +clkenable(char *name, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "%s.ipg_clk_patref", name); + setclkgate(clk, 0); + if(on) { + setclkrate(clk, "osc_25m_ref_clk", Moduleclk); + setclkgate(clk, 1); + } +} + +static int +init(I2Cbus *bus) +{ + Ctlr *ctlr = bus->ctlr; + uchar *regs = ctlr->regs; + + clkenable(bus->name, 1); + + regs[I2C_IFDR] = divindex(Moduleclk / bus->speed); + regs[I2C_IADR] = 0; + + regs[I2C_I2CR] = I2CR_IEN; + delay(1); + + intrenable(ctlr->irq, interrupt, bus, BUSUNKNOWN, bus->name); + + return 0; +} + +static Ctlr ctlr1 = { + .regs = (void*)(VIRTIO + 0xA20000), + .irq = IRQi2c1, +}; +static Ctlr ctlr2 = { + .regs = (void*)(VIRTIO + 0xA30000), + .irq = IRQi2c2, +}; +static Ctlr ctlr3 = { + .regs = (void*)(VIRTIO + 0xA40000), + .irq = IRQi2c3, +}; +static Ctlr ctlr4 = { + .regs = (void*)(VIRTIO + 0xA50000), + .irq = IRQi2c4, +}; + +void +i2cimxlink(void) +{ + static I2Cbus i2c1 = { "i2c1", 400000, &ctlr1, init, io }; + static I2Cbus i2c3 = { "i2c3", 400000, &ctlr3, init, io }; + static I2Cbus i2c4 = { "i2c4", 400000, &ctlr4, init, io }; + + iomuxpad("pad_i2c1_sda", "i2c1_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c1_scl", "i2c1_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + addi2cbus(&i2c1); + + iomuxpad("pad_i2c3_sda", "i2c3_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c3_scl", "i2c3_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM VSEL_0"); + addi2cbus(&i2c3); + + iomuxpad("pad_i2c4_sda", "i2c4_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c4_scl", "i2c4_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + addi2cbus(&i2c4); +} From c14962657cff151be8bf805f92c13f0323b4b3b7 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 12:49:04 +0000 Subject: [PATCH 42/58] usbxhciimx: set iomux pad configuration --- sys/src/9/imx8/usbxhciimx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index fb422926a..eed92b1a6 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1852,8 +1852,8 @@ reset(Hci *hp) Found: if(i == 0){ - iomuxpad("pad_gpio1_io13", "usb1_otg_oc", nil); - iomuxpad("pad_gpio1_io14", "gpio1_io14", "FAST 45_OHM"); + iomuxpad("pad_gpio1_io13", "usb1_otg_oc", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + iomuxpad("pad_gpio1_io14", "gpio1_io14", "~LVTTL HYS PUE ~ODE FAST 45_OHM"); /* gpio1_io14: hub reset */ gpioout(GPIO_PIN(1, 14), 0); From 524f8c2d5374e34bbb665e7a52484859ae9e3e59 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 12:49:29 +0000 Subject: [PATCH 43/58] imx8/lcd: set iomux pad configuration --- sys/src/9/imx8/lcd.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c index 6053be39f..78549f036 100644 --- a/sys/src/9/imx8/lcd.c +++ b/sys/src/9/imx8/lcd.c @@ -790,8 +790,14 @@ dpiinit(struct video_mode *mode) static void backlighton(void) { + /* gpio1_io10: for panel backlight enable */ + iomuxpad("pad_gpio1_io10", "gpio1_io10", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + + /* gpio1_io10 low: panel backlight off */ + gpioout(GPIO_PIN(1, 10), 0); + /* pwm2_out: for panel backlight */ - iomuxpad("pad_spdif_rx", "pwm2_out", nil); + iomuxpad("pad_spdif_rx", "pwm2_out", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); setclkgate("pwm2.ipg_clk_high_freq", 1); @@ -801,6 +807,9 @@ backlighton(void) wr(pwm2, PWMSAR, Pwmsrcclk/150000); wr(pwm2, PWMPR, (Pwmsrcclk/100000)-2); mr(pwm2, PWMCR, CR_EN, CR_EN); + + /* gpio1_io10 high: panel backlight on */ + gpioout(GPIO_PIN(1, 10), 1); } void @@ -814,19 +823,10 @@ lcdinit(void) /* GPR13[MIPI_MUX_SEL]: 0 = LCDIF, 1 = DCSS */ iomuxgpr(13, 0, 1<<2); - /* gpio3_io20: sn65dsi86 bridge */ - iomuxpad("pad_sai5_rxc", "gpio3_io20", nil); - - /* gpio1_io10: for panel */ - iomuxpad("pad_gpio1_io10", "gpio1_io10", nil); - - /* gpio1_io10 low: panel off */ - gpioout(GPIO_PIN(1, 10), 0); - backlighton(); - /* gpio1_io10 high: panel on */ - gpioout(GPIO_PIN(1, 10), 1); + /* gpio3_io20: sn65dsi86 bridge enable */ + iomuxpad("pad_sai5_rxc", "gpio3_io20", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); /* gpio3_io20 high: bridge on */ gpioout(GPIO_PIN(3, 20), 1); From e760ded4943d802d7012514d56e18a8ddb54cc56 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 13:19:55 +0000 Subject: [PATCH 44/58] imx8/usdhc: implement highspeed mode (50Mhz) --- sys/src/9/imx8/usdhc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c index 01ea685d6..ba3989211 100644 --- a/sys/src/9/imx8/usdhc.c +++ b/sys/src/9/imx8/usdhc.c @@ -10,6 +10,7 @@ enum { Initfreq = 400000, /* initialisation frequency for MMC */ SDfreq = 25*Mhz, /* standard SD frequency */ + SDfreqhs = 50*Mhz, /* highspeed frequency */ DTO = 14, /* data timeout exponent (guesswork) */ GoIdle = 0, /* mmc/sdio go idle state */ @@ -446,6 +447,15 @@ usdhccmd(u32int cmd, u32int arg, u32int *resp) WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); break; } + } else { + /* + * If card switched into high speed mode, increase clock speed + */ + if((arg&0x8000000F) == 0x80000001){ + delay(1); + usdhcclk(SDfreqhs); + delay(1); + } } }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ switch(arg & 0x3){ @@ -518,4 +528,5 @@ SDio sdio = { usdhccmd, usdhciosetup, usdhcio, + .highspeed = 1, }; From 73b9f7c362dde15dee4331b02f1c75e29e49fbeb Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 14:32:51 +0000 Subject: [PATCH 45/58] imx8: fix install target --- sys/src/9/imx8/mkfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9/imx8/mkfile b/sys/src/9/imx8/mkfile index 01f8adad6..10d50f06b 100644 --- a/sys/src/9/imx8/mkfile +++ b/sys/src/9/imx8/mkfile @@ -80,7 +80,7 @@ $OBJ: $HFILES install:V: /$objtype/$p$CONF -/$objtype/$p$CONF:D: $p$CONF s$p$CONF +/$objtype/$p$CONF:D: $p$CONF $p$CONF.u cp -x $p$CONF $p$CONF.u /$objtype/ <../boot/bootmkfile From 7d4ffb868403377922d9cd0c8b4531cb77ec901c Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 18:12:38 +0000 Subject: [PATCH 46/58] aux/txt2uimage: helper for generating uimage script files --- sys/src/cmd/aux/mkfile | 1 + sys/src/cmd/aux/txt2uimage.c | 108 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 sys/src/cmd/aux/txt2uimage.c diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index f38fda5d7..1ef302c45 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -43,6 +43,7 @@ TARG=\ tablet\ timesync\ trampoline\ + txt2uimage\ unbflz\ usage\ write\ diff --git a/sys/src/cmd/aux/txt2uimage.c b/sys/src/cmd/aux/txt2uimage.c new file mode 100644 index 000000000..5fec8c7c9 --- /dev/null +++ b/sys/src/cmd/aux/txt2uimage.c @@ -0,0 +1,108 @@ +#include <u.h> +#include <libc.h> +#include <flate.h> + +int infd, outfd; +ulong dcrc; +ulong *tab; +uchar buf[65536]; + +enum { + IH_TYPE_SCRIPT = 6, +}; + +void +put(uchar *p, u32int v) +{ + *p++ = v >> 24; + *p++ = v >> 16; + *p++ = v >> 8; + *p = v; +} + +void +usage(void) +{ + fprint(2, "usage: %s a.out\n", argv0); + exits("usage"); +} + +void +block(int n) +{ + int rc; + + rc = readn(infd, buf, n); + if(rc < 0) sysfatal("read: %r"); + if(rc < n) sysfatal("input file truncated"); + if(write(outfd, buf, n) < 0) sysfatal("write: %r"); + dcrc = blockcrc(tab, dcrc, buf, n); +} + +void +copy(int n) +{ + int i; + + for(i = sizeof(buf) - 1; i < n; i += sizeof(buf)) + block(sizeof(buf)); + i = n & sizeof(buf) - 1; + if(i > 0) + block(i); +} + +void +main(int argc, char **argv) +{ + uchar header[64]; + char *ofile; + Dir *dir; + + ofile = nil; + ARGBEGIN { + case 'o': ofile = strdup(EARGF(usage())); break; + default: usage(); + } ARGEND; + + if(argc == 0) + infd = 0; + else { + if(argc != 1) usage(); + infd = open(argv[0], OREAD); + if(infd < 0) sysfatal("infd: %r"); + } + dir = dirfstat(infd); + if(dir == nil) sysfatal("stat: %r"); + if(dir->length > 0xFFFFFFFF-8) sysfatal("file too big"); + if(ofile == nil) ofile = smprint("%s.u", dir->name); + outfd = create(ofile, OWRITE|OTRUNC, 0666); + if(outfd < 0) sysfatal("create: %r"); + + tab = mkcrctab(0xEDB88320); + seek(outfd, sizeof(header), 0); + put(buf+0, dir->length); + put(buf+4, 0); + dcrc = blockcrc(tab, 0, buf, 8); + if(write(outfd, buf, 8) != 8) sysfatal("write: %r"); + copy(dir->length); + + memset(header, 0, sizeof(header)); + put(&header[0], 0x27051956); /* magic */ + put(&header[8], time(0)); /* time */ + put(&header[12], 8+dir->length); /* image size */ + put(&header[16], 0); /* load address */ + put(&header[20], 0); /* entry point */ + put(&header[24], dcrc); /* data crc */ + header[28] = 0; + header[29] = 0; + header[30] = IH_TYPE_SCRIPT; + header[31] = 0; /* compressed = no */ + + strncpy((char*)&header[32], dir->name, sizeof(header)-32); + put(&header[4], blockcrc(tab, 0, header, sizeof(header))); + + seek(outfd, 0, 0); + if(write(outfd, header, sizeof(header)) < sizeof(header)) sysfatal("write: %r"); + + exits(nil); +} From a16d54da37131f00ce2db824cf85c85ae746b752 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 18:15:16 +0000 Subject: [PATCH 47/58] add /sys/src/boot/reform/mkfile to download official u-boot for the mnt-reform --- sys/src/boot/reform/mkfile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 sys/src/boot/reform/mkfile diff --git a/sys/src/boot/reform/mkfile b/sys/src/boot/reform/mkfile new file mode 100644 index 000000000..17d4326dc --- /dev/null +++ b/sys/src/boot/reform/mkfile @@ -0,0 +1,9 @@ +FILES=flash.bin + +all:V: flash.bin + +clean:V: + rm -f $FILES + +flash.bin: + hget -o flash.bin 'https://source.mnt.re/reform/reform-boundary-uboot/-/jobs/artifacts/v3/raw/flash.bin?job=build' From ff7aa0671d8bcb65bc33df25f99b1c886c672df5 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 18:15:47 +0000 Subject: [PATCH 48/58] /sys/lib/dist/mkfile: add target for mnt-reform image --- sys/lib/dist/mkfile | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sys/lib/dist/mkfile b/sys/lib/dist/mkfile index 581ca2989..fa39a56e1 100644 --- a/sys/lib/dist/mkfile +++ b/sys/lib/dist/mkfile @@ -88,6 +88,18 @@ cd:V: /tmp/9front.386.iso.gz mv $target.$pid.disk $target } +%.reform.img: /n/src9/sys/src/boot/reform/flash.bin + @{ + objtype=arm64 + kernel=/n/src9/$objtype/9reform.u + echo 'load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} ${prefix}9reform.u; bootm ${kernel_addr_r}' > /env/boot.txt + aux/txt2uimage -o /env/boot.scr /env/boot.txt + fatfiles=(/env/boot.scr $kernel) + mb=1885 # storage vendors idea of 2GB + mk $target.$pid.disk + mv $target.$pid.disk $target && dd -trunc 0 -bs 1024 -oseek 33 -if /n/src9/sys/src/boot/reform/flash.bin -of $target + } + %.pc.iso:D: $proto /n/src9/sys/lib/sysconfig/proto/9bootproto $kernel @{rfork n mk binds @@ -142,6 +154,20 @@ cd:V: /tmp/9front.386.iso.gz disk/prep -bw -a^(nvram fs) $d/plan9 disk/format -d $d/dos $fatfiles } + if not if(~ $target *.reform.img.*){ + { + echo 'a p1 4M 100M' + echo 't p1 FAT32' + echo 'a p2 . $' + echo 't p2 PLAN9' + echo 'A p1' + echo 'p' + echo 'w' + echo 'q' + } | disk/fdisk -b $d/data + disk/prep -bw -a^(nvram fs) $d/plan9 + disk/format -d $d/dos $fatfiles + } if not { disk/fdisk -baw $d/data disk/prep -bw -a^(9fat nvram fs) $d/plan9 From 7bae48c452c75115a965aa13243c886a99cbf192 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 18:23:22 +0000 Subject: [PATCH 49/58] generate boot.scr in /sys/src/boot/reform --- sys/lib/dist/mkfile | 8 +++----- sys/src/boot/reform/boot.txt | 2 ++ sys/src/boot/reform/mkfile | 7 +++++-- 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 sys/src/boot/reform/boot.txt diff --git a/sys/lib/dist/mkfile b/sys/lib/dist/mkfile index fa39a56e1..ac9118ab3 100644 --- a/sys/lib/dist/mkfile +++ b/sys/lib/dist/mkfile @@ -77,7 +77,7 @@ cd:V: /tmp/9front.386.iso.gz mv $target.$pid.disk $target } -%.zynq.img: +%.zynq.img:D: @{ objtype=arm kernel=/n/src9/$objtype/9zynq @@ -88,13 +88,11 @@ cd:V: /tmp/9front.386.iso.gz mv $target.$pid.disk $target } -%.reform.img: /n/src9/sys/src/boot/reform/flash.bin +%.reform.img:D: /n/src9/sys/src/boot/reform/flash.bin /n/src9/sys/src/boot/reform/boot.scr @{ objtype=arm64 kernel=/n/src9/$objtype/9reform.u - echo 'load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} ${prefix}9reform.u; bootm ${kernel_addr_r}' > /env/boot.txt - aux/txt2uimage -o /env/boot.scr /env/boot.txt - fatfiles=(/env/boot.scr $kernel) + fatfiles=(/n/src9/sys/src/boot/reform/boot.scr $kernel) mb=1885 # storage vendors idea of 2GB mk $target.$pid.disk mv $target.$pid.disk $target && dd -trunc 0 -bs 1024 -oseek 33 -if /n/src9/sys/src/boot/reform/flash.bin -of $target diff --git a/sys/src/boot/reform/boot.txt b/sys/src/boot/reform/boot.txt new file mode 100644 index 000000000..738fd305d --- /dev/null +++ b/sys/src/boot/reform/boot.txt @@ -0,0 +1,2 @@ +load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} ${prefix}9reform.u +bootm ${kernel_addr_r} diff --git a/sys/src/boot/reform/mkfile b/sys/src/boot/reform/mkfile index 17d4326dc..52cd5058e 100644 --- a/sys/src/boot/reform/mkfile +++ b/sys/src/boot/reform/mkfile @@ -1,9 +1,12 @@ -FILES=flash.bin +FILES=flash.bin boot.scr -all:V: flash.bin +all:V: $FILES clean:V: rm -f $FILES flash.bin: hget -o flash.bin 'https://source.mnt.re/reform/reform-boundary-uboot/-/jobs/artifacts/v3/raw/flash.bin?job=build' + +boot.scr: boot.txt + aux/txt2uimage -o $target $prereq From 2b1ecbe87da757ddb12e38239773a05f816d03ae Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 20:31:49 +0000 Subject: [PATCH 50/58] imx8/usdhc: work around broken multi-write for now for unknown reasons, multiwrite is busted in usdhc: sdhc: write error intr 10 stat ff88858e usdhccmd: need to reset Datinhibit intr 10 stat ff88858e usdhc: cmd 193a0027 arg 1e5b6b error intr 18010 stat ff88858f i'm disabling it for now, adding a flag to the SDio struct. --- sys/src/9/imx8/usdhc.c | 10 +++++----- sys/src/9/port/sd.h | 1 + sys/src/9/port/sdmmc.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c index ba3989211..8954ba8b9 100644 --- a/sys/src/9/imx8/usdhc.c +++ b/sys/src/9/imx8/usdhc.c @@ -219,16 +219,15 @@ dmaalloc(void *addr, int len) uintptr a; Adma *adma, *p; - a = (uintptr)addr; + a = PADDR(addr); n = (len + Maxdma-1) / Maxdma; adma = sdmalloc(n * sizeof(Adma)); for(p = adma; len > 0; p++){ - p->desc = Valid | Tran; if(n == 1) - p->desc |= len<<OLength | End | Int; + p->desc = len<<OLength | End | Int | Valid | Tran; else - p->desc |= Maxdma<<OLength; - p->addr = PADDR(a); + p->desc = Maxdma<<OLength | Valid | Tran; + p->addr = a; a += Maxdma; len -= Maxdma; n--; @@ -529,4 +528,5 @@ SDio sdio = { usdhciosetup, usdhcio, .highspeed = 1, + .nomultiwrite = 1, }; diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index e4c567a17..0ef5dab33 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -162,6 +162,7 @@ struct SDio { void (*iosetup)(int, void*, int, int); void (*io)(int, uchar*, int); char highspeed; + char nomultiwrite; /* quirk for usdhc */ }; extern SDio sdio; diff --git a/sys/src/9/port/sdmmc.c b/sys/src/9/port/sdmmc.c index 34dbd046e..d7bd02d97 100644 --- a/sys/src/9/port/sdmmc.c +++ b/sys/src/9/port/sdmmc.c @@ -332,7 +332,7 @@ mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno) error(Echange); buf = data; len = unit->secsize; - if(Multiblock){ + if(Multiblock && (!write || !io->nomultiwrite)){ b = bno; tries = 0; while(waserror()) From 990ceeef3bfd9d56e2e6dd39cf5ac185b1a2de08 Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sat, 18 Jun 2022 23:37:12 +0000 Subject: [PATCH 51/58] nusb/usbd: retry opendevtata() a few times on attach (work around mnt-reform trackball) this is a known and already fixed issue with version the following version of the mnt-reform trackball firmware: https://source.mnt.re/reform/reform/-/commit/55ca5bf848b57cdf6e7243fc1018411f6c8ab9b5 --- sys/src/cmd/nusb/usbd/hub.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/src/cmd/nusb/usbd/hub.c b/sys/src/cmd/nusb/usbd/hub.c index 1a484625d..e04a4aedc 100644 --- a/sys/src/cmd/nusb/usbd/hub.c +++ b/sys/src/cmd/nusb/usbd/hub.c @@ -355,6 +355,7 @@ portattach(Hub *h, int p, u32int sts) char *sp; int mp; int nr; + int i; d = h->dev; pp = &h->port[p]; @@ -421,9 +422,13 @@ portattach(Hub *h, int p, u32int sts) nd->isusb3 = h->dev->isusb3; if(usbdebug > 2) devctl(nd, "debug 1"); - if(opendevdata(nd, ORDWR) < 0){ + for(i=0;; i++){ + if(opendevdata(nd, ORDWR) >= 0) + break; fprint(2, "%s: %s: opendevdata: %r\n", argv0, nd->dir); - goto Fail; + if(i >= 4) + goto Fail; + sleep(500); } if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p); From f0fc84aba3a40557539e7c014454b916a101759d Mon Sep 17 00:00:00 2001 From: cinap_lenrek <cinap_lenrek@felloff.net> Date: Sun, 19 Jun 2022 18:07:50 +0000 Subject: [PATCH 52/58] etherimx: fix link negotiation mdio interrupt command completion handling was broken, as the interrupt handler would clear the mii status register before mdiodone() sees it. handle errors in miistatus() and miiane(), to not get confused. --- sys/src/9/imx8/etherimx.c | 47 ++++++++++++++++++++++++--------------- sys/src/9/port/ethermii.c | 23 ++++++++++++++++++- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index 2f3d8ed28..9b816920f 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -9,7 +9,10 @@ #include "../port/ethermii.h" enum { - Moduleclk = 125000000, /* 125Mhz */ + Ptpclk = 100*Mhz, + Busclk = 266*Mhz, + Txclk = 125*Mhz, + Maxtu = 1518, R_BUF_SIZE = ((Maxtu+BLOCKALIGN-1)&~BLOCKALIGN), @@ -231,6 +234,7 @@ struct Ctlr struct { Mii; + int done; Rendez; } mii[1]; @@ -245,7 +249,7 @@ static int mdiodone(void *arg) { Ctlr *ctlr = arg; - return rr(ctlr, ENET_EIR) & INT_MII; + return ctlr->mii->done || (rr(ctlr, ENET_EIR) & INT_MII) != 0; } static int mdiowait(Ctlr *ctlr) @@ -265,9 +269,13 @@ mdiow(Mii* mii, int phy, int addr, int data) Ctlr *ctlr = mii->ctlr; data &= 0xFFFF; + wr(ctlr, ENET_EIR, INT_MII); + ctlr->mii->done = 0; + wr(ctlr, ENET_MMFR, MMFR_WR | MMFR_ST | MMFR_TA | phy<<MMFR_PA_SHIFT | addr<<MMFR_RA_SHIFT | data); - if(mdiowait(ctlr) < 0) return -1; + if(mdiowait(ctlr) < 0) + return -1; return data; } static int @@ -276,8 +284,11 @@ mdior(Mii* mii, int phy, int addr) Ctlr *ctlr = mii->ctlr; wr(ctlr, ENET_EIR, INT_MII); + ctlr->mii->done = 0; + wr(ctlr, ENET_MMFR, MMFR_RD | MMFR_ST | MMFR_TA | phy<<MMFR_PA_SHIFT | addr<<MMFR_RA_SHIFT); - if(mdiowait(ctlr) < 0) return -1; + if(mdiowait(ctlr) < 0) + return -1; return rr(ctlr, ENET_MMFR) & 0xFFFF; } @@ -289,11 +300,13 @@ interrupt(Ureg*, void *arg) u32int e; e = rr(ctlr, ENET_EIR); - wr(ctlr, ENET_EIR, e); - if(e & INT_RXF) wakeup(ctlr->rx); if(e & INT_TXF) wakeup(ctlr->tx); - if(e & INT_MII) wakeup(ctlr->mii); + if(e & INT_MII) { + ctlr->mii->done = 1; + wakeup(ctlr->mii); + } + wr(ctlr, ENET_EIR, e); } static void @@ -450,13 +463,11 @@ linkproc(void *arg) Ether *edev = arg; Ctlr *ctlr = edev->ctlr; MiiPhy *phy; - int link = -1; + int link = 0; while(waserror()) ; - - miiane(ctlr->mii, ~0, AnaAP|AnaP, ~0); - + miiane(ctlr->mii, ~0, ~0, ~0); for(;;){ miistatus(ctlr->mii); phy = ctlr->mii->curphy; @@ -505,7 +516,7 @@ linkproc(void *arg) edev->mbps = phy->speed; wr(ctlr, ENET_RDAR, RDAR_ACTIVE); - } + } edev->link = link; print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps); } @@ -532,7 +543,7 @@ attach(Ether *edev) wr(ctlr, ENET_RCR, RCR_MII_MODE | RCR_RGMII_EN | Maxtu<<RCR_MAX_FL_SHIFT); /* set MII clock to 2.5Mhz, 10ns hold time */ - wr(ctlr, ENET_MSCR, ((Moduleclk/(2*2500000))-1)<<MSCR_SPEED_SHIFT | ((Moduleclk/10000000)-1)<<MSCR_HOLD_SHIFT); + wr(ctlr, ENET_MSCR, ((Busclk/(2*2500000))-1)<<MSCR_SPEED_SHIFT | ((Busclk/1000000)-1)<<MSCR_HOLD_SHIFT); ctlr->intmask |= INT_MII; wr(ctlr, ENET_EIMR, ctlr->intmask); @@ -586,8 +597,8 @@ attach(Ether *edev) wr(ctlr, ENET_TFWR, TFWR_STRFWD); /* interrupt coalescing: 200 pkts, 1000 µs */ - wr(ctlr, ENET_RXIC0, IC_EN | 200<<IC_FT_SHIFT | ((1000*Moduleclk)/64000000)<<IC_TT_SHIFT); - wr(ctlr, ENET_TXIC0, IC_EN | 200<<IC_FT_SHIFT | ((1000*Moduleclk)/64000000)<<IC_TT_SHIFT); + wr(ctlr, ENET_RXIC0, IC_EN | 200<<IC_FT_SHIFT | ((1000*Txclk)/64000000)<<IC_TT_SHIFT); + wr(ctlr, ENET_TXIC0, IC_EN | 200<<IC_FT_SHIFT | ((1000*Txclk)/64000000)<<IC_TT_SHIFT); ctlr->intmask |= INT_TXF | INT_RXF; wr(ctlr, ENET_EIMR, ctlr->intmask); @@ -708,9 +719,9 @@ pnp(Ether *edev) setclkgate("enet1.ipp_ind_mac0_txclk", 0); setclkgate("sim_enet.mainclk", 0); - setclkrate("enet1.ipg_clk", "system_pll1_div3", 266*Mhz); - setclkrate("enet1.ipp_ind_mac0_txclk", "system_pll2_div8", Moduleclk); - setclkrate("enet1.ipg_clk_time", "system_pll2_div10", 25*Mhz); + setclkrate("enet1.ipg_clk", "system_pll1_div3", Busclk); + setclkrate("enet1.ipp_ind_mac0_txclk", "system_pll2_div8", Txclk); + setclkrate("enet1.ipg_clk_time", "system_pll2_div10", Ptpclk); setclkgate("enet1.ipp_ind_mac0_txclk", 1); setclkgate("sim_enet.mainclk", 1); diff --git a/sys/src/9/port/ethermii.c b/sys/src/9/port/ethermii.c index d75c35072..dcb3915e2 100644 --- a/sys/src/9/port/ethermii.c +++ b/sys/src/9/port/ethermii.c @@ -87,6 +87,8 @@ miireset(Mii* mii) if(mii == nil || mii->ctlr == nil || mii->curphy == nil) return -1; bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr); + if(bmcr == -1) + return -1; bmcr |= BmcrR; mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr); microdelay(1); @@ -104,6 +106,8 @@ miiane(Mii* mii, int a, int p, int e) phyno = mii->curphy->phyno; bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & BmsrAna)) return -1; @@ -113,6 +117,8 @@ miiane(Mii* mii, int a, int p, int e) anar = mii->curphy->anar; else{ anar = mii->mir(mii, phyno, Anar); + if(anar == -1) + return -1; anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD); if(bmsr & Bmsr10THD) anar |= Ana10HD; @@ -133,6 +139,8 @@ miiane(Mii* mii, int a, int p, int e) if(bmsr & BmsrEs){ mscr = mii->mir(mii, phyno, Mscr); + if(mscr == -1) + return -1; mscr &= ~(Mscr1000TFD|Mscr1000THD); if(e != ~0) mscr |= (Mscr1000TFD|Mscr1000THD) & e; @@ -140,6 +148,8 @@ miiane(Mii* mii, int a, int p, int e) mscr = mii->curphy->mscr; else{ r = mii->mir(mii, phyno, Esr); + if(r == -1) + return -1; if(r & Esr1000THD) mscr |= Mscr1000THD; if(r & Esr1000TFD) @@ -148,9 +158,12 @@ miiane(Mii* mii, int a, int p, int e) mii->curphy->mscr = mscr; mii->miw(mii, phyno, Mscr, mscr); } - mii->miw(mii, phyno, Anar, anar); + if(mii->miw(mii, phyno, Anar, anar) == -1) + return -1; r = mii->mir(mii, phyno, Bmcr); + if(r == -1) + return -1; if(!(r & BmcrR)){ r |= BmcrAne|BmcrRan; mii->miw(mii, phyno, Bmcr, r); @@ -175,12 +188,16 @@ miistatus(Mii* mii) * (Read status twice as the Ls bit is sticky). */ bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & (BmsrAnc|BmsrAna))) { // print("miistatus: auto-neg incomplete\n"); return -1; } bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & BmsrLs)){ // print("miistatus: link down\n"); phy->link = 0; @@ -190,6 +207,8 @@ miistatus(Mii* mii) phy->speed = phy->fd = phy->rfc = phy->tfc = 0; if(phy->mscr){ r = mii->mir(mii, phyno, Mssr); + if(r == -1) + return -1; if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){ phy->speed = 1000; phy->fd = 1; @@ -199,6 +218,8 @@ miistatus(Mii* mii) } anlpar = mii->mir(mii, phyno, Anlpar); + if(anlpar == -1) + return -1; if(phy->speed == 0){ r = phy->anar & anlpar; if(r & AnaTXFD){ From 7ca997bf7efdca16416b22488ebc7b70c419fd44 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sun, 19 Jun 2022 23:42:04 +0000 Subject: [PATCH 53/58] ndb: increase buffer size to allow longer lines when reading a long line such as a dkim key in a txt record, ndb calls Brdstr, which is limited to the size of the buffer. This means we would fail to parse the line from NDB, and bail out early. Increasing the buffer size allows us to read and parse longer lines. --- sys/include/ndb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/include/ndb.h b/sys/include/ndb.h index b44da0539..1a9ab7742 100644 --- a/sys/include/ndb.h +++ b/sys/include/ndb.h @@ -27,7 +27,7 @@ struct Ndb Ndb *next; Biobufhdr b; /* buffered input file */ - uchar buf[256]; /* and its buffer */ + uchar buf[8192]; /* and its buffer */ ulong mtime; /* mtime of db file */ Qid qid; /* qid of db file */ From fa0c807bfb50ba01c9e602de555f64e4c84e3fb1 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 21 Jun 2022 13:21:38 +0000 Subject: [PATCH 54/58] kernel: add /srv/clone to get seperate /srv bulletin boards. --- sys/man/3/srv | 16 +- sys/src/9/port/devsrv.c | 430 ++++++++++++++++++++++++++++++++-------- 2 files changed, 358 insertions(+), 88 deletions(-) diff --git a/sys/man/3/srv b/sys/man/3/srv index 820c849db..b68f00887 100644 --- a/sys/man/3/srv +++ b/sys/man/3/srv @@ -5,6 +5,8 @@ srv \- server registry .nf .B bind #s /srv +.BI #s/ clone +.BI #s/ n .BI #s/ service1 .BI #s/ service2 ... @@ -12,7 +14,7 @@ srv \- server registry .SH DESCRIPTION The .I srv -device provides a one-level directory holding +device provides a tree of directories holding already-open channels to services. In effect, .I srv @@ -40,6 +42,18 @@ releases that reference. .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. +.PP +Opening the +.I clone +file allocates a new service directory. Reading +.I clone +returns the id of the new directory. This new service +directory can then be accessed at +.BR /srv/id . +Directories are recursable; each new service directory +contains its own +.I clone +file. .SH EXAMPLE To drop one end of a pipe into .BR /srv , diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 8128569a1..f676227d4 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -5,80 +5,249 @@ #include "fns.h" #include "../port/error.h" +#include "netif.h" + +typedef struct Link Link; +struct Link +{ + void *link; + char *name; + ulong path; +}; typedef struct Srv Srv; struct Srv { - char *name; + Link; + char *owner; ulong perm; Chan *chan; - Srv *link; - ulong path; }; -static QLock srvlk; -static Srv *srv; -static int qidpath; - -static Srv* -srvlookup(char *name, ulong qidpath) +typedef struct Board Board; +struct Board { - Srv *sp; + Link; + RWlock; + Ref; - for(sp = srv; sp != nil; sp = sp->link) { - if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) - return sp; + Board *parent; + Board *child; + Srv *srv; + long id; + int qidpath; + int closed; +}; + +struct{ + QLock; + long path; +} boards; + +enum{ + Qroot, + Qclone, + Qlease, + + Qend, +}; + +Board root; + +static char Eexpired[] = "expired lease"; + +static void* +lookup(Link *l, char *name, ulong qidpath) +{ + Link *lp; + + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + for(lp = l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + return lp; + if(name != nil && strcmp(lp->name, name) == 0) + return lp; } return nil; } +static void* +remove(Link **l, char *name, ulong qidpath) +{ + Link *lp; + Link **last; + + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + last = l; + for(lp = *l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + break; + if(name != nil && strcmp(lp->name, name) == 0) + break; + last = &lp->link; + } + if(lp == nil) + return nil; + + *last = lp->link; + lp->link = nil; + return lp; +} + +static void +boardclunk(Board *b, int close) +{ + Srv *sp, *prv; + Board *ch; + long ref; + + /* caller holds a wlock */ + if(b == &root){ + wunlock(b); + return; + } + + if(close){ + assert(b->closed == 0); + b->closed++; + for(sp = b->srv; sp != nil; sp = prv){ + prv = sp->link; + free(sp->owner); + free(sp->name); + if(sp->chan != nil) + cclose(sp->chan); + free(sp); + } + b->srv = nil; + } + ref = decref(b); + + /* + * All boards must be walkable from root. So a board + * is allowed to sit at zero references as long as it + * still has active children. For leaf nodes we then + * have to walk up the tree to clear now empty parents. + */ + while(b->closed && b->child == nil && ref == 0){ + //Root should never be closed + assert(b->parent != nil); + wlock(b->parent); + ch = remove((Link**)&b->parent->child, b->name, b->path); + assert(ch == b); + + b = ch->parent; + free(ch->name); + wunlock(ch); + free(ch); + } + wunlock(b); +} + static int srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; + Board *b, *ch; Qid q; - if(s == DEVDOTDOT){ - devdir(c, c->qid, "#s", 0, eve, 0555, dp); - return 1; - } + if(name != nil && strlen(name) >= sizeof(up->genbuf)) + return -1; - qlock(&srvlk); - if(name != nil) - sp = srvlookup(name, -1); - else { - for(sp = srv; sp != nil && s > 0; sp = sp->link) - s--; - } - if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { - qunlock(&srvlk); + b = c->aux; + ch = nil; + mkqid(&q, ~0L, 0, QTFILE); + rlock(b); + if(waserror()){ + runlock(b); return -1; } - mkqid(&q, sp->path, 0, QTFILE); - /* make sure name string continues to exist after we release lock */ - kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); - devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - qunlock(&srvlk); + if(s == DEVDOTDOT){ + ch = b->parent; + if(ch == nil) + ch = &root; + goto Child; + + } + if(name != nil){ + if(strcmp("clone", name) == 0) + goto Clone; + + sp = lookup(b->srv, name, ~0UL); + if(sp == nil) + ch = lookup(b->child, name, ~0UL); + } else { + if(s == 0) + goto Clone; + s--; + for(sp = b->srv; sp != nil && s > 0; sp = sp->link) + s--; + for(ch = b->child; ch != nil && s > 0; ch = ch->link) + s--; + } + if(sp != nil){ + kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, sp->path); + devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); + } else if(ch != nil){ +Child: + kstrcpy(up->genbuf, ch->name, sizeof up->genbuf); + q.vers = ch->id; + q.path = NETQID(q.vers, ch->path); + q.type = QTDIR; + devdir(c, q, up->genbuf, 0, eve, 0555|DMDIR, dp); + /* dirread's and stats shouldn't alter c->aux */ + if(name != nil) + c->aux = ch; + } else if(0){ +Clone: + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, Qclone); + devdir(c, q, "clone", 0, eve, 0444, dp); + } else + error(Enonexist); + + runlock(b); + poperror(); return 1; } static void srvinit(void) { - qidpath = 1; + root.qidpath = Qend; + root.name = "#s"; } static Chan* srvattach(char *spec) { - return devattach('s', spec); + Chan *c; + + c = devattach('s', spec); + c->aux = &root; + return c; } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, 0, 0, srvgen); + Board *b; + Walkqid *wq; + + wq = devwalk(c, nc, name, nname, 0, 0, srvgen); + if(wq == nil || wq->clone == nil) + return wq; + + b = wq->clone->aux; + if(b == &root) + return wq; + + incref(b); + return wq; } static int @@ -90,12 +259,14 @@ srvstat(Chan *c, uchar *db, int n) char* srvname(Chan *c) { + Board *b; Srv *sp; char *s; s = nil; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + rlock(b); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -103,15 +274,17 @@ srvname(Chan *c) break; } } - qunlock(&srvlk); + runlock(b); return s; } static Chan* srvopen(Chan *c, int omode) { + Board *b, *ch; Srv *sp; Chan *nc; + char buf[64]; if(c->qid.type == QTDIR){ if(omode & ORCLOSE) @@ -123,20 +296,53 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } - qlock(&srvlk); - if(waserror()){ - qunlock(&srvlk); - nexterror(); - } - - sp = srvlookup(nil, c->qid.path); - if(sp == nil || sp->chan == nil) - error(Eshutdown); - if(omode&OTRUNC) error(Eexist); if(omode&ORCLOSE) error(Eperm); + + b = c->aux; + if(NETTYPE(c->qid.path) == Qclone){; + wlock(b); + if(b->closed){ + wunlock(b); + error(Eexpired); + } + ch = smalloc(sizeof *ch); + ch->qidpath = Qend; + ch->ref = 1; + do { + qlock(&boards); + ch->id = ++boards.path; + qunlock(&boards); + snprint(buf, sizeof buf, "%ld", ch->id); + } while(lookup(b->srv, buf, ~0UL) != nil); + + ch->parent = b; + ch->path = b->qidpath++; + kstrdup(&ch->name, buf); + + ch->link = b->child; + b->child = ch; + c->aux = ch; + c->qid.vers = ch->id; + c->qid.path = NETQID(ch->id, Qlease); + boardclunk(b, 0); //unlock + return c; + } + + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } + if(b->closed) + error(Eexpired); + + sp = lookup(b->srv, nil, c->qid.path); + if(sp == nil || sp->chan == nil) + error(Eshutdown); + if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); devpermcheck(sp->owner, sp->perm, omode); @@ -144,7 +350,7 @@ srvopen(Chan *c, int omode) nc = sp->chan; incref(nc); - qunlock(&srvlk); + runlock(b); poperror(); cclose(c); @@ -154,6 +360,7 @@ srvopen(Chan *c, int omode) static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { + Board *b; Srv *sp; if(openmode(omode) != OWRITE) @@ -166,27 +373,33 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(srvlookup(name, -1) != nil) + if(b->closed) + error(Eexpired); + if(lookup(b->srv, name, ~0UL) != nil) + error(Eexist); + if(lookup(b->child, name, ~0UL) != nil) error(Eexist); sp->perm = perm&0777; - sp->path = qidpath++; + sp->path = b->qidpath++; - c->qid.path = sp->path; + c->qid.path = NETQID(b->id, sp->path); + c->qid.vers = b->id; c->qid.type = QTFILE; - sp->link = srv; - srv = sp; + sp->link = b->srv; + b->srv = sp; - qunlock(&srvlk); + wunlock(b); poperror(); c->flag |= COPEN; @@ -198,22 +411,24 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) static void srvremove(Chan *c) { - Srv *sp, **l; + Board *b; + Srv *sp; if(c->qid.type == QTDIR) error(Eperm); + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: + error(Eperm); + } - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); nexterror(); } - l = &srv; - for(sp = *l; sp != nil; sp = *l) { - if(sp->path == c->qid.path) - break; - l = &sp->link; - } + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -229,10 +444,9 @@ srvremove(Chan *c) if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve()) error(Eperm); - *l = sp->link; - sp->link = nil; + remove((Link**)&b->srv, nil, c->qid.path); - qunlock(&srvlk); + boardclunk(b, 0); //unlock poperror(); if(sp->chan != nil) @@ -245,12 +459,18 @@ srvremove(Chan *c) static int srvwstat(Chan *c, uchar *dp, int n) { + Board *b; char *strs; Srv *sp; Dir d; if(c->qid.type & QTDIR) error(Eperm); + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: + error(Eperm); + } strs = smalloc(n); if(waserror()){ @@ -261,13 +481,16 @@ srvwstat(Chan *c, uchar *dp, int n) if(n == 0) error(Eshortstat); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); nexterror(); } + if(b->closed) + error(Eexpired); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -279,6 +502,10 @@ srvwstat(Chan *c, uchar *dp, int n) error(Ebadchar); if(strlen(d.name) >= sizeof(up->genbuf)) error(Etoolong); + if(lookup(b->srv, d.name, ~0UL) != nil) + error(Eexist); + if(lookup(b->child, d.name, ~0UL) != nil) + error(Eexist); kstrdup(&sp->name, d.name); } if(d.uid != nil && *d.uid) @@ -286,7 +513,7 @@ srvwstat(Chan *c, uchar *dp, int n) if(d.mode != ~0UL) sp->perm = d.mode & 0777; - qunlock(&srvlk); + wunlock(b); poperror(); free(strs); @@ -298,22 +525,42 @@ srvwstat(Chan *c, uchar *dp, int n) static void srvclose(Chan *c) { - /* - * in theory we need to override any changes in removability - * since open, but since all that's checked is the owner, - * which is immutable, all is well. - */ - if(c->flag & CRCLOSE){ + Board *b; + int expired; + + expired = 0; + if(NETTYPE(c->qid.path) == Qlease) + expired++; + else if(c->flag & CRCLOSE){ + /* + * in theory we need to override any changes in removability + * since open, but since all that's checked is the owner, + * which is immutable, all is well. + */ if(waserror()) - return; + goto Clunk; srvremove(c); poperror(); + return; } +Clunk: + b = c->aux; + wlock(b); + boardclunk(b, expired); //unlock } static long -srvread(Chan *c, void *va, long n, vlong) +srvread(Chan *c, void *va, long n, vlong off) { + Board *b; + + if(NETTYPE(c->qid.path) == Qlease){ + b = c->aux; + rlock(b); + n = readstr((ulong)off, va, n, b->name); + runlock(b); + return n; + } isdir(c); return devdirread(c, va, n, 0, 0, srvgen); } @@ -321,11 +568,15 @@ srvread(Chan *c, void *va, long n, vlong) static long srvwrite(Chan *c, void *va, long n, vlong) { + Board *b; Srv *sp; Chan *c1; int fd; char buf[32]; + if(NETTYPE(c->qid.path) == Qlease) + error(Eperm); + if(n >= sizeof buf) error(Etoobig); memmove(buf, va, n); /* so we can NUL-terminate */ @@ -334,15 +585,18 @@ srvwrite(Chan *c, void *va, long n, vlong) c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()) { - qunlock(&srvlk); + wunlock(b); cclose(c1); nexterror(); } + if(b->closed) + error(Eexpired); if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -351,7 +605,7 @@ srvwrite(Chan *c, void *va, long n, vlong) sp->chan = c1; - qunlock(&srvlk); + wunlock(b); poperror(); return n; } @@ -380,12 +634,14 @@ Dev srvdevtab = { void srvrenameuser(char *old, char *new) { + Board *b; Srv *sp; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + wlock(b); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - qunlock(&srvlk); + wunlock(b); } From 5ee86cf824c5591aa92118c0cd9d71b005e789d0 Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Wed, 22 Jun 2022 15:53:32 +0000 Subject: [PATCH 55/58] kernel: correct error handling in /srv/clone read readstr can error, we need to catch the error and unlock. --- sys/src/9/port/devsrv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index f676227d4..e1b7856f9 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -557,8 +557,13 @@ srvread(Chan *c, void *va, long n, vlong off) if(NETTYPE(c->qid.path) == Qlease){ b = c->aux; rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } n = readstr((ulong)off, va, n, b->name); runlock(b); + poperror(); return n; } isdir(c); From 5579176f4a885bb83119bb49598c357ce8db2343 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 25 Jun 2022 18:58:55 +0000 Subject: [PATCH 56/58] awk: initialize records fully in recinit() when using records in BEGIN, we would read from the field table before we read into it; this ensures that the fields are an empty string before we start touching their contents. --- sys/src/cmd/awk/lib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/awk/lib.c b/sys/src/cmd/awk/lib.c index 2c5a60465..5044d3123 100644 --- a/sys/src/cmd/awk/lib.c +++ b/sys/src/cmd/awk/lib.c @@ -54,11 +54,13 @@ static Cell dollar1 = { OCELL, CFLD, nil, "", 0.0, FLD|STR|DONTFREE }; void recinit(unsigned int n) { + assert(n > 0); record = (char *) malloc(n); fields = (char *) malloc(n); fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *)); if (record == nil || fields == nil || fldtab == nil) FATAL("out of space for $0 and fields"); + record[0] = '\0'; fldtab[0] = (Cell *) malloc(sizeof (Cell)); *fldtab[0] = dollar0; fldtab[0]->sval = record; @@ -108,7 +110,7 @@ int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ firsttime = 0; initgetrec(); } - dprint( ("RS=<%s>, FS=<%s>, AARGC=%g, FILENAME=%s\n", + dprint( ("RS=<%s>, FS=<%s>, AARGC=%g, FILENAME=%s\n", *RS, *FS, *AARGC, *FILENAME) ); if (isrecord) { donefld = 0; From 10afa189d5ee84e1935ead905b3bbe38060a92e8 Mon Sep 17 00:00:00 2001 From: Ori Bernstein <ori@eigenstate.org> Date: Sat, 25 Jun 2022 20:03:41 +0000 Subject: [PATCH 57/58] awk: correct incoherent cell in assignment (thanks smj, mpinjr) In run.c::assign(), assigning to $0 from $F, a field, where F >= 2, produces an incoherent cell. The assignment occurs in two steps, first the string value and then the float. When the string value is assigned to $0, setsval invalidates the fields. If FS hasn't changed, after getfval rebuilds the fields, NF = 1 and F >= 2, therefore $F is definitely uninitialized. The result is a float val of 0.0, producing a boolean false in the pattern expression. Coercing a string comparison gives the expected result because the incoherent cell has the correct string value, which is not empty and evaluates to true. --- sys/src/cmd/awk/run.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/awk/run.c b/sys/src/cmd/awk/run.c index 5e75c9d0a..090410314 100644 --- a/sys/src/cmd/awk/run.c +++ b/sys/src/cmd/awk/run.c @@ -1127,8 +1127,9 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ goto Free; /* leave alone unless it's a field */ if ((y->tval & (STR|NUM)) == (STR|NUM)) { + yf = getfval(y); setsval(x, getsval(y)); - x->fval = getfval(y); + x->fval = yf; x->tval |= NUM; } else if (isstr(y)) From 9e363c506eccb783dd4d1d31f14c9d8dba98f65e Mon Sep 17 00:00:00 2001 From: Jacob Moody <moody@posixcafe.org> Date: Tue, 28 Jun 2022 14:57:39 +0000 Subject: [PATCH 58/58] /lib/rob: Sockets are just so unpleasant https://minnie.tuhs.org/pipermail/tuhs/2022-June/026012.html --- lib/rob | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rob b/lib/rob index 6da79ed6d..6c0725a56 100644 --- a/lib/rob +++ b/lib/rob @@ -399,3 +399,4 @@ Over time, everything gets better but also worse and always bigger and more comp Nice to see Egreg again. It wasn't my intention. The Blit was nice. +Sockets are just so unpleasant, and the endless nonsense around network configuration doubly so.