ixp425_iic.c revision 164426
1/* 2 * Copyright (c) 2006 Kevin Lo. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed for the NetBSD Project by 15 * Wasabi Systems, Inc. 16 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: head/sys/arm/xscale/ixp425/ixp425_iic.c 164426 2006-11-19 23:55:23Z sam $"); 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39#include <sys/module.h> 40#include <sys/bus.h> 41#include <sys/uio.h> 42 43#include <arm/xscale/ixp425/ixp425reg.h> 44#include <arm/xscale/ixp425/ixp425var.h> 45#include <arm/xscale/ixp425/ixdp425reg.h> 46 47#include <dev/iicbus/iiconf.h> 48#include <dev/iicbus/iicbus.h> 49 50#include "iicbb_if.h" 51 52#define I2C_DELAY 10 53 54/* bit clr/set shorthands */ 55#define GPIO_CONF_CLR(sc, reg, mask) \ 56 GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask)) 57#define GPIO_CONF_SET(sc, reg, mask) \ 58 GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask)) 59 60struct ixpiic_softc { 61 device_t sc_dev; 62 bus_space_tag_t sc_iot; 63 bus_space_handle_t sc_gpio_ioh; 64 65 device_t iicbb; 66}; 67 68static struct ixpiic_softc *ixpiic_sc = NULL; 69 70static int 71ixpiic_probe(device_t dev) 72{ 73 device_set_desc(dev, "IXP425 GPIO-Based I2C Interface"); 74 return (0); 75} 76 77static int 78ixpiic_attach(device_t dev) 79{ 80 struct ixpiic_softc *sc = device_get_softc(dev); 81 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); 82 83 ixpiic_sc = sc; 84 85 sc->sc_dev = dev; 86 sc->sc_iot = sa->sc_iot; 87 sc->sc_gpio_ioh = sa->sc_gpio_ioh; 88 89 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, 90 GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT); 91 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, 92 GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT); 93 94 /* add generic bit-banging code */ 95 if ((sc->iicbb = device_add_child(dev, "iicbb", -1)) == NULL) 96 device_printf(dev, "could not add iicbb\n"); 97 98 /* probe and attach the bit-banging code */ 99 device_probe_and_attach(sc->iicbb); 100 101 return (0); 102} 103 104static int 105ixpiic_callback(device_t dev, int index, caddr_t *data) 106{ 107 return (0); 108} 109 110static int 111ixpiic_getscl(device_t dev) 112{ 113 struct ixpiic_softc *sc = ixpiic_sc; 114 uint32_t reg; 115 116 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 117 118 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); 119 return (reg & GPIO_I2C_SCL_BIT); 120} 121 122static int 123ixpiic_getsda(device_t dev) 124{ 125 struct ixpiic_softc *sc = ixpiic_sc; 126 uint32_t reg; 127 128 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 129 130 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); 131 return (reg & GPIO_I2C_SDA_BIT); 132} 133 134static void 135ixpiic_setsda(device_t dev, char val) 136{ 137 struct ixpiic_softc *sc = ixpiic_sc; 138 139 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT); 140 if (val) 141 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 142 else 143 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 144 DELAY(I2C_DELAY); 145} 146 147static void 148ixpiic_setscl(device_t dev, char val) 149{ 150 struct ixpiic_softc *sc = ixpiic_sc; 151 152 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT); 153 if (val) 154 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 155 else 156 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 157 DELAY(I2C_DELAY); 158} 159 160static int 161ixpiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 162{ 163 /* reset bus */ 164 ixpiic_setsda(dev, 1); 165 ixpiic_setscl(dev, 1); 166 167 return (IIC_ENOADDR); 168} 169 170static device_method_t ixpiic_methods[] = { 171 /* device interface */ 172 DEVMETHOD(device_probe, ixpiic_probe), 173 DEVMETHOD(device_attach, ixpiic_attach), 174 175 /* iicbb interface */ 176 DEVMETHOD(iicbb_callback, ixpiic_callback), 177 DEVMETHOD(iicbb_setsda, ixpiic_setsda), 178 DEVMETHOD(iicbb_setscl, ixpiic_setscl), 179 DEVMETHOD(iicbb_getsda, ixpiic_getsda), 180 DEVMETHOD(iicbb_getscl, ixpiic_getscl), 181 DEVMETHOD(iicbb_reset, ixpiic_reset), 182 183 { 0, 0 } 184}; 185 186static driver_t ixpiic_driver = { 187 "ixpiic", 188 ixpiic_methods, 189 sizeof(struct ixpiic_softc), 190}; 191static devclass_t ixpiic_devclass; 192 193DRIVER_MODULE(ixpiic, ixp, ixpiic_driver, ixpiic_devclass, 0, 0); 194