int iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, int how) { device_t bus; int error; bus = device_get_parent(dev); error = iicbus_request_bus(bus, dev, how); if (error == 0) error = IICBUS_TRANSFER(bus, msgs, nmsgs); iicbus_release_bus(bus, dev); return (error); }
static int gmbus_xfer(device_t adapter, struct iic_msg *msgs, uint32_t num) { struct intel_iic_softc *sc = device_get_softc(adapter); struct intel_gmbus *bus = sc->bus; struct drm_i915_private *dev_priv = bus->dev_priv; int i, reg_offset; int ret = 0; sx_xlock(&dev_priv->gmbus_mutex); if (bus->force_bit) { ret = -IICBUS_TRANSFER(bus->bbbus, msgs, num); goto out; } reg_offset = dev_priv->gpio_mmio_base; I915_WRITE(GMBUS0 + reg_offset, bus->reg0); for (i = 0; i < num; i++) { u32 gmbus2; if (gmbus_is_index_read(msgs, i, num)) { ret = gmbus_xfer_index_read(dev_priv, &msgs[i]); i += 1; /* set i to the index of the read xfer */ } else if (msgs[i].flags & I2C_M_RD) { ret = gmbus_xfer_read(dev_priv, &msgs[i], 0); } else { ret = gmbus_xfer_write(dev_priv, &msgs[i]); } if (ret == -ETIMEDOUT) goto timeout; if (ret == -ENXIO) goto clear_err; ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50); if (ret) goto timeout; if (gmbus2 & GMBUS_SATOER) goto clear_err; } /* Generate a STOP condition on the bus. Note that gmbus can't generata * a STOP on the very first cycle. To simplify the code we * unconditionally generate the STOP condition with an additional gmbus * cycle. */ I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_STOP | GMBUS_SW_RDY); /* Mark the GMBUS interface as disabled after waiting for idle. * We will re-enable it at the start of the next xfer, * till then let it sleep. */ if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) { DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n", device_get_desc(adapter)); ret = -ETIMEDOUT; } I915_WRITE(GMBUS0 + reg_offset, 0); goto out; clear_err: /* * Wait for bus to IDLE before clearing NAK. * If we clear the NAK while bus is still active, then it will stay * active and the next transaction may fail. * * If no ACK is received during the address phase of a transaction, the * adapter must report -ENXIO. It is not clear what to return if no ACK * is received at other times. But we have to be careful to not return * spurious -ENXIO because that will prevent i2c and drm edid functions * from retrying. So return -ENXIO only when gmbus properly quiescents - * timing out seems to happen when there _is_ a ddc chip present, but * it's slow responding and only answers on the 2nd retry. */ ret = -ENXIO; if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) { DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n", device_get_desc(adapter)); ret = -ETIMEDOUT; } /* Toggle the Software Clear Interrupt bit. This has the effect * of resetting the GMBUS controller and so clearing the * BUS_ERROR raised by the slave's NAK. */ I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); I915_WRITE(GMBUS1 + reg_offset, 0); I915_WRITE(GMBUS0 + reg_offset, 0); DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n", device_get_desc(adapter), msgs[i].slave >> 1, (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len); goto out; timeout: DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", device_get_desc(adapter), bus->reg0 & 0xff); I915_WRITE(GMBUS0 + reg_offset, 0); /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ bus->force_bit = 1; ret = -IICBUS_TRANSFER(bus->bbbus, msgs, num); out: sx_xunlock(&dev_priv->gmbus_mutex); return -ret; }
/* * iicbus_transfer() * * Do an aribtrary number of transfers on the iicbus. We pass these * raw requests to the bridge driver. If the bridge driver supports * them directly, then it manages all the details. If not, it can use * the helper function iicbus_transfer_gen() which will do the * transfers at a low level. * * Pointers passed in as part of iic_msg must be kernel pointers. * Callers that have user addresses to manage must do so on their own. */ int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) { return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs)); }