1 /* 2 * Copyright 2015 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 <bskeggs@redhat.com> 23 */ 24 #include "bus.h" 25 #include "pad.h" 26 27 #include <core/option.h> 28 29 /******************************************************************************* 30 * i2c-algo-bit 31 ******************************************************************************/ 32 static int 33 nvkm_i2c_bus_pre_xfer(struct i2c_adapter *adap) 34 { 35 struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); 36 return nvkm_i2c_bus_acquire(bus); 37 } 38 39 static void 40 nvkm_i2c_bus_post_xfer(struct i2c_adapter *adap) 41 { 42 struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); 43 return nvkm_i2c_bus_release(bus); 44 } 45 46 static void 47 nvkm_i2c_bus_setscl(void *data, int state) 48 { 49 struct nvkm_i2c_bus *bus = data; 50 bus->func->drive_scl(bus, state); 51 } 52 53 static void 54 nvkm_i2c_bus_setsda(void *data, int state) 55 { 56 struct nvkm_i2c_bus *bus = data; 57 bus->func->drive_sda(bus, state); 58 } 59 60 static int 61 nvkm_i2c_bus_getscl(void *data) 62 { 63 struct nvkm_i2c_bus *bus = data; 64 return bus->func->sense_scl(bus); 65 } 66 67 static int 68 nvkm_i2c_bus_getsda(void *data) 69 { 70 struct nvkm_i2c_bus *bus = data; 71 return bus->func->sense_sda(bus); 72 } 73 74 /******************************************************************************* 75 * !i2c-algo-bit (off-chip i2c bus / hw i2c / internal bit-banging algo) 76 ******************************************************************************/ 77 static int 78 nvkm_i2c_bus_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 79 { 80 struct nvkm_i2c_bus *bus = container_of(adap, typeof(*bus), i2c); 81 int ret; 82 83 ret = nvkm_i2c_bus_acquire(bus); 84 if (ret) 85 return ret; 86 87 ret = bus->func->xfer(bus, msgs, num); 88 nvkm_i2c_bus_release(bus); 89 return ret; 90 } 91 92 static u32 93 nvkm_i2c_bus_func(struct i2c_adapter *adap) 94 { 95 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 96 } 97 98 static const struct i2c_algorithm 99 nvkm_i2c_bus_algo = { 100 .master_xfer = nvkm_i2c_bus_xfer, 101 .functionality = nvkm_i2c_bus_func, 102 }; 103 104 /******************************************************************************* 105 * nvkm_i2c_bus base 106 ******************************************************************************/ 107 void 108 nvkm_i2c_bus_init(struct nvkm_i2c_bus *bus) 109 { 110 BUS_TRACE(bus, "init"); 111 if (bus->func->init) 112 bus->func->init(bus); 113 } 114 115 void 116 nvkm_i2c_bus_release(struct nvkm_i2c_bus *bus) 117 { 118 struct nvkm_i2c_pad *pad = bus->pad; 119 BUS_TRACE(bus, "release"); 120 nvkm_i2c_pad_release(pad); 121 mutex_unlock(&bus->mutex); 122 } 123 124 int 125 nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *bus) 126 { 127 struct nvkm_i2c_pad *pad = bus->pad; 128 int ret; 129 BUS_TRACE(bus, "acquire"); 130 mutex_lock(&bus->mutex); 131 ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C); 132 if (ret) 133 mutex_unlock(&bus->mutex); 134 return ret; 135 } 136 137 int 138 nvkm_i2c_bus_probe(struct nvkm_i2c_bus *bus, const char *what, 139 struct nvkm_i2c_bus_probe *info, 140 bool (*match)(struct nvkm_i2c_bus *, 141 struct i2c_board_info *, void *), void *data) 142 { 143 int i; 144 145 BUS_DBG(bus, "probing %ss", what); 146 for (i = 0; info[i].dev.addr; i++) { 147 u8 orig_udelay = 0; 148 149 if ((bus->i2c.algo == &i2c_bit_algo) && (info[i].udelay != 0)) { 150 struct i2c_algo_bit_data *algo = bus->i2c.algo_data; 151 BUS_DBG(bus, "%dms delay instead of %dms", 152 info[i].udelay, algo->udelay); 153 orig_udelay = algo->udelay; 154 algo->udelay = info[i].udelay; 155 } 156 157 if (nvkm_probe_i2c(&bus->i2c, info[i].dev.addr) && 158 (!match || match(bus, &info[i].dev, data))) { 159 BUS_DBG(bus, "detected %s: %s", 160 what, info[i].dev.type); 161 return i; 162 } 163 164 if (orig_udelay) { 165 struct i2c_algo_bit_data *algo = bus->i2c.algo_data; 166 algo->udelay = orig_udelay; 167 } 168 } 169 170 BUS_DBG(bus, "no devices found."); 171 return -ENODEV; 172 } 173 174 void 175 nvkm_i2c_bus_del(struct nvkm_i2c_bus **pbus) 176 { 177 struct nvkm_i2c_bus *bus = *pbus; 178 if (bus && !WARN_ON(!bus->func)) { 179 BUS_TRACE(bus, "dtor"); 180 list_del(&bus->head); 181 i2c_del_adapter(&bus->i2c); 182 kfree(bus->i2c.algo_data); 183 kfree(*pbus); 184 *pbus = NULL; 185 } 186 } 187 188 int 189 nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func *func, 190 struct nvkm_i2c_pad *pad, int id, 191 struct nvkm_i2c_bus *bus) 192 { 193 struct nvkm_device *device = pad->i2c->subdev.device; 194 struct i2c_algo_bit_data *bit; 195 #ifndef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT 196 const bool internal = false; 197 #else 198 const bool internal = true; 199 #endif 200 int ret; 201 202 bus->func = func; 203 bus->pad = pad; 204 bus->id = id; 205 mutex_init(&bus->mutex); 206 list_add_tail(&bus->head, &pad->i2c->bus); 207 BUS_TRACE(bus, "ctor"); 208 209 snprintf(bus->i2c.name, sizeof(bus->i2c.name), "nvkm-%s-bus-%04x", 210 dev_name(device->dev), id); 211 bus->i2c.owner = THIS_MODULE; 212 bus->i2c.dev.parent = device->dev; 213 214 if ( bus->func->drive_scl && 215 !nvkm_boolopt(device->cfgopt, "NvI2C", internal)) { 216 if (!(bit = kzalloc(sizeof(*bit), GFP_KERNEL))) 217 return -ENOMEM; 218 bit->udelay = 10; 219 bit->timeout = usecs_to_jiffies(2200); 220 bit->data = bus; 221 bit->pre_xfer = nvkm_i2c_bus_pre_xfer; 222 bit->post_xfer = nvkm_i2c_bus_post_xfer; 223 bit->setscl = nvkm_i2c_bus_setscl; 224 bit->setsda = nvkm_i2c_bus_setsda; 225 bit->getscl = nvkm_i2c_bus_getscl; 226 bit->getsda = nvkm_i2c_bus_getsda; 227 bus->i2c.algo_data = bit; 228 ret = i2c_bit_add_bus(&bus->i2c); 229 } else { 230 bus->i2c.algo = &nvkm_i2c_bus_algo; 231 ret = i2c_add_adapter(&bus->i2c); 232 } 233 234 return ret; 235 } 236 237 int 238 nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *func, 239 struct nvkm_i2c_pad *pad, int id, 240 struct nvkm_i2c_bus **pbus) 241 { 242 if (!(*pbus = kzalloc(sizeof(**pbus), GFP_KERNEL))) 243 return -ENOMEM; 244 return nvkm_i2c_bus_ctor(func, pad, id, *pbus); 245 } 246