summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c191
1 files changed, 4 insertions, 187 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
index f027aed..e84b9a4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c
@@ -21,190 +21,8 @@
*
* Authors: Ben Skeggs
*/
-#include "nv50.h"
-
-#define AUX_DBG(fmt, args...) \
- nvkm_debug(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
-#define AUX_ERR(fmt, args...) \
- nvkm_error(&i2c->subdev, "AUXCH(%d): " fmt, ch, ##args)
-
-static void
-auxch_fini(struct nvkm_i2c *i2c, int ch)
-{
- struct nvkm_device *device = i2c->subdev.device;
- nvkm_mask(device, 0x00d954 + (ch * 0x50), 0x00310000, 0x00000000);
-}
-
-static int
-auxch_init(struct nvkm_i2c *i2c, int ch)
-{
- struct nvkm_device *device = i2c->subdev.device;
- const u32 unksel = 1; /* nfi which to use, or if it matters.. */
- const u32 ureq = unksel ? 0x00100000 : 0x00200000;
- const u32 urep = unksel ? 0x01000000 : 0x02000000;
- u32 ctrl, timeout;
-
- /* wait up to 1ms for any previous transaction to be done... */
- timeout = 1000;
- do {
- ctrl = nvkm_rd32(device, 0x00d954 + (ch * 0x50));
- udelay(1);
- if (!timeout--) {
- AUX_ERR("begin idle timeout %08x\n", ctrl);
- return -EBUSY;
- }
- } while (ctrl & 0x03010000);
-
- /* set some magic, and wait up to 1ms for it to appear */
- nvkm_mask(device, 0x00d954 + (ch * 0x50), 0x00300000, ureq);
- timeout = 1000;
- do {
- ctrl = nvkm_rd32(device, 0x00d954 + (ch * 0x50));
- udelay(1);
- if (!timeout--) {
- AUX_ERR("magic wait %08x\n", ctrl);
- auxch_fini(i2c, ch);
- return -EBUSY;
- }
- } while ((ctrl & 0x03000000) != urep);
-
- return 0;
-}
-
-int
-gm204_aux(struct nvkm_i2c_port *base, bool retry,
- u8 type, u32 addr, u8 *data, u8 size)
-{
- struct nvkm_i2c *i2c = nvkm_i2c(base);
- struct nvkm_device *device = i2c->subdev.device;
- struct nv50_i2c_port *port = (void *)base;
- u32 ctrl, stat, timeout, retries;
- u32 xbuf[4] = {};
- int ch = port->addr;
- int ret, i;
-
- AUX_DBG("%d: %08x %d\n", type, addr, size);
-
- ret = auxch_init(i2c, ch);
- if (ret < 0)
- goto out;
-
- stat = nvkm_rd32(device, 0x00d958 + (ch * 0x50));
- if (!(stat & 0x10000000)) {
- AUX_DBG("sink not detected\n");
- ret = -ENXIO;
- goto out;
- }
-
- if (!(type & 1)) {
- memcpy(xbuf, data, size);
- for (i = 0; i < 16; i += 4) {
- AUX_DBG("wr %08x\n", xbuf[i / 4]);
- nvkm_wr32(device, 0x00d930 + (ch * 0x50) + i, xbuf[i / 4]);
- }
- }
-
- ctrl = nvkm_rd32(device, 0x00d954 + (ch * 0x50));
- ctrl &= ~0x0001f0ff;
- ctrl |= type << 12;
- ctrl |= size - 1;
- nvkm_wr32(device, 0x00d950 + (ch * 0x50), addr);
-
- /* (maybe) retry transaction a number of times on failure... */
- for (retries = 0; !ret && retries < 32; retries++) {
- /* reset, and delay a while if this is a retry */
- nvkm_wr32(device, 0x00d954 + (ch * 0x50), 0x80000000 | ctrl);
- nvkm_wr32(device, 0x00d954 + (ch * 0x50), 0x00000000 | ctrl);
- if (retries)
- udelay(400);
-
- /* transaction request, wait up to 1ms for it to complete */
- nvkm_wr32(device, 0x00d954 + (ch * 0x50), 0x00010000 | ctrl);
-
- timeout = 1000;
- do {
- ctrl = nvkm_rd32(device, 0x00d954 + (ch * 0x50));
- udelay(1);
- if (!timeout--) {
- AUX_ERR("tx req timeout %08x\n", ctrl);
- ret = -EIO;
- goto out;
- }
- } while (ctrl & 0x00010000);
- ret = 1;
-
- /* read status, and check if transaction completed ok */
- stat = nvkm_mask(device, 0x00d958 + (ch * 0x50), 0, 0);
- if ((stat & 0x000f0000) == 0x00080000 ||
- (stat & 0x000f0000) == 0x00020000)
- ret = retry ? 0 : 1;
- if ((stat & 0x00000100))
- ret = -ETIMEDOUT;
- if ((stat & 0x00000e00))
- ret = -EIO;
-
- AUX_DBG("%02d %08x %08x\n", retries, ctrl, stat);
- }
-
- if (type & 1) {
- for (i = 0; i < 16; i += 4) {
- xbuf[i / 4] = nvkm_rd32(device, 0x00d940 + (ch * 0x50) + i);
- AUX_DBG("rd %08x\n", xbuf[i / 4]);
- }
- memcpy(data, xbuf, size);
- }
-
-out:
- auxch_fini(i2c, ch);
- return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
-}
-
-static const struct nvkm_i2c_func
-gm204_aux_func = {
- .aux = gm204_aux,
-};
-
-int
-gm204_aux_port_ctor(struct nvkm_object *parent,
- struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 index,
- struct nvkm_object **pobject)
-{
- struct dcb_i2c_entry *info = data;
- struct nv50_i2c_port *port;
- int ret;
-
- ret = nvkm_i2c_port_create(parent, engine, oclass, index,
- &nvkm_i2c_aux_algo, &gm204_aux_func, &port);
- *pobject = nv_object(port);
- if (ret)
- return ret;
-
- port->base.aux = info->auxch;
- port->addr = info->auxch;
- return 0;
-}
-
-struct nvkm_oclass
-gm204_i2c_sclass[] = {
- { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gf110_i2c_port_ctor,
- .dtor = _nvkm_i2c_port_dtor,
- .init = nv50_i2c_port_init,
- .fini = _nvkm_i2c_port_fini,
- },
- },
- { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX),
- .ofuncs = &(struct nvkm_ofuncs) {
- .ctor = gm204_aux_port_ctor,
- .dtor = _nvkm_i2c_port_dtor,
- .init = _nvkm_i2c_port_init,
- .fini = _nvkm_i2c_port_fini,
- },
- },
- {}
-};
+#include "priv.h"
+#include "pad.h"
struct nvkm_oclass *
gm204_i2c_oclass = &(struct nvkm_i2c_impl) {
@@ -215,9 +33,8 @@ gm204_i2c_oclass = &(struct nvkm_i2c_impl) {
.init = _nvkm_i2c_init,
.fini = _nvkm_i2c_fini,
},
- .sclass = gm204_i2c_sclass,
- .pad_x = &nv04_i2c_pad_oclass,
- .pad_s = &gm204_i2c_pad_oclass,
+ .pad_x_new = gf119_i2c_pad_x_new,
+ .pad_s_new = gm204_i2c_pad_s_new,
.aux = 8,
.aux_stat = gk104_aux_stat,
.aux_mask = gk104_aux_mask,
OpenPOWER on IntegriCloud