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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2021-01-13 17:12:52 +10:00
Родитель b5510d1e21
Коммит 8ad95edc39
7 изменённых файлов: 40 добавлений и 6 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_I2C_PAD_H__
#define __NVKM_I2C_PAD_H__
#include <subdev/i2c.h>
#include "priv.h"
struct nvkm_i2c_pad {
const struct nvkm_i2c_pad_func *func;

Просмотреть файл

@ -23,6 +23,10 @@ struct nvkm_i2c_func {
/* mask on/off interrupt types for a given set of auxch
*/
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 *);