Commit 8ad95edc authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/i2c/gk110-: disable hw-initiated dpcd reads



RM does this around transactions, and it seemed to help while debugging
AUXCH issues on GA102.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent b5510d1e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3,6 +3,13 @@
#define __NVKM_I2C_AUX_H__
#include "pad.h"

static inline void
nvkm_i2c_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
{
	if (i2c->func->aux_autodpcd)
		i2c->func->aux_autodpcd(i2c, aux, false);
}

struct nvkm_i2c_aux_func {
	bool address_only;
	int  (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
+7 −3
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		 u8 type, u32 addr, u8 *data, u8 *size)
{
	struct g94_i2c_aux *aux = g94_i2c_aux(obj);
	struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
	struct nvkm_i2c *i2c = aux->base.pad->i2c;
	struct nvkm_device *device = i2c->subdev.device;
	const u32 base = aux->ch * 0x50;
	u32 ctrl, stat, timeout, retries = 0;
	u32 xbuf[4] = {};
@@ -96,6 +97,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		goto out;
	}

	nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);

	if (!(type & 1)) {
		memcpy(xbuf, data, *size);
		for (i = 0; i < 16; i += 4) {
@@ -128,7 +131,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
			if (!timeout--) {
				AUX_ERR(&aux->base, "timeout %08x", ctrl);
				ret = -EIO;
				goto out;
				goto out_err;
			}
		} while (ctrl & 0x00010000);
		ret = 0;
@@ -154,7 +157,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		memcpy(data, xbuf, *size);
		*size = stat & 0x0000001f;
	}

out_err:
	nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
out:
	g94_i2c_aux_fini(aux);
	return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
+7 −2
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		   u8 type, u32 addr, u8 *data, u8 *size)
{
	struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
	struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
	struct nvkm_i2c *i2c = aux->base.pad->i2c;
	struct nvkm_device *device = i2c->subdev.device;
	const u32 base = aux->ch * 0x50;
	u32 ctrl, stat, timeout, retries = 0;
	u32 xbuf[4] = {};
@@ -96,6 +97,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		goto out;
	}

	nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);

	if (!(type & 1)) {
		memcpy(xbuf, data, *size);
		for (i = 0; i < 16; i += 4) {
@@ -128,7 +131,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
			if (!timeout--) {
				AUX_ERR(&aux->base, "timeout %08x", ctrl);
				ret = -EIO;
				goto out;
				goto out_err;
			}
		} while (ctrl & 0x00010000);
		ret = 0;
@@ -155,6 +158,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
		*size = stat & 0x0000001f;
	}

out_err:
	nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
out:
	gm200_i2c_aux_fini(aux);
	return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
+7 −0
Original line number Diff line number Diff line
@@ -22,6 +22,12 @@
#include "priv.h"
#include "pad.h"

static void
gk110_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
{
	nvkm_mask(i2c->subdev.device, 0x00e4f8 + (aux * 0x50), 0x00010000, enable << 16);
}

static const struct nvkm_i2c_func
gk110_i2c = {
	.pad_x_new = gf119_i2c_pad_x_new,
@@ -29,6 +35,7 @@ gk110_i2c = {
	.aux = 4,
	.aux_stat = gk104_aux_stat,
	.aux_mask = gk104_aux_mask,
	.aux_autodpcd = gk110_aux_autodpcd,
};

int
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@
#include "priv.h"
#include "pad.h"

static void
gm200_aux_autodpcd(struct nvkm_i2c *i2c, int aux, bool enable)
{
	nvkm_mask(i2c->subdev.device, 0x00d968 + (aux * 0x50), 0x00010000, enable << 16);
}

static const struct nvkm_i2c_func
gm200_i2c = {
	.pad_x_new = gf119_i2c_pad_x_new,
@@ -31,6 +37,7 @@ gm200_i2c = {
	.aux = 8,
	.aux_stat = gk104_aux_stat,
	.aux_mask = gk104_aux_mask,
	.aux_autodpcd = gm200_aux_autodpcd,
};

int
Loading