131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs/* 27dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs * Copyright 2012 Red Hat Inc. 331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * 431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * copy of this software and associated documentation files (the "Software"), 631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * to deal in the Software without restriction, including without limitation 731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the 931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * Software is furnished to do so, subject to the following conditions: 1031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * 1131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * The above copyright notice and this permission notice shall be included in 1231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * all copies or substantial portions of the Software. 1331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * 1431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * OTHER DEALINGS IN THE SOFTWARE. 2131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * 2231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs * Authors: Ben Skeggs 2331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs */ 2431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 257dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs#include "nv50.h" 2631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 27d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggsvoid 28d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggsnv94_aux_stat(struct nouveau_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) 29d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs{ 30d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs u32 intr = nv_rd32(i2c, 0x00e06c); 31d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs u32 stat = nv_rd32(i2c, 0x00e068) & intr, i; 32d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { 33d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if ((stat & (1 << (i * 4)))) *hi |= 1 << i; 34d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if ((stat & (2 << (i * 4)))) *lo |= 1 << i; 35d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if ((stat & (4 << (i * 4)))) *rq |= 1 << i; 36d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if ((stat & (8 << (i * 4)))) *tx |= 1 << i; 37d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs } 38d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs nv_wr32(i2c, 0x00e06c, intr); 39d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs} 40d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs 41d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggsvoid 42d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggsnv94_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) 43d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs{ 44d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs u32 temp = nv_rd32(i2c, 0x00e068), i; 45d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs for (i = 0; i < 8; i++) { 46d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if (mask & (1 << i)) { 47d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs if (!(data & (1 << i))) { 48d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs temp &= ~(type << (i * 4)); 49d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs continue; 50d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs } 51d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs temp |= type << (i * 4); 52d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs } 53d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs } 54d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs nv_wr32(i2c, 0x00e068, temp); 55d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs} 56d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs 5731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) 5831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) 5931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 6031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsstatic void 6131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsauxch_fini(struct nouveau_i2c *aux, int ch) 6231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs{ 6331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); 6431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs} 6531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 6631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsstatic int 6731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsauxch_init(struct nouveau_i2c *aux, int ch) 6831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs{ 6931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs const u32 unksel = 1; /* nfi which to use, or if it matters.. */ 7031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs const u32 ureq = unksel ? 0x00100000 : 0x00200000; 7131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs const u32 urep = unksel ? 0x01000000 : 0x02000000; 7231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs u32 ctrl, timeout; 7331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 7431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs /* wait up to 1ms for any previous transaction to be done... */ 7531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs timeout = 1000; 7631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs do { 7731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 7831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs udelay(1); 7931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (!timeout--) { 8031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_ERR("begin idle timeout 0x%08x\n", ctrl); 8131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs return -EBUSY; 8231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 8331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } while (ctrl & 0x03010000); 8431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 8531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs /* set some magic, and wait up to 1ms for it to appear */ 8631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); 8731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs timeout = 1000; 8831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs do { 8931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 9031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs udelay(1); 9131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (!timeout--) { 9231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_ERR("magic wait 0x%08x\n", ctrl); 9331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs auxch_fini(aux, ch); 9431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs return -EBUSY; 9531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 9631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } while ((ctrl & 0x03000000) != urep); 9731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 9831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs return 0; 9931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs} 10031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 10131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsint 102842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggsnv94_aux(struct nouveau_i2c_port *base, bool retry, 103842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs u8 type, u32 addr, u8 *data, u8 size) 10431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs{ 1057dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nouveau_i2c *aux = nouveau_i2c(base); 1067dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nv50_i2c_port *port = (void *)base; 10731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs u32 ctrl, stat, timeout, retries; 10831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs u32 xbuf[4] = {}; 1097dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs int ch = port->addr; 11031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs int ret, i; 11131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 11231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_DBG("%d: 0x%08x %d\n", type, addr, size); 11331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 11431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ret = auxch_init(aux, ch); 11531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (ret) 11631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs goto out; 11731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 11831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); 11931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (!(stat & 0x10000000)) { 12031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_DBG("sink not detected\n"); 12131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ret = -ENXIO; 12231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs goto out; 12331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 12431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 12531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (!(type & 1)) { 12631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs memcpy(xbuf, data, size); 12731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs for (i = 0; i < 16; i += 4) { 12831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); 12931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); 13031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 13131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 13231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 13331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 13431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl &= ~0x0001f0ff; 13531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl |= type << 12; 13631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl |= size - 1; 13731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); 13831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 139842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs /* (maybe) retry transaction a number of times on failure... */ 140842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs for (retries = 0; !ret && retries < 32; retries++) { 14131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs /* reset, and delay a while if this is a retry */ 14231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); 14331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); 14431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (retries) 14531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs udelay(400); 14631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 14731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs /* transaction request, wait up to 1ms for it to complete */ 14831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); 14931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 15031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs timeout = 1000; 15131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs do { 15231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 15331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs udelay(1); 15431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (!timeout--) { 15531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_ERR("tx req timeout 0x%08x\n", ctrl); 156842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs ret = -EIO; 15731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs goto out; 15831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 15931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } while (ctrl & 0x00010000); 160842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs ret = 1; 16131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 16231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs /* read status, and check if transaction completed ok */ 16331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); 164842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs if ((stat & 0x000f0000) == 0x00080000 || 165842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs (stat & 0x000f0000) == 0x00020000) 166842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs ret = retry ? 0 : 1; 167842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs if ((stat & 0x00000100)) 168842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs ret = -ETIMEDOUT; 169842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs if ((stat & 0x00000e00)) 170842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs ret = -EIO; 17131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 17231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); 17331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 17431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 17531a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs if (type & 1) { 17631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs for (i = 0; i < 16; i += 4) { 17731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); 17831a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); 17931a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 18031a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs memcpy(data, xbuf, size); 18131a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs } 18231a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 18331a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggsout: 18431a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs auxch_fini(aux, ch); 185842c2953fc360f9661d7b8bdd90303d4c946f1efBen Skeggs return ret < 0 ? ret : (stat & 0x000f0000) >> 16; 18631a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs} 18731a34aa421032cfe3b2b892c929e7539e747a7acBen Skeggs 1887dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsstatic const struct nouveau_i2c_func 1897dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsnv94_i2c_func = { 1907dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .drive_scl = nv50_i2c_drive_scl, 1917dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .drive_sda = nv50_i2c_drive_sda, 1927dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .sense_scl = nv50_i2c_sense_scl, 1937dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .sense_sda = nv50_i2c_sense_sda, 1947dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs}; 1957dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 1967dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsstatic int 1977dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsnv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 1987dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 index, 1997dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nouveau_object **pobject) 2007dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs{ 2017dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct dcb_i2c_entry *info = data; 2027dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nv50_i2c_port *port; 2037dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs int ret; 2047dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2057dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs ret = nouveau_i2c_port_create(parent, engine, oclass, index, 206c865534f1e5b5b4ef03f4a55cf4730f4b70dd75bIlia Mirkin &nouveau_i2c_bit_algo, &nv94_i2c_func, 207c865534f1e5b5b4ef03f4a55cf4730f4b70dd75bIlia Mirkin &port); 2087dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs *pobject = nv_object(port); 2097dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs if (ret) 2107dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs return ret; 2117dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2127dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs if (info->drive >= nv50_i2c_addr_nr) 2137dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs return -EINVAL; 2147dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2157dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->state = 7; 2167dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->addr = nv50_i2c_addr[info->drive]; 2177dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs if (info->share != DCB_I2C_UNUSED) { 2187dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->ctrl = 0x00e500 + (info->share * 0x50); 2197dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->data = 0x0000e001; 2207dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs } 2217dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs return 0; 2227dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs} 2237dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2247dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsstatic const struct nouveau_i2c_func 2257dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsnv94_aux_func = { 2267dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .aux = nv94_aux, 2277dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs}; 2287dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2297dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsint 2307dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsnv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 2317dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 index, 2327dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nouveau_object **pobject) 2337dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs{ 2347dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct dcb_i2c_entry *info = data; 2357dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs struct nv50_i2c_port *port; 2367dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs int ret; 2377dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2387dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs ret = nouveau_i2c_port_create(parent, engine, oclass, index, 239c865534f1e5b5b4ef03f4a55cf4730f4b70dd75bIlia Mirkin &nouveau_i2c_aux_algo, &nv94_aux_func, 240c865534f1e5b5b4ef03f4a55cf4730f4b70dd75bIlia Mirkin &port); 2417dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs *pobject = nv_object(port); 2427dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs if (ret) 2437dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs return ret; 2447dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2453668a339d6e7d47f777b8ce86bd7ca53451df6bbBen Skeggs port->base.aux = info->drive; 2467dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->addr = info->drive; 2477dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs if (info->share != DCB_I2C_UNUSED) { 2487dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->ctrl = 0x00e500 + (info->drive * 0x50); 2497dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs port->data = 0x00002002; 2507dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs } 2517dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2527dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs return 0; 2537dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs} 2547dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 2557dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsstatic struct nouveau_oclass 2567dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggsnv94_i2c_sclass[] = { 2577dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 2587dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .ofuncs = &(struct nouveau_ofuncs) { 2597dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .ctor = nv94_i2c_port_ctor, 2607dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .dtor = _nouveau_i2c_port_dtor, 2617dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .init = nv50_i2c_port_init, 2627dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .fini = _nouveau_i2c_port_fini, 2637dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs }, 2647dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs }, 2657dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), 2667dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .ofuncs = &(struct nouveau_ofuncs) { 2677dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .ctor = nv94_aux_port_ctor, 2687dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .dtor = _nouveau_i2c_port_dtor, 2697dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .init = _nouveau_i2c_port_init, 2707dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .fini = _nouveau_i2c_port_fini, 2717dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs }, 2727dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs }, 2737dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs {} 2747dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs}; 2757dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs 276c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggsstruct nouveau_oclass * 277c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggsnv94_i2c_oclass = &(struct nouveau_i2c_impl) { 278c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggs .base.handle = NV_SUBDEV(I2C, 0x94), 279c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggs .base.ofuncs = &(struct nouveau_ofuncs) { 280c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggs .ctor = _nouveau_i2c_ctor, 2817dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .dtor = _nouveau_i2c_dtor, 2827dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .init = _nouveau_i2c_init, 2837dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs .fini = _nouveau_i2c_fini, 2847dcd060c0e6e4f76ce7eea94c66437ce8f546530Ben Skeggs }, 285c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggs .sclass = nv94_i2c_sclass, 2869efc583ea9a474a8d89421da8aad4a2265f2ac5aBen Skeggs .pad_x = &nv04_i2c_pad_oclass, 2879efc583ea9a474a8d89421da8aad4a2265f2ac5aBen Skeggs .pad_s = &nv94_i2c_pad_oclass, 288d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs .aux = 4, 289d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs .aux_stat = nv94_aux_stat, 290d78fa39a2b766b680e6c703f52553afc6c532e11Ben Skeggs .aux_mask = nv94_aux_mask, 291c26fe843560fe01b4b652ee21952d33f60f4e699Ben Skeggs}.base; 292