diff options
author | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-08-21 01:30:03 +0000 |
---|---|---|
committer | Sigrid Solveig Haflínudóttir <sigrid@ftrv.se> | 2022-08-21 01:30:03 +0000 |
commit | a78b71b143240fa1dad019f5c655a03c2d2400d9 (patch) | |
tree | e89536e837fbd4a921542d81e73d7315b4da3ac4 /sys/src/cmd/reform/pm.c | |
parent | 5e15db8fa31dd68fee22f260ae797a38ccaa4070 (diff) |
move and rename MNT Reform 2 support utilies, cat manpages into one
Aux/imx8pm and aux/wm8960 had pretty cryptic names and it made
more sense to use a reform/pm and reform/audio naming, accordingly.
Instead of having special mount points /mnt/pm and /mnt/wm8960,
/dev is used directly, removing the need to do any manual work -
stats(1) will continue showing the CPU temperature, and zuke(1)
will still be able to control the volume, etc.
Brightness controls were changed to a better interface -
/dev/light, where each line contains a "a_thing its_light_value".
This way more parts can be controlled. Right now it's only "lcd",
but later it might be "kbd" and "trackball" as well.
Example of lib/profile:
reform/audio
echo master 80 > /dev/volume
reform/pm
echo lcd 100 > /dev/light
Diffstat (limited to 'sys/src/cmd/reform/pm.c')
-rw-r--r-- | sys/src/cmd/reform/pm.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/sys/src/cmd/reform/pm.c b/sys/src/cmd/reform/pm.c new file mode 100644 index 000000000..6e0f3c161 --- /dev/null +++ b/sys/src/cmd/reform/pm.c @@ -0,0 +1,243 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> + +enum +{ + Mhz = 1000*1000, + Pwmsrcclk = 25*Mhz, + + Light = 1, + Temp, + + PWMSAR = 0x0c/4, + PWMPR = 0x10/4, + + TMUTMR = 0x00/4, + TMR_ME = 1<<31, + TMR_ALPF_SHIFT = 26, + TMR_MSITE_SHIFT = 13, + TMUTSR = 0x04/4, + TSR_MIE = 1<<30, + TSR_ORL = 1<<29, + TSR_ORH = 1<<28, + TMUTMTMIR = 0x08/4, + TMUTIER = 0x20/4, + TMUTIDR = 0x24/4, + TIDR_MASK = 0xe0000000, + TMUTISCR = 0x28/4, + TMUTICSCR = 0x2c/4, + TMUTTCFGR = 0x80/4, + TMUTSCFGR = 0x84/4, + TMUTRITSR0 = 0x100/4, + TMUTRITSR1 = 0x110/4, + TMUTRITSR2 = 0x120/4, + TMUTTR0CR = 0xf10/4, + TMUTTR1CR = 0xf14/4, + TMUTTR2CR = 0xf18/4, + TMUTTR3CR = 0xf1c/4, + CR_CAL_PTR_SHIFT = 16, + +}; + +static u32int *pwm2, *tmu; +static char *uid = "pm"; + +static void +wr(u32int *base, int reg, u32int v) +{ + //fprint(2, "[0%x] ← 0x%ux\n", reg*4, v); + if(base != nil) + base[reg] = v; +} + +static u32int +rd(u32int *base, int reg) +{ + return base != nil ? base[reg] : -1; +} + +static void +setlight(int p) +{ + u32int v; + + if(p < 0) + p = 0; + if(p > 100) + p = 100; + + v = Pwmsrcclk / rd(pwm2, PWMSAR); + wr(pwm2, PWMPR, (Pwmsrcclk/(v*p/100))-2); +} + +static int +getlight(void) +{ + u32int m, v; + + m = Pwmsrcclk / rd(pwm2, PWMSAR); + v = Pwmsrcclk / (rd(pwm2, PWMPR)+2); + return v*100/m; +} + +static int +getcputemp(int c[3]) +{ + int i, r[] = {TMUTRITSR0, TMUTRITSR1, TMUTRITSR2}; + u32int s; + + s = rd(tmu, TMUTSR); + if(s & TSR_MIE){ + werrstr("monitoring interval exceeded"); + return -1; + } + if(s & (TSR_ORL|TSR_ORH)){ + werrstr("out of range"); + return -1; + } + + c[0] = c[1] = c[2] = 0; + for(;;){ + for(i = 0; i < 3; i++) + if(c[i] >= 0) + c[i] = rd(tmu, r[i]); + if(c[0] < 0 && c[1] < 0 && c[2] < 0) + break; + sleep(10); + } + c[0] &= 0xff; + c[1] &= 0xff; + c[2] &= 0xff; + return 0; +} + +static void +tmuinit(void) +{ + /* without proper calibration data sensing is useless */ + static u8int cfg[4][12] = { + {0x23, 0x29, 0x2f, 0x35, 0x3d, 0x43, 0x4b, 0x51, 0x57, 0x5f, 0x67, 0x6f}, + {0x1b, 0x23, 0x2b, 0x33, 0x3b, 0x43, 0x4b, 0x55, 0x5d, 0x67, 0x70, 0}, + {0x17, 0x23, 0x2d, 0x37, 0x41, 0x4b, 0x57, 0x63, 0x6f, 0}, + {0x15, 0x21, 0x2d, 0x39, 0x45, 0x53, 0x5f, 0x71, 0}, + }; + int i, j; + + wr(tmu, TMUTMR, 0); /* disable */ + wr(tmu, TMUTIER, 0); /* disable all interrupts */ + wr(tmu, TMUTMTMIR, 0xf); /* no monitoring interval */ + + /* configure default ranges */ + wr(tmu, TMUTTR0CR, 11<<CR_CAL_PTR_SHIFT | 0); + wr(tmu, TMUTTR1CR, 10<<CR_CAL_PTR_SHIFT | 38); + wr(tmu, TMUTTR2CR, 8<<CR_CAL_PTR_SHIFT | 72); + wr(tmu, TMUTTR3CR, 7<<CR_CAL_PTR_SHIFT | 97); + + /* calibration data */ + for(i = 0; i < 4; i++){ + for(j = 0; j < 12 && cfg[i][j] != 0; j++){ + wr(tmu, TMUTTCFGR, i<<16|j); + wr(tmu, TMUTSCFGR, cfg[i][j]); + } + } + + /* enable: all sites, ALPF 11=0.125 */ + wr(tmu, TMUTMR, TMR_ME | 3<<TMR_ALPF_SHIFT | 7<<TMR_MSITE_SHIFT); +} + +static void +fsread(Req *r) +{ + char msg[256]; + int c[3]; + + msg[0] = 0; + if(r->ifcall.offset == 0){ + if(r->fid->file->aux == (void*)Light) + snprint(msg, sizeof(msg), "lcd %d\n", getlight()); + else if(r->fid->file->aux == (void*)Temp){ + if(getcputemp(c) == 0) + snprint(msg, sizeof(msg), "%d.0\n", c[0]); + else + snprint(msg, sizeof(msg), "%r\n"); + } + } + + readstr(r, msg); + respond(r, nil); +} + +static void +fswrite(Req *r) +{ + char msg[256], *f[4]; + int nf, v; + + if(r->fid->file->aux == (void*)Light){ + snprint(msg, sizeof(msg), "%.*s", + utfnlen((char*)r->ifcall.data, r->ifcall.count), (char*)r->ifcall.data); + nf = tokenize(msg, f, nelem(f)); + if(nf < 2){ + respond(r, "invalid ctl message"); + return; + } + if(strcmp(f[0], "lcd") == 0){ + v = atoi(f[1]); + if(*f[1] == '+' || *f[1] == '-') + v += getlight(); + setlight(v); + } + } + + r->ofcall.count = r->ifcall.count; + respond(r, nil); +} + +static Srv fs = { + .read = fsread, + .write = fswrite, +}; + +static void +usage(void) +{ + fprint(2, "usage: %s [-D] [-m /dev] [-s service]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *mtpt, *srv; + + mtpt = "/dev"; + srv = nil; + ARGBEGIN{ + case 'D': + chatty9p = 1; + break; + case 'm': + mtpt = EARGF(usage()); + break; + case 's': + srv = EARGF(usage()); + break; + default: + usage(); + }ARGEND + + if((tmu = segattach(0, "tmu", 0, 0xf20)) == (void*)-1) + sysfatal("no tmu"); + if((pwm2 = segattach(0, "pwm2", 0, 0x18)) == (void*)-1) + sysfatal("no pwm2"); + tmuinit(); + fs.tree = alloctree(uid, uid, DMDIR|0555, nil); + createfile(fs.tree->root, "cputemp", uid, 0444, (void*)Temp); + createfile(fs.tree->root, "light", uid, 0666, (void*)Light); + postmountsrv(&fs, srv, mtpt, MAFTER); + + exits(nil); +} |