diff --git a/sys/dev/pci/amdpm.c b/sys/dev/pci/amdpm.c index 00fd8c9f377f..d4e177174eb9 100644 --- a/sys/dev/pci/amdpm.c +++ b/sys/dev/pci/amdpm.c @@ -1,4 +1,4 @@ -/* $NetBSD: amdpm.c,v 1.24 2007/01/06 20:25:01 jmcneill Exp $ */ +/* $NetBSD: amdpm.c,v 1.25 2007/02/05 23:38:15 jmcneill Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: amdpm.c,v 1.24 2007/01/06 20:25:01 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: amdpm.c,v 1.25 2007/02/05 23:38:15 jmcneill Exp $"); #include "opt_amdpm.h" @@ -115,6 +115,7 @@ amdpm_attach(struct device *parent, struct device *self, void *aux) sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; sc->sc_iot = pa->pa_iot; + sc->sc_pa = pa; #if 0 aprint_normal("%s: ", sc->sc_dev.dv_xname); @@ -169,8 +170,9 @@ amdpm_attach(struct device *parent, struct device *self, void *aux) /* try to attach devices on the smbus */ if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC8111_ACPI || - sc->sc_nforce) + sc->sc_nforce) { amdpm_smbus_attach(sc); + } if (confreg & AMDPM_RNGEN) { /* Check to see if we can read data from the RNG. */ diff --git a/sys/dev/pci/amdpm_smbus.c b/sys/dev/pci/amdpm_smbus.c index 5d2fc55b8051..3d9144d6308c 100644 --- a/sys/dev/pci/amdpm_smbus.c +++ b/sys/dev/pci/amdpm_smbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: amdpm_smbus.c,v 1.9 2007/01/06 02:16:22 jmcneill Exp $ */ +/* $NetBSD: amdpm_smbus.c,v 1.10 2007/02/05 23:38:15 jmcneill Exp $ */ /* * Copyright (c) 2005 Anil Gopinath (anil_public@yahoo.com) @@ -32,7 +32,7 @@ * AMD-8111 HyperTransport I/O Hub */ #include -__KERNEL_RCSID(0, "$NetBSD: amdpm_smbus.c,v 1.9 2007/01/06 02:16:22 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: amdpm_smbus.c,v 1.10 2007/02/05 23:38:15 jmcneill Exp $"); #include #include @@ -51,24 +51,35 @@ __KERNEL_RCSID(0, "$NetBSD: amdpm_smbus.c,v 1.9 2007/01/06 02:16:22 jmcneill Exp #include +#ifdef __i386__ +#include "opt_xbox.h" +#endif + +#ifdef XBOX +extern int arch_i386_is_xbox; +#endif + static int amdpm_smbus_acquire_bus(void *cookie, int flags); static void amdpm_smbus_release_bus(void *cookie, int flags); static int amdpm_smbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, size_t cmdlen, void *vbuf, size_t buflen, int flags); -static int amdpm_smbus_check_done(struct amdpm_softc *sc); +static int amdpm_smbus_check_done(struct amdpm_softc *sc, i2c_op_t op); static void amdpm_smbus_clear_gsr(struct amdpm_softc *sc); static u_int16_t amdpm_smbus_get_gsr(struct amdpm_softc *sc); -static int amdpm_smbus_send_1(struct amdpm_softc *sc, u_int8_t val); -static int amdpm_smbus_write_1(struct amdpm_softc *sc, u_int8_t cmd, u_int8_t data); -static int amdpm_smbus_receive_1(struct amdpm_softc *sc); -static int amdpm_smbus_read_1(struct amdpm_softc *sc, u_int8_t cmd); +static int amdpm_smbus_send_1(struct amdpm_softc *sc, u_int8_t val, i2c_op_t op); +static int amdpm_smbus_write_1(struct amdpm_softc *sc, u_int8_t cmd, u_int8_t data, i2c_op_t op); +static int amdpm_smbus_receive_1(struct amdpm_softc *sc, i2c_op_t op); +static int amdpm_smbus_read_1(struct amdpm_softc *sc, u_int8_t cmd, i2c_op_t op); +static int amdpm_smbus_intr(void *); void amdpm_smbus_attach(struct amdpm_softc *sc) { struct i2cbus_attach_args iba; + pci_intr_handle_t ih; + const char *intrstr; /* register with iic */ sc->sc_i2c.ic_cookie = sc; @@ -83,10 +94,58 @@ amdpm_smbus_attach(struct amdpm_softc *sc) lockinit(&sc->sc_lock, PZERO, "amdpm_smbus", 0, 0); +#ifdef XBOX +#define XBOX_SMBA 0x8000 +#define XBOX_SMSIZE 256 +#define XBOX_INTRLINE 12 + /* XXX pci0 dev 1 function 2 "System Management" doesn't probe */ + if (arch_i386_is_xbox) { + sc->sc_pa->pa_intrline = XBOX_INTRLINE; + + if (bus_space_map(sc->sc_iot, XBOX_SMBA, XBOX_SMSIZE, + 0, &sc->sc_sm_ioh) == 0) + aprint_normal("%s: system management at 0x%04x\n", + sc->sc_dev.dv_xname, XBOX_SMBA); + + } + + if (pci_intr_map(sc->sc_pa, &ih)) + aprint_error("%s: couldn't map interrupt\n", + sc->sc_dev.dv_xname); + else { + intrstr = pci_intr_string(sc->sc_pc, ih); + sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO, + amdpm_smbus_intr, sc); + if (sc->sc_ih != NULL) + aprint_normal("%s: interrupting at %s\n", + sc->sc_dev.dv_xname, intrstr); + } +#endif + iba.iba_tag = &sc->sc_i2c; (void) config_found_ia(&sc->sc_dev, "i2cbus", &iba, iicbus_print); } +static int +amdpm_smbus_intr(void *cookie) +{ +#ifdef XBOX + struct amdpm_softc *sc; + uint32_t status; + + sc = (struct amdpm_softc *)cookie; + + if (arch_i386_is_xbox) { + status = bus_space_read_4(sc->sc_iot, sc->sc_sm_ioh, 0x20); + bus_space_write_4(sc->sc_iot, sc->sc_sm_ioh, 0x20, status); + + if (status & 2) + return iic_smbus_intr(&sc->sc_i2c); + } +#endif + return 0; +} + static int amdpm_smbus_acquire_bus(void *cookie, int flags) { @@ -118,7 +177,7 @@ amdpm_smbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, int rv; if (I2C_OP_READ_P(op) && (cmdlen == 0) && (buflen == 1)) { - rv = amdpm_smbus_receive_1(sc); + rv = amdpm_smbus_receive_1(sc, op); if (rv == -1) return -1; *p = (u_int8_t)rv; @@ -126,7 +185,7 @@ amdpm_smbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, } if ( (I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) { - rv = amdpm_smbus_read_1(sc, *(const uint8_t*)cmd); + rv = amdpm_smbus_read_1(sc, *(const uint8_t*)cmd, op); if (rv == -1) return -1; *p = (u_int8_t)rv; @@ -134,18 +193,18 @@ amdpm_smbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, } if ( (I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) { - return amdpm_smbus_send_1(sc, *(uint8_t*)vbuf); + return amdpm_smbus_send_1(sc, *(uint8_t*)vbuf, op); } if ( (I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) { - return amdpm_smbus_write_1(sc, *(const uint8_t*)cmd, *(uint8_t*)vbuf); + return amdpm_smbus_write_1(sc, *(const uint8_t*)cmd, *(uint8_t*)vbuf, op); } return (-1); } static int -amdpm_smbus_check_done(struct amdpm_softc *sc) +amdpm_smbus_check_done(struct amdpm_softc *sc, i2c_op_t op) { int i = 0; for (i = 0; i < 1000; i++) { @@ -154,7 +213,8 @@ amdpm_smbus_check_done(struct amdpm_softc *sc) if (data & AMDPM_8111_GSR_CYCLE_DONE) { return (0); } - delay(1); + if (!(op & I2C_F_POLL)) + delay(1); } return (-1); } @@ -179,7 +239,7 @@ amdpm_smbus_get_gsr(struct amdpm_softc *sc) } static int -amdpm_smbus_send_1(struct amdpm_softc *sc, u_int8_t val) +amdpm_smbus_send_1(struct amdpm_softc *sc, u_int8_t val, i2c_op_t op) { u_int16_t data = 0; int off = (sc->sc_nforce ? 0xe0 : 0); @@ -203,12 +263,12 @@ amdpm_smbus_send_1(struct amdpm_softc *sc, u_int8_t val) AMDPM_8111_SMBUS_CTRL - off, AMDPM_8111_SMBUS_GSR_SB); - return(amdpm_smbus_check_done(sc)); + return(amdpm_smbus_check_done(sc, op)); } static int -amdpm_smbus_write_1(struct amdpm_softc *sc, u_int8_t cmd, u_int8_t val) +amdpm_smbus_write_1(struct amdpm_softc *sc, u_int8_t cmd, u_int8_t val, i2c_op_t op) { u_int16_t data = 0; int off = (sc->sc_nforce ? 0xe0 : 0); @@ -233,11 +293,11 @@ amdpm_smbus_write_1(struct amdpm_softc *sc, u_int8_t cmd, u_int8_t val) bus_space_write_2(sc->sc_iot, sc->sc_ioh, AMDPM_8111_SMBUS_CTRL - off, AMDPM_8111_SMBUS_GSR_WB); - return (amdpm_smbus_check_done(sc)); + return (amdpm_smbus_check_done(sc, op)); } static int -amdpm_smbus_receive_1(struct amdpm_softc *sc) +amdpm_smbus_receive_1(struct amdpm_softc *sc, i2c_op_t op) { u_int16_t data = 0; int off = (sc->sc_nforce ? 0xe0 : 0); @@ -257,7 +317,7 @@ amdpm_smbus_receive_1(struct amdpm_softc *sc) AMDPM_8111_SMBUS_CTRL - off, AMDPM_8111_SMBUS_GSR_RXB); /* check for errors */ - if (amdpm_smbus_check_done(sc) < 0) + if (amdpm_smbus_check_done(sc, op) < 0) return (-1); /* read data */ @@ -268,7 +328,7 @@ amdpm_smbus_receive_1(struct amdpm_softc *sc) } static int -amdpm_smbus_read_1(struct amdpm_softc *sc, u_int8_t cmd) +amdpm_smbus_read_1(struct amdpm_softc *sc, u_int8_t cmd, i2c_op_t op) { u_int16_t data = 0; u_int8_t ret; @@ -292,7 +352,7 @@ amdpm_smbus_read_1(struct amdpm_softc *sc, u_int8_t cmd) AMDPM_8111_SMBUS_CTRL - off, AMDPM_8111_SMBUS_GSR_RB); /* check for errors */ - if (amdpm_smbus_check_done(sc) < 0) + if (amdpm_smbus_check_done(sc, op) < 0) return (-1); /* store data */ diff --git a/sys/dev/pci/amdpmvar.h b/sys/dev/pci/amdpmvar.h index 75c49ec7ae8a..d6af6978c5e0 100644 --- a/sys/dev/pci/amdpmvar.h +++ b/sys/dev/pci/amdpmvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: amdpmvar.h,v 1.3 2007/01/06 00:14:21 jmcneill Exp $ */ +/* $NetBSD: amdpmvar.h,v 1.4 2007/02/05 23:38:15 jmcneill Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -46,14 +46,18 @@ struct amdpm_softc { pci_chipset_tag_t sc_pc; pcitag_t sc_tag; + struct pci_attach_args *sc_pa; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; /* PMxx space */ + bus_space_handle_t sc_sm_ioh; /* SM space */ i2c_addr_t sc_smbus_slaveaddr; /* address of smbus slave */ struct i2c_controller sc_i2c; /* i2c controller info */ struct lock sc_lock; + void *sc_ih; + struct callout sc_rnd_ch; rndsource_element_t sc_rnd_source; #ifdef AMDPM_RND_COUNTERS