From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- .../gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c | 219 +++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c (limited to 'kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c') diff --git a/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c new file mode 100644 index 000000000..ab64237b3 --- /dev/null +++ b/kernel/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/gm204.c @@ -0,0 +1,219 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ +#include "nv50.h" + +#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) +#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) + +static void +auxch_fini(struct nvkm_i2c *aux, int ch) +{ + nv_mask(aux, 0x00d954 + (ch * 0x50), 0x00310000, 0x00000000); +} + +static int +auxch_init(struct nvkm_i2c *aux, int ch) +{ + 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 = nv_rd32(aux, 0x00d954 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("begin idle timeout 0x%08x\n", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(aux, 0x00d954 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("magic wait 0x%08x\n", ctrl); + auxch_fini(aux, 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 *aux = nvkm_i2c(base); + 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: 0x%08x %d\n", type, addr, size); + + ret = auxch_init(aux, ch); + if (ret) + goto out; + + stat = nv_rd32(aux, 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 0x%08x\n", xbuf[i / 4]); + nv_wr32(aux, 0x00d930 + (ch * 0x50) + i, xbuf[i / 4]); + } + } + + ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(aux, 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 */ + nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x80000000 | ctrl); + nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nv_wr32(aux, 0x00d954 + (ch * 0x50), 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00d954 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("tx req timeout 0x%08x\n", ctrl); + ret = -EIO; + goto out; + } + } while (ctrl & 0x00010000); + ret = 1; + + /* read status, and check if transaction completed ok */ + stat = nv_mask(aux, 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 0x%08x 0x%08x\n", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nv_rd32(aux, 0x00d940 + (ch * 0x50) + i); + AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + auxch_fini(aux, 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, + }, + }, + {} +}; + +struct nvkm_oclass * +gm204_i2c_oclass = &(struct nvkm_i2c_impl) { + .base.handle = NV_SUBDEV(I2C, 0x24), + .base.ofuncs = &(struct nvkm_ofuncs) { + .ctor = _nvkm_i2c_ctor, + .dtor = _nvkm_i2c_dtor, + .init = _nvkm_i2c_init, + .fini = _nvkm_i2c_fini, + }, + .sclass = gm204_i2c_sclass, + .pad_x = &nv04_i2c_pad_oclass, + .pad_s = &gm204_i2c_pad_oclass, + .aux = 8, + .aux_stat = gk104_aux_stat, + .aux_mask = gk104_aux_mask, +}.base; -- cgit 1.2.3-korg