shithub: riscv

Download patch

ref: bcb67353c1ae559d6f91ab0669a06db52000b15d
parent: b18a6413975a0a8d06e6d310072a0ff90b1ed541
author: cinap_lenrek <[email protected]>
date: Sun Nov 9 19:04:37 EST 2014

pc, pc64: provide access to embedded controller with #P/ec file

--- a/sys/man/3/arch
+++ b/sys/man/3/arch
@@ -8,6 +8,7 @@
 .B /dev/acpitbls
 .B /dev/archctl
 .B /dev/cputype
+.B /dev/ec
 .B /dev/ioalloc
 .B /dev/iob
 .B /dev/iol
@@ -127,6 +128,10 @@
 Reads and writes to
 .I msr
 go to the P4/P6/Core/Core2/AMD64 MSRs.
+.PP
+Reads and writes to
+.I ec
+transfer bytes from and to the embedded controller.
 .PP
 Reads from
 .I acpitbls
--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -453,6 +453,30 @@
 	return 1;
 }
 
+static int
+enumec(void *dot, void *)
+{
+	int cmdport, dataport;
+	uchar *b;
+	void *x;
+	char *id;
+
+	b = nil;
+	id = eisaid(amlval(amlwalk(dot, "^_HID")));
+	if(id == nil || strcmp(id, "PNP0C09") != 0)
+		return 1;
+	if((x = amlwalk(dot, "^_CRS")) == nil)
+		return 1;
+	if(amleval(x, "", &b) < 0 || amltag(b) != 'b' || amllen(b) < 16)
+		return 1;
+	if(b[0] != 0x47 || b[8] != 0x47)	/* two i/o port descriptors */
+		return 1;
+	dataport = b[0+2] | b[0+3]<<8;
+	cmdport = b[8+2] | b[8+3]<<8;
+	ecinit(cmdport, dataport);
+	return 1;
+}
+
 static void
 acpiinit(void)
 {
@@ -588,6 +612,9 @@
 	/* add identity mapped legacy isa interrupts */
 	for(i=0; i<16; i++)
 		addirq(i, BusISA, 0, i, 0);
+
+	/* find embedded controller */
+	amlenum(amlroot, "_HID", enumec, nil);
 
 	/* free the AML interpreter */
 	amlexit();
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -34,6 +34,7 @@
 	Qiow,
 	Qiol,
 	Qmsr,
+	Qec,
 	Qbase,
 
 	Qmax = 16,
@@ -62,7 +63,8 @@
 	"iob",		{ Qiob, 0 },		0,	0660,
 	"iow",		{ Qiow, 0 },		0,	0660,
 	"iol",		{ Qiol, 0 },		0,	0660,
-	"msr",	{ Qmsr, 0},	0,	0660,
+	"msr",		{ Qmsr, 0 },		0,	0660,
+	"ec",		{ Qec, 0 },		0,	0660,
 };
 Lock archwlock;	/* the lock is only for changing archdir */
 int narchdir = Qbase;
@@ -361,7 +363,7 @@
 archread(Chan *c, void *a, long n, vlong offset)
 {
 	char *buf, *p;
-	int port;
+	int port, v;
 	ushort *sp;
 	ulong *lp;
 	vlong *vp;
@@ -407,6 +409,19 @@
 				error(Ebadarg);
 		return n;
 
+	case Qec:
+		if(offset >= 256)
+			error(Ebadarg);
+		if(offset+n > 256)
+			n = 256 - offset;
+		p = a;
+		for(port = offset; port < offset+n; port++){
+			if((v = ecread(port)) < 0)
+				error(Eio);
+			*p++ = v;
+		}
+		return n;
+
 	case Qioalloc:
 		break;
 
@@ -484,6 +499,15 @@
 		for(port = offset; port < offset+n; port += 8)
 			if(wrmsr(port, *vp++) < 0)
 				error(Ebadarg);
+		return n;
+
+	case Qec:
+		if(offset+n > 256)
+			error(Ebadarg);
+		p = a;
+		for(port = offset; port < offset+n; port++)
+			if(ecwrite(port, *p++) < 0)
+				error(Eio);
 		return n;
 
 	default:
--- /dev/null
+++ b/sys/src/9/pc/ec.c
@@ -1,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;
+}
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -30,6 +30,9 @@
 #define DMALOOP 2
 long	dmasetup(int, void*, long, int);
 void	dumpmcregs(void);
+int	ecinit(int cmdport, int dataport);
+int	ecread(uchar addr);
+int	ecwrite(uchar addr, uchar val);
 #define	evenaddr(x)				/* x86 doesn't care */
 void	fpclear(void);
 void	fpenv(FPsave*);
--- a/sys/src/9/pc/pccpuf
+++ b/sys/src/9/pc/pccpuf
@@ -85,6 +85,7 @@
 	archacpi	mp apic squidboy
 	archmp		mp apic squidboy
 	mtrr
+	ec
 
 	uarti8250
 	uartisa
--- a/sys/src/9/pc/pcf
+++ b/sys/src/9/pc/pcf
@@ -87,6 +87,7 @@
 	archacpi	mp apic squidboy
 	archmp		mp apic squidboy
 	mtrr
+	ec
 
 	sdaoe
 	sdide		pci sdscsi
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -30,6 +30,9 @@
 #define DMALOOP 2
 long	dmasetup(int, void*, long, int);
 void	dumpmcregs(void);
+int	ecinit(int cmdport, int dataport);
+int	ecread(uchar addr);
+int	ecwrite(uchar addr, uchar val);
 #define	evenaddr(x)				/* x86 doesn't care */
 void	(*fprestore)(FPsave*);
 void	(*fpsave)(FPsave*);
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -85,6 +85,7 @@
 	archacpi	mp apic squidboy
 	archmp		mp apic squidboy
 	mtrr
+	ec
 
 #	sdaoe
 	sdide		pci sdscsi