1/* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24#include "nv50.h" 25 26void 27g94_aux_stat(struct nvkm_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) 28{ 29 u32 intr = nv_rd32(i2c, 0x00e06c); 30 u32 stat = nv_rd32(i2c, 0x00e068) & intr, i; 31 for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { 32 if ((stat & (1 << (i * 4)))) *hi |= 1 << i; 33 if ((stat & (2 << (i * 4)))) *lo |= 1 << i; 34 if ((stat & (4 << (i * 4)))) *rq |= 1 << i; 35 if ((stat & (8 << (i * 4)))) *tx |= 1 << i; 36 } 37 nv_wr32(i2c, 0x00e06c, intr); 38} 39 40void 41g94_aux_mask(struct nvkm_i2c *i2c, u32 type, u32 mask, u32 data) 42{ 43 u32 temp = nv_rd32(i2c, 0x00e068), i; 44 for (i = 0; i < 8; i++) { 45 if (mask & (1 << i)) { 46 if (!(data & (1 << i))) { 47 temp &= ~(type << (i * 4)); 48 continue; 49 } 50 temp |= type << (i * 4); 51 } 52 } 53 nv_wr32(i2c, 0x00e068, temp); 54} 55 56#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) 57#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) 58 59static void 60auxch_fini(struct nvkm_i2c *aux, int ch) 61{ 62 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); 63} 64 65static int 66auxch_init(struct nvkm_i2c *aux, int ch) 67{ 68 const u32 unksel = 1; /* nfi which to use, or if it matters.. */ 69 const u32 ureq = unksel ? 0x00100000 : 0x00200000; 70 const u32 urep = unksel ? 0x01000000 : 0x02000000; 71 u32 ctrl, timeout; 72 73 /* wait up to 1ms for any previous transaction to be done... */ 74 timeout = 1000; 75 do { 76 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 77 udelay(1); 78 if (!timeout--) { 79 AUX_ERR("begin idle timeout 0x%08x\n", ctrl); 80 return -EBUSY; 81 } 82 } while (ctrl & 0x03010000); 83 84 /* set some magic, and wait up to 1ms for it to appear */ 85 nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); 86 timeout = 1000; 87 do { 88 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 89 udelay(1); 90 if (!timeout--) { 91 AUX_ERR("magic wait 0x%08x\n", ctrl); 92 auxch_fini(aux, ch); 93 return -EBUSY; 94 } 95 } while ((ctrl & 0x03000000) != urep); 96 97 return 0; 98} 99 100int 101g94_aux(struct nvkm_i2c_port *base, bool retry, 102 u8 type, u32 addr, u8 *data, u8 size) 103{ 104 struct nvkm_i2c *aux = nvkm_i2c(base); 105 struct nv50_i2c_port *port = (void *)base; 106 u32 ctrl, stat, timeout, retries; 107 u32 xbuf[4] = {}; 108 int ch = port->addr; 109 int ret, i; 110 111 AUX_DBG("%d: 0x%08x %d\n", type, addr, size); 112 113 ret = auxch_init(aux, ch); 114 if (ret) 115 goto out; 116 117 stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); 118 if (!(stat & 0x10000000)) { 119 AUX_DBG("sink not detected\n"); 120 ret = -ENXIO; 121 goto out; 122 } 123 124 if (!(type & 1)) { 125 memcpy(xbuf, data, size); 126 for (i = 0; i < 16; i += 4) { 127 AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); 128 nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); 129 } 130 } 131 132 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 133 ctrl &= ~0x0001f0ff; 134 ctrl |= type << 12; 135 ctrl |= size - 1; 136 nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); 137 138 /* (maybe) retry transaction a number of times on failure... */ 139 for (retries = 0; !ret && retries < 32; retries++) { 140 /* reset, and delay a while if this is a retry */ 141 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); 142 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); 143 if (retries) 144 udelay(400); 145 146 /* transaction request, wait up to 1ms for it to complete */ 147 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); 148 149 timeout = 1000; 150 do { 151 ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 152 udelay(1); 153 if (!timeout--) { 154 AUX_ERR("tx req timeout 0x%08x\n", ctrl); 155 ret = -EIO; 156 goto out; 157 } 158 } while (ctrl & 0x00010000); 159 ret = 1; 160 161 /* read status, and check if transaction completed ok */ 162 stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); 163 if ((stat & 0x000f0000) == 0x00080000 || 164 (stat & 0x000f0000) == 0x00020000) 165 ret = retry ? 0 : 1; 166 if ((stat & 0x00000100)) 167 ret = -ETIMEDOUT; 168 if ((stat & 0x00000e00)) 169 ret = -EIO; 170 171 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); 172 } 173 174 if (type & 1) { 175 for (i = 0; i < 16; i += 4) { 176 xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); 177 AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); 178 } 179 memcpy(data, xbuf, size); 180 } 181 182out: 183 auxch_fini(aux, ch); 184 return ret < 0 ? ret : (stat & 0x000f0000) >> 16; 185} 186 187static const struct nvkm_i2c_func 188g94_i2c_func = { 189 .drive_scl = nv50_i2c_drive_scl, 190 .drive_sda = nv50_i2c_drive_sda, 191 .sense_scl = nv50_i2c_sense_scl, 192 .sense_sda = nv50_i2c_sense_sda, 193}; 194 195static int 196g94_i2c_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 197 struct nvkm_oclass *oclass, void *data, u32 index, 198 struct nvkm_object **pobject) 199{ 200 struct dcb_i2c_entry *info = data; 201 struct nv50_i2c_port *port; 202 int ret; 203 204 ret = nvkm_i2c_port_create(parent, engine, oclass, index, 205 &nvkm_i2c_bit_algo, &g94_i2c_func, &port); 206 *pobject = nv_object(port); 207 if (ret) 208 return ret; 209 210 if (info->drive >= nv50_i2c_addr_nr) 211 return -EINVAL; 212 213 port->state = 7; 214 port->addr = nv50_i2c_addr[info->drive]; 215 return 0; 216} 217 218static const struct nvkm_i2c_func 219g94_aux_func = { 220 .aux = g94_aux, 221}; 222 223int 224g94_aux_port_ctor(struct nvkm_object *parent, struct nvkm_object *engine, 225 struct nvkm_oclass *oclass, void *data, u32 index, 226 struct nvkm_object **pobject) 227{ 228 struct dcb_i2c_entry *info = data; 229 struct nv50_i2c_port *port; 230 int ret; 231 232 ret = nvkm_i2c_port_create(parent, engine, oclass, index, 233 &nvkm_i2c_aux_algo, &g94_aux_func, &port); 234 *pobject = nv_object(port); 235 if (ret) 236 return ret; 237 238 port->base.aux = info->auxch; 239 port->addr = info->auxch; 240 return 0; 241} 242 243static struct nvkm_oclass 244g94_i2c_sclass[] = { 245 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 246 .ofuncs = &(struct nvkm_ofuncs) { 247 .ctor = g94_i2c_port_ctor, 248 .dtor = _nvkm_i2c_port_dtor, 249 .init = nv50_i2c_port_init, 250 .fini = _nvkm_i2c_port_fini, 251 }, 252 }, 253 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), 254 .ofuncs = &(struct nvkm_ofuncs) { 255 .ctor = g94_aux_port_ctor, 256 .dtor = _nvkm_i2c_port_dtor, 257 .init = _nvkm_i2c_port_init, 258 .fini = _nvkm_i2c_port_fini, 259 }, 260 }, 261 {} 262}; 263 264struct nvkm_oclass * 265g94_i2c_oclass = &(struct nvkm_i2c_impl) { 266 .base.handle = NV_SUBDEV(I2C, 0x94), 267 .base.ofuncs = &(struct nvkm_ofuncs) { 268 .ctor = _nvkm_i2c_ctor, 269 .dtor = _nvkm_i2c_dtor, 270 .init = _nvkm_i2c_init, 271 .fini = _nvkm_i2c_fini, 272 }, 273 .sclass = g94_i2c_sclass, 274 .pad_x = &nv04_i2c_pad_oclass, 275 .pad_s = &g94_i2c_pad_oclass, 276 .aux = 4, 277 .aux_stat = g94_aux_stat, 278 .aux_mask = g94_aux_mask, 279}.base; 280