diff options
-rw-r--r-- | sys/arch/macppc/conf/files.macppc | 9 | ||||
-rw-r--r-- | sys/arch/macppc/dev/adb.c | 17 | ||||
-rw-r--r-- | sys/arch/macppc/dev/pi2c.c | 148 | ||||
-rw-r--r-- | sys/arch/macppc/dev/pm_direct.h | 9 |
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 |