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: head/sys/dev/bktr/bktr_i2c.c 146734 2005-05-29 04:42:30Z nyan $");
|
28__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_i2c.c 162234 2006-09-11 20:52:41Z jhb $"); |
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 <machine/clock.h> /* for DELAY */ 54#include <pci/pcivar.h> 55#include <pci/pcireg.h> 56#else 57#include <dev/pci/pcivar.h> 58#include <dev/pci/pcireg.h> 59#endif 60 61#include <machine/bus.h> 62#include <sys/bus.h> 63 64#include <dev/bktr/ioctl_meteor.h> 65#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 66#include <dev/bktr/bktr_reg.h> 67#include <dev/bktr/bktr_i2c.h> 68 69#include <dev/smbus/smbconf.h> 70#include <dev/iicbus/iiconf.h> 71 72#define I2C_DELAY 40 73 74/* Compilation is void if BKTR_USE_FREEBSD_SMBUS is not 75 * defined. This allows bktr owners to have smbus active for there 76 * motherboard and still use their bktr without smbus. 77 */ 78#if defined(BKTR_USE_FREEBSD_SMBUS) 79 80#define BTI2C_DEBUG(x) if (bti2c_debug) (x) 81static int bti2c_debug = 0; 82 83/* 84 * Call this to pass the address of the bktr device to the 85 * bti2c_i2c layer and initialize all the I2C bus architecture 86 */ 87int bt848_i2c_attach(device_t dev) 88{ 89 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 90 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 91 92 sc->smbus = device_add_child(dev, "smbus", -1); 93 sc->iicbb = device_add_child(dev, "iicbb", -1); 94 95 if (!sc->iicbb || !sc->smbus) 96 return ENXIO; 97 98 bus_generic_attach(dev); 99 100 return (0); 101}; 102 103int bt848_i2c_detach(device_t dev) 104{ 105 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 106 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 107 int error = 0; 108 109 if ((error = bus_generic_detach(dev))) 110 goto error; 111 112 if (sc->iicbb && (error = device_delete_child(dev, sc->iicbb))) 113 goto error; 114 115 if (sc->smbus && (error = device_delete_child(dev, sc->smbus))) 116 goto error; 117 118error: 119 return (error); 120} 121
|
122int bti2c_smb_callback(device_t dev, int index, caddr_t *data)
|
122int bti2c_smb_callback(device_t dev, int index, void *data) |
123{ 124 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 125 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 126 int error = 0; 127 128 /* test each time if we already have/haven't the iicbus 129 * to avoid deadlocks 130 */ 131 switch (index) { 132 case SMB_REQUEST_BUS: 133 /* XXX test & set */ 134 if (!sc->bus_owned) { 135 sc->bus_owned = 1; 136 } else 137 error = EWOULDBLOCK; 138 break; 139 140 case SMB_RELEASE_BUS: 141 /* XXX test & set */ 142 if (sc->bus_owned) { 143 sc->bus_owned = 0; 144 } else 145 error = EINVAL; 146 break; 147 148 default: 149 error = EINVAL; 150 } 151 152 return (error); 153} 154 155int bti2c_iic_callback(device_t dev, int index, caddr_t *data) 156{ 157 struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); 158 struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; 159 int error = 0; 160 161 /* test each time if we already have/haven't the smbus 162 * to avoid deadlocks 163 */ 164 switch (index) { 165 case IIC_REQUEST_BUS: 166 /* XXX test & set */ 167 if (!sc->bus_owned) { 168 sc->bus_owned = 1; 169 } else 170 error = EWOULDBLOCK; 171 break; 172 173 case IIC_RELEASE_BUS: 174 /* XXX test & set */ 175 if (sc->bus_owned) { 176 sc->bus_owned = 0; 177 } else 178 error = EINVAL; 179 break; 180 181 default: 182 error = EINVAL; 183 } 184 185 return (error); 186} 187 188int bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) 189{ 190 if (oldaddr) 191 *oldaddr = 0; /* XXX */ 192 193 return (IIC_ENOADDR); 194} 195 196void bti2c_iic_setsda(device_t dev, int val) 197{ 198 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 199 int clock; 200 201 clock = INL(sc, BKTR_I2C_DATA_CTL) & 0x2; 202 203 if (val) 204 OUTL(sc, BKTR_I2C_DATA_CTL, clock | 1); 205 else 206 OUTL(sc, BKTR_I2C_DATA_CTL, clock); 207 208 DELAY(I2C_DELAY); 209 210 return; 211} 212 213void bti2c_iic_setscl(device_t dev, int val) 214{ 215 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 216 int data; 217 218 data = INL(sc, BKTR_I2C_DATA_CTL) & 0x1; 219 220 if (val) 221 OUTL(sc, BKTR_I2C_DATA_CTL, 0x2 | data); 222 else 223 OUTL(sc, BKTR_I2C_DATA_CTL, data); 224 225 DELAY(I2C_DELAY); 226 227 return; 228} 229 230int 231bti2c_iic_getsda(device_t dev) 232{ 233 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 234 235 return (INL(sc,BKTR_I2C_DATA_CTL) & 0x1); 236} 237 238int 239bti2c_iic_getscl(device_t dev) 240{ 241 return (0); 242} 243 244static int 245bti2c_write(struct bktr_softc *sc, u_long data) 246{ 247 u_long x; 248 249 /* clear status bits */ 250 OUTL(sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); 251 252 BTI2C_DEBUG(printf("w%lx", data)); 253 254 /* write the address and data */ 255 OUTL(sc, BKTR_I2C_DATA_CTL, data); 256 257 /* wait for completion */ 258 for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 259 if ( INL(sc, BKTR_INT_STAT) & BT848_INT_I2CDONE ) 260 break; 261 } 262 263 /* check for ACK */ 264 if ( !x || !( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK) ) { 265 BTI2C_DEBUG(printf("%c%c", (!x)?'+':'-', 266 (!( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); 267 return (SMB_ENOACK); 268 } 269 BTI2C_DEBUG(printf("+")); 270 271 /* return OK */ 272 return( 0 ); 273} 274 275int 276bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte) 277{ 278 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 279 u_long data; 280 281 data = ((slave & 0xff) << 24) | ((byte & 0xff) << 16) | (u_char)cmd; 282 283 return (bti2c_write(sc, data)); 284} 285 286/* 287 * byte1 becomes low byte of word 288 * byte2 becomes high byte of word 289 */ 290int 291bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word) 292{ 293 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 294 u_long data; 295 char low, high; 296 297 low = (char)(word & 0xff); 298 high = (char)((word & 0xff00) >> 8); 299 300 data = ((slave & 0xff) << 24) | ((low & 0xff) << 16) | 301 ((high & 0xff) << 8) | BT848_DATA_CTL_I2CW3B | (u_char)cmd; 302 303 return (bti2c_write(sc, data)); 304} 305 306/* 307 * The Bt878 and Bt879 differed on the treatment of i2c commands 308 */ 309int 310bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte) 311{ 312 struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); 313 u_long x; 314 315 /* clear status bits */ 316 OUTL(sc,BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); 317 318 OUTL(sc,BKTR_I2C_DATA_CTL, ((slave & 0xff) << 24) | (u_char)cmd);; 319 320 BTI2C_DEBUG(printf("r%lx/", (u_long)(((slave & 0xff) << 24) | (u_char)cmd))); 321 322 /* wait for completion */ 323 for ( x = 0x7fffffff; x; --x ) { /* safety valve */ 324 if ( INL(sc,BKTR_INT_STAT) & BT848_INT_I2CDONE ) 325 break; 326 } 327 328 /* check for ACK */ 329 if ( !x || !(INL(sc,BKTR_INT_STAT) & BT848_INT_RACK) ) { 330 BTI2C_DEBUG(printf("r%c%c", (!x)?'+':'-', 331 (!( INL(sc,BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); 332 return (SMB_ENOACK); 333 } 334 335 *byte = (char)((INL(sc,BKTR_I2C_DATA_CTL) >> 8) & 0xff); 336 BTI2C_DEBUG(printf("r%x+", *byte)); 337 338 return (0); 339} 340
|
341DRIVER_MODULE(smbus, bktr, smbus_driver, smbus_devclass, 0, 0); 342 |
343#endif /* defined(BKTR_USE_FREEBSD_SMBUS) */
|