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:
Родитель
b5510d1e21
Коммит
8ad95edc39
|
@ -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 *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче