diff options
author | gonzo <gonzo@FreeBSD.org> | 2015-01-25 23:58:34 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2015-01-25 23:58:34 +0000 |
commit | b09edd53c954af35a87f8a2240c50eff7397978b (patch) | |
tree | fb6d42f29e756504fc10e3dae2d514ee5fb52195 /sys/arm | |
parent | 588a6eb29f37c0081497dc155776215a84099f02 (diff) | |
download | FreeBSD-src-b09edd53c954af35a87f8a2240c50eff7397978b.zip FreeBSD-src-b09edd53c954af35a87f8a2240c50eff7397978b.tar.gz |
- Increase default i2c bus timeout to 5 seconds from 1 second. Sometimes
1 second is not enugh for TDA19988 HDMI framer (e.g. on Beaglebone Black)
- Add per-device i2c_timout sysctl (dev.iichb.X.i2c_timeout) to control
I2C bus timeout manually
- Pass softc instead of device_t to all sysctl handlers
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/ti/ti_i2c.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 0da338e..ad688f3 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -95,6 +95,7 @@ struct ti_i2c_softc int sc_buffer_pos; int sc_error; int sc_fifo_trsh; + int sc_timeout; uint16_t sc_con_reg; uint16_t sc_rev; @@ -442,7 +443,7 @@ ti_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) ti_i2c_write_2(sc, I2C_REG_CON, reg); /* Wait for an event. */ - err = mtx_sleep(sc, &sc->sc_mtx, 0, "i2ciowait", hz); + err = mtx_sleep(sc, &sc->sc_mtx, 0, "i2ciowait", sc->sc_timeout); if (err == 0) err = sc->sc_error; @@ -761,12 +762,10 @@ ti_i2c_deactivate(device_t dev) static int ti_i2c_sysctl_clk(SYSCTL_HANDLER_ARGS) { - device_t dev; int clk, psc, sclh, scll; struct ti_i2c_softc *sc; - dev = (device_t)arg1; - sc = device_get_softc(dev); + sc = arg1; TI_I2C_LOCK(sc); /* Get the system prescaler value. */ @@ -783,6 +782,34 @@ ti_i2c_sysctl_clk(SYSCTL_HANDLER_ARGS) } static int +ti_i2c_sysctl_timeout(SYSCTL_HANDLER_ARGS) +{ + struct ti_i2c_softc *sc; + unsigned int val; + int err; + + sc = arg1; + + /* + * MTX_DEF lock can't be held while doing uimove in + * sysctl_handle_int + */ + TI_I2C_LOCK(sc); + val = sc->sc_timeout; + TI_I2C_UNLOCK(sc); + + err = sysctl_handle_int(oidp, &val, 0, req); + /* Write request? */ + if ((err == 0) && (req->newptr != NULL)) { + TI_I2C_LOCK(sc); + sc->sc_timeout = val; + TI_I2C_UNLOCK(sc); + } + + return (err); +} + +static int ti_i2c_probe(device_t dev) { @@ -858,12 +885,19 @@ ti_i2c_attach(device_t dev) /* Set the FIFO threshold to 5 for now. */ sc->sc_fifo_trsh = 5; + /* Set I2C bus timeout */ + sc->sc_timeout = 5*hz; + ctx = device_get_sysctl_ctx(dev); tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "i2c_clock", - CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0, + CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0, ti_i2c_sysctl_clk, "IU", "I2C bus clock"); + SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "i2c_timeout", + CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0, + ti_i2c_sysctl_timeout, "IU", "I2C bus timeout (in ticks)"); + /* Activate the interrupt. */ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_i2c_intr, sc, &sc->sc_irq_h); |