1/*- 2 * Copyright (c) 1998, 2001 Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: releng/10.2/sys/dev/bktr/bktr_i2c.c 201758 2010-01-07 21:01:37Z mbr $"); 29 30/* 31 * I2C support for the bti2c chipset. 32 * 33 * From brooktree848.c <fsmp@freefall.org> 34 */ 35 36#include "opt_bktr.h" 37 38#include <sys/param.h> 39#include <sys/kernel.h> 40#include <sys/malloc.h> 41#include <sys/systm.h> 42#include <sys/module.h> 43#include <sys/bus.h> 44#include <sys/uio.h> 45 46#if __FreeBSD_version < 500014 47#include <sys/select.h> 48#else 49#include <sys/selinfo.h> 50#endif 51 52#if (__FreeBSD_version < 500000) 53#include <pci/pcivar.h> 54#include <pci/pcireg.h> 55#else 56#include <dev/pci/pcivar.h> 57#include <dev/pci/pcireg.h> 58#endif 59 60#include <machine/bus.h> 61#include <sys/bus.h> 62 63#include <dev/bktr/ioctl_meteor.h> 64#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 65#include <dev/bktr/bktr_reg.h> 66#include <dev/bktr/bktr_i2c.h> 67 68#include <dev/smbus/smbconf.h> 69#include <dev/iicbus/iiconf.h> 70 71/* Compilation is void if BKTR_USE_FREEBSD_SMBUS is not 72 * defined. This allows bktr owners to have smbus active for there 73 * motherboard and still use their bktr without smbus. 74 */ 75#if defined(BKTR_USE_FREEBSD_SMBUS) 76 77#define BTI2C_DEBUG(x) if (bti2c_debug) (x) 78static int bti2c_debug = 0; 79 80/* 81 * Call this to pass the address of the bktr device to the 82 * bti2c_i2c layer and initialize all the I2C bus architecture 83 */ 84int bt848_i2c_attach(device_t dev) 85{ 86 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 87 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 88 89 sc->smbus = device_add_child(dev, "smbus", -1); 90 sc->iicbb = device_add_child(dev, "iicbb", -1); 91 92 if (!sc->iicbb || !sc->smbus) 93 return ENXIO; 94 95 bus_generic_attach(dev); 96 97 return (0); 98}; 99 100int bt848_i2c_detach(device_t dev) 101{ 102 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 103 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 104 int error = 0; 105 106 if ((error = bus_generic_detach(dev))) 107 goto error; 108 109 if (sc->iicbb && (error = device_delete_child(dev, sc->iicbb))) 110 goto error; 111 112 if (sc->smbus && (error = device_delete_child(dev, sc->smbus))) 113 goto error; 114 115error: 116 return (error); 117} 118 119int bti2c_smb_callback(device_t dev, int index, void *data) 120{ 121 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 122 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 123 int error = 0; 124 125 /* test each time if we already have/haven't the iicbus 126 * to avoid deadlocks 127 */ 128 switch (index) { 129 case SMB_REQUEST_BUS: 130 /* XXX test & set */ 131 mtx_lock(&Giant); 132 if (!sc->bus_owned) { 133 sc->bus_owned = 1; 134 } else 135 error = EWOULDBLOCK; 136 mtx_unlock(&Giant); 137 break; 138 139 case SMB_RELEASE_BUS: 140 /* XXX test & set */ 141 mtx_lock(&Giant); 142 if (sc->bus_owned) { 143 sc->bus_owned = 0; 144 } else 145 error = EINVAL; 146 mtx_unlock(&Giant); 147 break; 148 149 default: 150 error = EINVAL; 151 } 152 153 return (error); 154} 155 156int bti2c_iic_callback(device_t dev, int index, caddr_t *data) 157{ 158 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 159 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 160 int error = 0; 161 162 /* test each time if we already have/haven't the smbus 163 * to avoid deadlocks 164 */ 165 switch (index) { 166 case IIC_REQUEST_BUS: 167 /* XXX test & set */ 168 mtx_lock(&Giant); 169 if (!sc->bus_owned) { 170 sc->bus_owned = 1; 171 } else 172 error = EWOULDBLOCK; 173 mtx_unlock(&Giant); 174 break; 175 176 case IIC_RELEASE_BUS: 177 /* XXX test & set */ 178 mtx_lock(&Giant); 179 if (sc->bus_owned) { 180 sc->bus_owned = 0; 181 } else 182 error = EINVAL; 183 mtx_unlock(&Giant); 184 break; 185 186 default: 187 error = EINVAL; 188 } 189 190 return (error); 191} 192 193int bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) 194{ 195 mtx_lock(&Giant); 196 if (oldaddr) 197 *oldaddr = 0; /* XXX */ 198 mtx_unlock(&Giant); 199 200 return (IIC_ENOADDR); 201} 202 203void bti2c_iic_setsda(device_t dev, int val) 204{ 205 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 206 int clock; 207 208 mtx_lock(&Giant); 209 clock = INL(sc, BKTR_I2C_DATA_CTL) & 0x2; 210 211 if (val) 212 OUTL(sc, BKTR_I2C_DATA_CTL, clock | 1); 213 else 214 OUTL(sc, BKTR_I2C_DATA_CTL, clock); 215 mtx_unlock(&Giant); 216 217 return; 218} 219 220void bti2c_iic_setscl(device_t dev, int val) 221{ 222 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 223 int data; 224 225 mtx_lock(&Giant); 226 data = INL(sc, BKTR_I2C_DATA_CTL) & 0x1; 227 228 if (val) 229 OUTL(sc, BKTR_I2C_DATA_CTL, 0x2 | data); 230 else 231 OUTL(sc, BKTR_I2C_DATA_CTL, data); 232 mtx_unlock(&Giant); 233 234 return; 235} 236 237int 238bti2c_iic_getsda(device_t dev) 239{ 240 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 241 int retval; 242 243 mtx_lock(&Giant); 244 retval = INL(sc,BKTR_I2C_DATA_CTL) & 0x1; 245 mtx_unlock(&Giant); 246 return (retval); 247} 248 249int 250bti2c_iic_getscl(device_t dev) 251{ 252 return (0); 253} 254 255static int 256bti2c_write(struct bktr_softc *sc, u_long data) 257{ 258 u_long x; 259 260 mtx_lock(&Giant); 261 262 /* clear status bits */ 263 OUTL(sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); 264 265 BTI2C_DEBUG(printf("w%lx", data)); 266 267 /* write the address and data */ 268 OUTL(sc, BKTR_I2C_DATA_CTL, data); 269 270 /* wait for completion */ 271 for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 272 if ( INL(sc, BKTR_INT_STAT) & BT848_INT_I2CDONE ) 273 break; 274 } 275 276 /* check for ACK */ 277 if ( !x || !( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK) ) { 278 BTI2C_DEBUG(printf("%c%c", (!x)?'+':'-', 279 (!( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); 280 mtx_unlock(&Giant); 281 return (SMB_ENOACK); 282 } 283 BTI2C_DEBUG(printf("+")); 284 mtx_unlock(&Giant); 285 286 /* return OK */ 287 return( 0 ); 288} 289 290int 291bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 292{ 293 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 294 u_long data; 295 296 data = ((slave & 0xff) << 24) | ((byte & 0xff) << 16) | (u_char)cmd; 297 298 return (bti2c_write(sc, data)); 299} 300 301/* 302 * byte1 becomes low byte of word 303 * byte2 becomes high byte of word 304 */ 305int 306bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word) 307{ 308 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 309 u_long data; 310 char low, high; 311 312 low = (char)(word & 0xff); 313 high = (char)((word & 0xff00) >> 8); 314 315 data = ((slave & 0xff) << 24) | ((low & 0xff) << 16) | 316 ((high & 0xff) << 8) | BT848_DATA_CTL_I2CW3B | (u_char)cmd; 317 318 return (bti2c_write(sc, data)); 319} 320 321/* 322 * The Bt878 and Bt879 differed on the treatment of i2c commands 323 */ 324int 325bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 326{ 327 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 328 u_long x; 329 330 mtx_lock(&Giant); 331 /* clear status bits */ 332 OUTL(sc,BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); 333 334 OUTL(sc,BKTR_I2C_DATA_CTL, ((slave & 0xff) << 24) | (u_char)cmd); 335 336 BTI2C_DEBUG(printf("r%lx/", (u_long)(((slave & 0xff) << 24) | (u_char)cmd))); 337 338 /* wait for completion */ 339 for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 340 if ( INL(sc,BKTR_INT_STAT) & BT848_INT_I2CDONE ) 341 break; 342 } 343 344 /* check for ACK */ 345 if ( !x || !(INL(sc,BKTR_INT_STAT) & BT848_INT_RACK) ) { 346 BTI2C_DEBUG(printf("r%c%c", (!x)?'+':'-', 347 (!( INL(sc,BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); 348 mtx_unlock(&Giant); 349 return (SMB_ENOACK); 350 } 351 352 *byte = (char)((INL(sc,BKTR_I2C_DATA_CTL) >> 8) & 0xff); 353 BTI2C_DEBUG(printf("r%x+", *byte)); 354 mtx_unlock(&Giant); 355 356 return (0); 357} 358 359DRIVER_MODULE(iicbb, bktr, iicbb_driver, iicbb_devclass, 0, 0); 360DRIVER_MODULE(smbus, bktr, smbus_driver, smbus_devclass, 0, 0); 361 362#endif /* defined(BKTR_USE_FREEBSD_SMBUS) */ 363