summaryrefslogtreecommitdiff
path: root/sys/arch/macppc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/macppc')
-rw-r--r--sys/arch/macppc/conf/files.macppc9
-rw-r--r--sys/arch/macppc/dev/adb.c17
-rw-r--r--sys/arch/macppc/dev/pi2c.c148
-rw-r--r--sys/arch/macppc/dev/pm_direct.h9
4 files changed, 179 insertions, 4 deletions
diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc
index 67f9537d5ff..922d76e5123 100644
--- a/sys/arch/macppc/conf/files.macppc
+++ b/sys/arch/macppc/conf/files.macppc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.macppc,v 1.38 2005/11/16 03:43:40 deraadt Exp $
+# $OpenBSD: files.macppc,v 1.39 2005/11/16 12:28:54 kettenis Exp $
#
# macppc-specific configuration info
@@ -194,6 +194,11 @@ attach ki2c at macobio
attach ki2c at memc with ki2c_memc
file arch/macppc/dev/ki2c.c ki2c
+# PMU I2C
+device pi2c {}
+attach pi2c at adb
+file arch/macppc/dev/pi2c.c pi2c
+
# I2S
define i2s
file arch/macppc/dev/i2s.c i2s
@@ -267,7 +272,7 @@ include "dev/usb/files.usb"
include "dev/i2c/files.i2c"
device maciic {} : i2c
-attach maciic at ki2c, smu
+attach maciic at ki2c, pi2c, smu
file arch/macppc/dev/maci2c.c maciic
#
diff --git a/sys/arch/macppc/dev/adb.c b/sys/arch/macppc/dev/adb.c
index dc57bf8c823..f28dff44802 100644
--- a/sys/arch/macppc/dev/adb.c
+++ b/sys/arch/macppc/dev/adb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: adb.c,v 1.13 2005/10/21 22:07:45 kettenis Exp $ */
+/* $OpenBSD: adb.c,v 1.14 2005/11/16 12:28:54 kettenis Exp $ */
/* $NetBSD: adb.c,v 1.6 1999/08/16 06:28:09 tsubai Exp $ */
/*-
@@ -41,6 +41,7 @@
#include <sys/systm.h>
#include <machine/autoconf.h>
+#include <dev/ofw/openfirm.h>
#include <macppc/dev/adbvar.h>
#include <macppc/dev/akbdvar.h>
@@ -99,6 +100,9 @@ adbattach(struct device *parent, struct device *self, void *aux)
{
struct adb_softc *sc = (struct adb_softc *)self;
struct confargs *ca = aux;
+ struct confargs nca;
+ char name[32];
+ int node;
ADBDataBlock adbdata;
struct adb_attach_args aa_args;
@@ -176,6 +180,17 @@ adbattach(struct device *parent, struct device *self, void *aux)
if (adbHardware == ADB_HW_CUDA)
adb_cuda_autopoll();
adb_polling = 0;
+
+ /* Attach I2C controller. */
+ for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
+ if (OF_getprop(node, "name", name, sizeof name) <= 0)
+ continue;
+ if (strcmp(name, "pmu-i2c") == 0) {
+ nca.ca_name = "pi2c";
+ nca.ca_node = node;
+ config_found(self, &nca, NULL);
+ }
+ }
}
int
diff --git a/sys/arch/macppc/dev/pi2c.c b/sys/arch/macppc/dev/pi2c.c
new file mode 100644
index 00000000000..cf2e55d2d0b
--- /dev/null
+++ b/sys/arch/macppc/dev/pi2c.c
@@ -0,0 +1,148 @@
+/* $OpenBSD: pi2c.c,v 1.1 2005/11/16 12:28:54 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2005 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#include <arch/macppc/dev/maci2cvar.h>
+#include <arch/macppc/dev/pm_direct.h>
+
+struct pi2c_softc {
+ struct device sc_dev;
+
+ struct lock sc_buslock;
+ struct i2c_controller sc_i2c_tag;
+};
+
+int pi2c_match(struct device *, void *, void *);
+void pi2c_attach(struct device *, struct device *, void *);
+
+struct cfattach pi2c_ca = {
+ sizeof(struct pi2c_softc), pi2c_match, pi2c_attach
+};
+
+struct cfdriver pi2c_cd = {
+ NULL, "pi2c", DV_DULL,
+};
+
+int pi2c_i2c_acquire_bus(void *, int);
+void pi2c_i2c_release_bus(void *, int);
+int pi2c_i2c_exec(void *, i2c_op_t, i2c_addr_t,
+ const void *, size_t, void *buf, size_t, int);
+
+int
+pi2c_match(struct device *parent, void *cf, void *aux)
+{
+ return (1);
+}
+
+void
+pi2c_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct pi2c_softc *sc = (struct pi2c_softc *)self;
+ struct confargs *ca = aux;
+ struct maci2cbus_attach_args iba;
+
+ printf("\n");
+
+ lockinit(&sc->sc_buslock, PZERO, sc->sc_dev.dv_xname, 0, 0);
+
+ sc->sc_i2c_tag.ic_cookie = sc;
+ sc->sc_i2c_tag.ic_acquire_bus = pi2c_i2c_acquire_bus;
+ sc->sc_i2c_tag.ic_release_bus = pi2c_i2c_release_bus;
+ sc->sc_i2c_tag.ic_exec = pi2c_i2c_exec;
+
+ iba.iba_node = ca->ca_node;
+ iba.iba_tag = &sc->sc_i2c_tag;
+ config_found(&sc->sc_dev, &iba, NULL);
+}
+
+int
+pi2c_i2c_acquire_bus(void *cookie, int flags)
+{
+ struct pi2c_softc *sc = cookie;
+
+ return (lockmgr(&sc->sc_buslock, LK_EXCLUSIVE, NULL, curproc));
+}
+
+void
+pi2c_i2c_release_bus(void *cookie, int flags)
+{
+ struct pi2c_softc *sc = cookie;
+
+ lockmgr(&sc->sc_buslock, LK_RELEASE, NULL, curproc);
+}
+
+int
+pi2c_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
+ const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
+{
+ u_int8_t pmu_op = PMU_I2C_NORMAL;
+ int retries = 10;
+ PMData p;
+
+ if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 5)
+ return (EINVAL);
+
+ if (cmdlen == 0)
+ pmu_op = PMU_I2C_SIMPLE;
+ else if (I2C_OP_READ_P(op))
+ pmu_op = PMU_I2C_COMBINED;
+
+ p.command = PMU_I2C;
+ p.num_data = 7 + len;
+ p.s_buf = p.r_buf = p.data;
+
+ p.data[0] = addr >> 7; /* bus number */
+ p.data[1] = pmu_op;
+ p.data[2] = 0;
+ p.data[3] = addr << 1;
+ p.data[4] = *(u_int8_t *)cmdbuf;
+ p.data[5] = addr << 1 | I2C_OP_READ_P(op);
+ p.data[6] = len;
+ memcpy(&p.data[7], buf, len);
+
+ if (pmgrop(&p))
+ return (EIO);
+
+ while (retries--) {
+ p.command = PMU_I2C;
+ p.num_data = 1;
+ p.s_buf = p.r_buf = p.data;
+ p.data[0] = 0;
+
+ if (pmgrop(&p))
+ return (EIO);
+
+ if (p.data[0] == 1)
+ break;
+
+ DELAY(10 * 1000);
+ }
+
+ if (I2C_OP_READ_P(op))
+ memcpy(buf, &p.data[1], len);
+ return (0);
+}
diff --git a/sys/arch/macppc/dev/pm_direct.h b/sys/arch/macppc/dev/pm_direct.h
index 065d518ecad..c3e4d3f238c 100644
--- a/sys/arch/macppc/dev/pm_direct.h
+++ b/sys/arch/macppc/dev/pm_direct.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pm_direct.h,v 1.6 2005/10/21 22:07:45 kettenis Exp $ */
+/* $OpenBSD: pm_direct.h,v 1.7 2005/11/16 12:28:54 kettenis Exp $ */
/* $NetBSD: pm_direct.h,v 1.5 1999/07/12 15:54:55 tsubai Exp $ */
/*
@@ -98,6 +98,8 @@ void pm_eject_pcmcia(int);
#define PMU_SMART_BATTERY_STATE 0x6f /* Read battery state */
+#define PMU_I2C 0x9a /* I2C */
+
/* Bits in PMU interrupt and interrupt mask bytes */
#define PMU_INT_ADB_AUTO 0x04 /* ADB autopoll, when PMU_INT_ADB */
#define PMU_INT_PCEJECT 0x04 /* PC-card eject buttons */
@@ -134,4 +136,9 @@ enum {
#define PMU_PWR_AC_PRESENT (1 << 0)
#define PMU_PWR_BATT_PRESENT (1 << 2)
+/* PMU I2C */
+#define PMU_I2C_SIMPLE 0x00
+#define PMU_I2C_NORMAL 0x01
+#define PMU_I2C_COMBINED 0x02
+
#endif