version 1.33, 2010/07/27 05:29:05 |
version 1.33.2.1, 2011/06/06 09:08:25 |
Line 49 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 49 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define DPRINTF(x) |
#define DPRINTF(x) |
#endif |
#endif |
|
|
|
#define PIIXPM_IS_CSB5(id) \ |
|
(PCI_VENDOR((id)) == PCI_VENDOR_SERVERWORKS && \ |
|
PCI_PRODUCT((id)) == PCI_PRODUCT_SERVERWORKS_CSB5) |
#define PIIXPM_DELAY 200 |
#define PIIXPM_DELAY 200 |
#define PIIXPM_TIMEOUT 1 |
#define PIIXPM_TIMEOUT 1 |
|
|
Line 65 struct piixpm_softc { |
|
Line 68 struct piixpm_softc { |
|
|
|
pci_chipset_tag_t sc_pc; |
pci_chipset_tag_t sc_pc; |
pcitag_t sc_pcitag; |
pcitag_t sc_pcitag; |
|
pcireg_t sc_id; |
|
|
struct i2c_controller sc_i2c_tag; |
struct i2c_controller sc_i2c_tag; |
krwlock_t sc_i2c_rwlock; |
krwlock_t sc_i2c_rwlock; |
Line 85 static void piixpm_attach(device_t, devi |
|
Line 89 static void piixpm_attach(device_t, devi |
|
static bool piixpm_suspend(device_t, const pmf_qual_t *); |
static bool piixpm_suspend(device_t, const pmf_qual_t *); |
static bool piixpm_resume(device_t, const pmf_qual_t *); |
static bool piixpm_resume(device_t, const pmf_qual_t *); |
|
|
|
static void piixpm_csb5_reset(void *); |
static int piixpm_i2c_acquire_bus(void *, int); |
static int piixpm_i2c_acquire_bus(void *, int); |
static void piixpm_i2c_release_bus(void *, int); |
static void piixpm_i2c_release_bus(void *, int); |
static int piixpm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, |
static int piixpm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, |
Line 144 piixpm_attach(device_t parent, device_t |
|
Line 149 piixpm_attach(device_t parent, device_t |
|
const char *intrstr = NULL; |
const char *intrstr = NULL; |
|
|
sc->sc_dev = self; |
sc->sc_dev = self; |
|
sc->sc_id = pa->pa_id; |
sc->sc_pc = pa->pa_pc; |
sc->sc_pc = pa->pa_pc; |
sc->sc_pcitag = pa->pa_tag; |
sc->sc_pcitag = pa->pa_tag; |
|
|
Line 266 piixpm_resume(device_t dv, const pmf_qua |
|
Line 272 piixpm_resume(device_t dv, const pmf_qua |
|
return true; |
return true; |
} |
} |
|
|
|
static void |
|
piixpm_csb5_reset(void *arg) |
|
{ |
|
struct piixpm_softc *sc = arg; |
|
pcireg_t base, hostc, pmbase; |
|
|
|
base = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PIIX_SMB_BASE); |
|
hostc = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PIIX_SMB_HOSTC); |
|
|
|
pmbase = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PIIX_PM_BASE); |
|
pmbase |= PIIX_PM_BASE_CSB5_RESET; |
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_PM_BASE, pmbase); |
|
pmbase &= ~PIIX_PM_BASE_CSB5_RESET; |
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_PM_BASE, pmbase); |
|
|
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_SMB_BASE, base); |
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_SMB_HOSTC, hostc); |
|
|
|
(void) tsleep(&sc, PRIBIO, "csb5reset", hz/2); |
|
} |
|
|
static int |
static int |
piixpm_i2c_acquire_bus(void *cookie, int flags) |
piixpm_i2c_acquire_bus(void *cookie, int flags) |
{ |
{ |
Line 316 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 343 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
if (cold || sc->sc_poll) |
if (cold || sc->sc_poll) |
flags |= I2C_F_POLL; |
flags |= I2C_F_POLL; |
|
|
if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2) |
if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2 || |
|
(cmdlen == 0 && len > 1)) |
return (1); |
return (1); |
|
|
/* Setup transfer */ |
/* Setup transfer */ |
Line 340 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 368 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
if (I2C_OP_WRITE_P(op)) { |
if (I2C_OP_WRITE_P(op)) { |
/* Write data */ |
/* Write data */ |
b = buf; |
b = buf; |
if (len > 0) |
if (cmdlen == 0 && len == 1) |
|
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
|
PIIX_SMB_HCMD, b[0]); |
|
else if (len > 0) |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HD0, b[0]); |
PIIX_SMB_HD0, b[0]); |
if (len > 1) |
if (len > 1) |
Line 349 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 380 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
} |
} |
|
|
/* Set SMBus command */ |
/* Set SMBus command */ |
if (len == 0) { |
if (cmdlen == 0) { |
if (cmdlen == 0) |
if (len == 0) |
ctl = PIIX_SMB_HC_CMD_QUICK; |
ctl = PIIX_SMB_HC_CMD_QUICK; |
else |
else |
ctl = PIIX_SMB_HC_CMD_BYTE; |
ctl = PIIX_SMB_HC_CMD_BYTE; |
Line 368 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 399 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
|
|
if (flags & I2C_F_POLL) { |
if (flags & I2C_F_POLL) { |
/* Poll for completion */ |
/* Poll for completion */ |
DELAY(PIIXPM_DELAY); |
if (PIIXPM_IS_CSB5(sc->sc_id)) |
|
DELAY(2*PIIXPM_DELAY); |
|
else |
|
DELAY(PIIXPM_DELAY); |
for (retries = 1000; retries > 0; retries--) { |
for (retries = 1000; retries > 0; retries--) { |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HS); |
PIIX_SMB_HS); |
|
|
if ((st & PIIX_SMB_HS_FAILED) == 0) |
if ((st & PIIX_SMB_HS_FAILED) == 0) |
aprint_error_dev(sc->sc_dev, "transaction abort failed, status 0x%x\n", st); |
aprint_error_dev(sc->sc_dev, "transaction abort failed, status 0x%x\n", st); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, st); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, st); |
|
/* |
|
* CSB5 needs hard reset to unlock the smbus after timeout. |
|
*/ |
|
if (PIIXPM_IS_CSB5(sc->sc_id)) |
|
piixpm_csb5_reset(sc); |
return (1); |
return (1); |
} |
} |
|
|