/*- * Copyright 2003 John-Mark Gurney * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: zr_i2c.c,v 1.8 2003/04/30 16:22:47 jmg Exp $ */ /* * Cribbed from lpbb, bktr_i2c and iicbb */ #include /* defines used in kernel.h */ #include /* uprintf */ #include #include #include #include /* structs, prototypes for pci bus stuff */ #include #include #include #include #include #include #include int zr_i2c_attach(device_t dev) { struct zr_softc *zr = (struct zr_softc *)device_get_softc(dev); struct zr_i2c_softc *i2c = &zr->zr_i2c_sc; if (!mtx_initialized(&i2c->zi_bus_owned)) mtx_init(&i2c->zi_bus_owned, device_get_nameunit(dev), "zr_i2c", MTX_DEF); else printf("zi_bus_owned already initalized\n"); /* add generic bit-banging code */ i2c->zi_iicbb = device_add_child(dev, "iicbb", -1); if (i2c->zi_iicbb == NULL) return ENXIO; device_probe_and_attach(i2c->zi_iicbb); return (0); } int zr_i2c_detach(device_t dev) { struct zr_softc *zr = (struct zr_softc *)device_get_softc(dev); struct zr_i2c_softc *i2c = &zr->zr_i2c_sc; int error = 0; if ((error = device_detach(i2c->zi_iicbb))) goto error; if ((error = device_delete_child(dev, i2c->zi_iicbb))) goto error; i2c->zi_iicbb = NULL; mtx_destroy(&i2c->zi_bus_owned); error: return error; } int zr_i2c_callback(device_t dev, int index, caddr_t *data) { struct zr_softc *zr = (struct zr_softc *)device_get_softc(dev); struct zr_i2c_softc *i2c = &zr->zr_i2c_sc; int error = 0; switch (index) { case IIC_REQUEST_BUS: if (mtx_trylock(&i2c->zi_bus_owned) == 0) error = EWOULDBLOCK; break; case IIC_RELEASE_BUS: if (mtx_owned(&i2c->zi_bus_owned) == 0) error = EINVAL; else mtx_unlock(&i2c->zi_bus_owned); break; } return error; } static void zr_i2c_set(device_t dev, uint32_t pos, char val) { struct zr_softc *zr = device_get_softc(dev); int res; res = zr_read_asrs(zr, ZR_I2C_REG); if (val == 0) zr_write_asrs(zr, ZR_I2C_REG, res&~pos); else zr_write_asrs(zr, ZR_I2C_REG, res|pos); } void zr_i2c_setscl(device_t dev, char val) { zr_i2c_set(dev, ZR_I2C_SCL, val); } void zr_i2c_setsda(device_t dev, char val) { zr_i2c_set(dev, ZR_I2C_SDA, val); } int zr_i2c_getscl(device_t dev) { ZR_SOFTC; return ZR_READ_ASR(zr, ZR_I2C_REG, i2c, SCL); } int zr_i2c_getsda(device_t dev) { ZR_SOFTC; return ZR_READ_ASR(zr, ZR_I2C_REG, i2c, SDA); } int zr_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { /* reset bus */ zr_i2c_setsda(dev, 1); zr_i2c_setscl(dev, 1); return (IIC_ENOADDR); }