Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/ichiic/ig4_iic.c
Show First 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
set_controller(ig4iic_softc_t *sc, uint32_t ctl) | set_controller(ig4iic_softc_t *sc, uint32_t ctl) | ||||
{ | { | ||||
int retry; | int retry; | ||||
int error; | int error; | ||||
uint32_t v; | uint32_t v; | ||||
/* | |||||
* When the controller is enabled, interrupt on STOP detect | |||||
* or receive character ready and clear pending interrupts. | |||||
*/ | |||||
if (ctl & IG4_I2C_ENABLE) { | |||||
reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | | |||||
IG4_INTR_RX_FULL); | |||||
reg_read(sc, IG4_REG_CLR_INTR); | |||||
} else | |||||
reg_write(sc, IG4_REG_INTR_MASK, 0); | |||||
reg_write(sc, IG4_REG_I2C_EN, ctl); | reg_write(sc, IG4_REG_I2C_EN, ctl); | ||||
error = SMB_ETIMEOUT; | error = SMB_ETIMEOUT; | ||||
for (retry = 100; retry > 0; --retry) { | for (retry = 100; retry > 0; --retry) { | ||||
v = reg_read(sc, IG4_REG_ENABLE_STATUS); | v = reg_read(sc, IG4_REG_ENABLE_STATUS); | ||||
if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) { | if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) { | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 429 Lines • ▼ Show 20 Lines | |||||
#if 0 | #if 0 | ||||
/* | /* | ||||
* Don't do this, it blows up the PCI config | * Don't do this, it blows up the PCI config | ||||
*/ | */ | ||||
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); | reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); | ||||
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); | reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); | ||||
#endif | #endif | ||||
/* | |||||
* Interrupt on STOP detect or receive character ready | |||||
*/ | |||||
reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | | |||||
IG4_INTR_RX_FULL); | |||||
mtx_lock(&sc->io_lock); | mtx_lock(&sc->io_lock); | ||||
if (set_controller(sc, 0)) | if (set_controller(sc, 0)) | ||||
device_printf(sc->dev, "controller error during attach-1\n"); | device_printf(sc->dev, "controller error during attach-1\n"); | ||||
if (set_controller(sc, IG4_I2C_ENABLE)) | if (set_controller(sc, IG4_I2C_ENABLE)) | ||||
device_printf(sc->dev, "controller error during attach-2\n"); | device_printf(sc->dev, "controller error during attach-2\n"); | ||||
mtx_unlock(&sc->io_lock); | mtx_unlock(&sc->io_lock); | ||||
error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, | error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, | ||||
NULL, ig4iic_intr, sc, &sc->intr_handle); | NULL, ig4iic_intr, sc, &sc->intr_handle); | ||||
if (error) { | if (error) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"Unable to setup irq: error %d\n", error); | "Unable to setup irq: error %d\n", error); | ||||
} | } | ||||
sc->enum_hook.ich_func = ig4iic_start; | sc->enum_hook.ich_func = ig4iic_start; | ||||
sc->enum_hook.ich_arg = sc->dev; | sc->enum_hook.ich_arg = sc->dev; | ||||
/* We have to wait until interrupts are enabled. I2C read and write | /* | ||||
* We have to wait until interrupts are enabled. I2C read and write | |||||
* only works if the interrupts are available. | * only works if the interrupts are available. | ||||
*/ | */ | ||||
if (config_intrhook_establish(&sc->enum_hook) != 0) | if (config_intrhook_establish(&sc->enum_hook) != 0) | ||||
error = ENOMEM; | error = ENOMEM; | ||||
else | else | ||||
error = 0; | error = 0; | ||||
done: | done: | ||||
Show All 37 Lines | if (sc->intr_handle) | ||||
bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); | bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); | ||||
sx_xlock(&sc->call_lock); | sx_xlock(&sc->call_lock); | ||||
mtx_lock(&sc->io_lock); | mtx_lock(&sc->io_lock); | ||||
sc->smb = NULL; | sc->smb = NULL; | ||||
sc->intr_handle = NULL; | sc->intr_handle = NULL; | ||||
reg_write(sc, IG4_REG_INTR_MASK, 0); | reg_write(sc, IG4_REG_INTR_MASK, 0); | ||||
reg_read(sc, IG4_REG_CLR_INTR); | |||||
set_controller(sc, 0); | set_controller(sc, 0); | ||||
mtx_unlock(&sc->io_lock); | mtx_unlock(&sc->io_lock); | ||||
sx_xunlock(&sc->call_lock); | sx_xunlock(&sc->call_lock); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
ig4iic_intr(void *cookie) | ig4iic_intr(void *cookie) | ||||
{ | { | ||||
ig4iic_softc_t *sc = cookie; | ig4iic_softc_t *sc = cookie; | ||||
uint32_t status; | uint32_t status; | ||||
mtx_lock(&sc->io_lock); | mtx_lock(&sc->io_lock); | ||||
/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/ | /* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/ | ||||
reg_read(sc, IG4_REG_CLR_INTR); | |||||
status = reg_read(sc, IG4_REG_I2C_STA); | status = reg_read(sc, IG4_REG_I2C_STA); | ||||
while (status & IG4_STATUS_RX_NOTEMPTY) { | while (status & IG4_STATUS_RX_NOTEMPTY) { | ||||
sc->rbuf[sc->rnext & IG4_RBUFMASK] = | sc->rbuf[sc->rnext & IG4_RBUFMASK] = | ||||
(uint8_t)reg_read(sc, IG4_REG_DATA_CMD); | (uint8_t)reg_read(sc, IG4_REG_DATA_CMD); | ||||
++sc->rnext; | ++sc->rnext; | ||||
status = reg_read(sc, IG4_REG_I2C_STA); | status = reg_read(sc, IG4_REG_I2C_STA); | ||||
} | } | ||||
reg_read(sc, IG4_REG_CLR_INTR); | |||||
wakeup(sc); | wakeup(sc); | ||||
mtx_unlock(&sc->io_lock); | mtx_unlock(&sc->io_lock); | ||||
} | } | ||||
#define REGDUMP(sc, reg) \ | #define REGDUMP(sc, reg) \ | ||||
device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg)) | device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg)) | ||||
static void | static void | ||||
Show All 38 Lines |