Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
/*
 * 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));
}