summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/ec.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-11-10 00:04:37 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-11-10 00:04:37 +0100
commitbcb67353c1ae559d6f91ab0669a06db52000b15d (patch)
treee2e6e9b26b7f13e234315c5753982bca4100dd22 /sys/src/9/pc/ec.c
parentb18a6413975a0a8d06e6d310072a0ff90b1ed541 (diff)
pc, pc64: provide access to embedded controller with #P/ec file
Diffstat (limited to 'sys/src/9/pc/ec.c')
-rw-r--r--sys/src/9/pc/ec.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/sys/src/9/pc/ec.c b/sys/src/9/pc/ec.c
new file mode 100644
index 000000000..c42356af7
--- /dev/null
+++ b/sys/src/9/pc/ec.c
@@ -0,0 +1,138 @@
+/*
+ * embedded controller (usually at ports 0x66/0x62)
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ /* registers */
+ EC_SC = 0,
+ EC_DATA,
+
+ /* Embedded Controller Status, EC_SC (R) */
+ OBF = 1<<0,
+ IBF = 1<<1,
+ CMD = 1<<3,
+ BURST = 1<<4,
+ SCI_EVT = 1<<5,
+ SMI_EVT = 1<<6,
+
+ /* Embedded Controller Command Set */
+ RD_EC = 0x80,
+ WR_EC = 0x81,
+ BE_EC = 0x82,
+ BD_EC = 0x83,
+ QR_EC = 0x84,
+};
+
+static struct {
+ Lock;
+ int init;
+ int port[2]; /* EC_SC and EC_DATA */
+} ec;
+
+static uchar
+ecrr(int reg)
+{
+ return inb(ec.port[reg]);
+}
+static void
+ecwr(int reg, uchar val)
+{
+ outb(ec.port[reg], val);
+}
+
+static int
+ecwait(uchar mask, uchar val)
+{
+ int i, s;
+
+ s = 0;
+ for(i=0; i<1000; i++){
+ s = ecrr(EC_SC);
+ if((s & mask) == val)
+ return 0;
+ delay(1);
+ }
+ print("ec: wait timeout status=%x pc=%#p\n", s, getcallerpc(&mask));
+ return -1;
+}
+
+int
+ecinit(int cmdport, int dataport)
+{
+ print("ec: cmd %X, data %X\n", cmdport, dataport);
+
+ if(ioalloc(cmdport, 1, 0, "ec.sc") < 0){
+ print("ec: cant allocate cmd port %X\n", cmdport);
+ return -1;
+ }
+ if(ioalloc(dataport, 1, 0, "ec.data") < 0){
+ print("ec: cant allocate data port %X\n", dataport);
+ iofree(cmdport);
+ return -1;
+ }
+
+ lock(&ec);
+ ec.port[EC_SC] = cmdport;
+ ec.port[EC_DATA] = dataport;
+ ec.init = 1;
+ unlock(&ec);
+
+ return 0;
+}
+
+int
+ecread(uchar addr)
+{
+ int r;
+
+ r = -1;
+ lock(&ec);
+ if(!ec.init)
+ goto out;
+ if(ecwait(BURST|CMD, 0))
+ goto out;
+ ecwr(EC_SC, RD_EC);
+ if(ecwait(IBF, 0))
+ goto out;
+ ecwr(EC_DATA, addr);
+ if(ecwait(OBF, OBF))
+ goto out;
+ r = ecrr(EC_DATA);
+ ecwait(OBF, 0);
+out:
+ unlock(&ec);
+ return r;
+}
+
+int
+ecwrite(uchar addr, uchar val)
+{
+ int r;
+
+ r = -1;
+ lock(&ec);
+ if(!ec.init)
+ goto out;
+ if(ecwait(BURST|CMD, 0))
+ goto out;
+ ecwr(EC_SC, WR_EC);
+ if(ecwait(IBF, 0))
+ goto out;
+ ecwr(EC_DATA, addr);
+ if(ecwait(IBF, 0))
+ goto out;
+ ecwr(EC_DATA, val);
+ if(ecwait(IBF, 0))
+ goto out;
+ r = 0;
+out:
+ unlock(&ec);
+ return r;
+}