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

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
...@@ -3,6 +3,13 @@ ...@@ -3,6 +3,13 @@
#define __NVKM_I2C_AUX_H__ #define __NVKM_I2C_AUX_H__
#include "pad.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 { struct nvkm_i2c_aux_func {
bool address_only; bool address_only;
int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type, int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
......
...@@ -77,7 +77,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -77,7 +77,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u8 type, u32 addr, u8 *data, u8 *size) u8 type, u32 addr, u8 *data, u8 *size)
{ {
struct g94_i2c_aux *aux = g94_i2c_aux(obj); 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; const u32 base = aux->ch * 0x50;
u32 ctrl, stat, timeout, retries = 0; u32 ctrl, stat, timeout, retries = 0;
u32 xbuf[4] = {}; u32 xbuf[4] = {};
...@@ -96,6 +97,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -96,6 +97,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
goto out; goto out;
} }
nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);
if (!(type & 1)) { if (!(type & 1)) {
memcpy(xbuf, data, *size); memcpy(xbuf, data, *size);
for (i = 0; i < 16; i += 4) { for (i = 0; i < 16; i += 4) {
...@@ -128,7 +131,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -128,7 +131,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
if (!timeout--) { if (!timeout--) {
AUX_ERR(&aux->base, "timeout %08x", ctrl); AUX_ERR(&aux->base, "timeout %08x", ctrl);
ret = -EIO; ret = -EIO;
goto out; goto out_err;
} }
} while (ctrl & 0x00010000); } while (ctrl & 0x00010000);
ret = 0; ret = 0;
...@@ -154,7 +157,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -154,7 +157,8 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
memcpy(data, xbuf, *size); memcpy(data, xbuf, *size);
*size = stat & 0x0000001f; *size = stat & 0x0000001f;
} }
out_err:
nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
out: out:
g94_i2c_aux_fini(aux); g94_i2c_aux_fini(aux);
return ret < 0 ? ret : (stat & 0x000f0000) >> 16; return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
......
...@@ -77,7 +77,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -77,7 +77,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
u8 type, u32 addr, u8 *data, u8 *size) u8 type, u32 addr, u8 *data, u8 *size)
{ {
struct gm200_i2c_aux *aux = gm200_i2c_aux(obj); 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; const u32 base = aux->ch * 0x50;
u32 ctrl, stat, timeout, retries = 0; u32 ctrl, stat, timeout, retries = 0;
u32 xbuf[4] = {}; u32 xbuf[4] = {};
...@@ -96,6 +97,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -96,6 +97,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
goto out; goto out;
} }
nvkm_i2c_aux_autodpcd(i2c, aux->ch, false);
if (!(type & 1)) { if (!(type & 1)) {
memcpy(xbuf, data, *size); memcpy(xbuf, data, *size);
for (i = 0; i < 16; i += 4) { for (i = 0; i < 16; i += 4) {
...@@ -128,7 +131,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -128,7 +131,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
if (!timeout--) { if (!timeout--) {
AUX_ERR(&aux->base, "timeout %08x", ctrl); AUX_ERR(&aux->base, "timeout %08x", ctrl);
ret = -EIO; ret = -EIO;
goto out; goto out_err;
} }
} while (ctrl & 0x00010000); } while (ctrl & 0x00010000);
ret = 0; ret = 0;
...@@ -155,6 +158,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ...@@ -155,6 +158,8 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
*size = stat & 0x0000001f; *size = stat & 0x0000001f;
} }
out_err:
nvkm_i2c_aux_autodpcd(i2c, aux->ch, true);
out: out:
gm200_i2c_aux_fini(aux); gm200_i2c_aux_fini(aux);
return ret < 0 ? ret : (stat & 0x000f0000) >> 16; return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
......
...@@ -22,6 +22,12 @@ ...@@ -22,6 +22,12 @@
#include "priv.h" #include "priv.h"
#include "pad.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 static const struct nvkm_i2c_func
gk110_i2c = { gk110_i2c = {
.pad_x_new = gf119_i2c_pad_x_new, .pad_x_new = gf119_i2c_pad_x_new,
...@@ -29,6 +35,7 @@ gk110_i2c = { ...@@ -29,6 +35,7 @@ gk110_i2c = {
.aux = 4, .aux = 4,
.aux_stat = gk104_aux_stat, .aux_stat = gk104_aux_stat,
.aux_mask = gk104_aux_mask, .aux_mask = gk104_aux_mask,
.aux_autodpcd = gk110_aux_autodpcd,
}; };
int int
......
...@@ -24,6 +24,12 @@ ...@@ -24,6 +24,12 @@
#include "priv.h" #include "priv.h"
#include "pad.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 static const struct nvkm_i2c_func
gm200_i2c = { gm200_i2c = {
.pad_x_new = gf119_i2c_pad_x_new, .pad_x_new = gf119_i2c_pad_x_new,
...@@ -31,6 +37,7 @@ gm200_i2c = { ...@@ -31,6 +37,7 @@ gm200_i2c = {
.aux = 8, .aux = 8,
.aux_stat = gk104_aux_stat, .aux_stat = gk104_aux_stat,
.aux_mask = gk104_aux_mask, .aux_mask = gk104_aux_mask,
.aux_autodpcd = gm200_aux_autodpcd,
}; };
int int
......
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
#ifndef __NVKM_I2C_PAD_H__ #ifndef __NVKM_I2C_PAD_H__
#define __NVKM_I2C_PAD_H__ #define __NVKM_I2C_PAD_H__
#include <subdev/i2c.h> #include "priv.h"
struct nvkm_i2c_pad { struct nvkm_i2c_pad {
const struct nvkm_i2c_pad_func *func; const struct nvkm_i2c_pad_func *func;
......
...@@ -23,6 +23,10 @@ struct nvkm_i2c_func { ...@@ -23,6 +23,10 @@ struct nvkm_i2c_func {
/* mask on/off interrupt types for a given set of auxch /* mask on/off interrupt types for a given set of auxch
*/ */
void (*aux_mask)(struct nvkm_i2c *, u32, u32, u32); void (*aux_mask)(struct nvkm_i2c *, u32, u32, u32);
/* enable/disable HW-initiated DPCD reads
*/
void (*aux_autodpcd)(struct nvkm_i2c *, int aux, bool enable);
}; };
void g94_aux_stat(struct nvkm_i2c *, u32 *, u32 *, u32 *, u32 *); void g94_aux_stat(struct nvkm_i2c *, u32 *, u32 *, u32 *, u32 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment