1164426Ssam/* 2164426Ssam * Copyright (c) 2006 Kevin Lo. All rights reserved. 3164426Ssam * 4164426Ssam * Redistribution and use in source and binary forms, with or without 5164426Ssam * modification, are permitted provided that the following conditions 6164426Ssam * are met: 7164426Ssam * 1. Redistributions of source code must retain the above copyright 8164426Ssam * notice, this list of conditions and the following disclaimer. 9164426Ssam * 2. Redistributions in binary form must reproduce the above copyright 10164426Ssam * notice, this list of conditions and the following disclaimer in the 11164426Ssam * documentation and/or other materials provided with the distribution. 12164426Ssam * 13164426Ssam * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 14164426Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15164426Ssam * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16164426Ssam * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 17164426Ssam * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18164426Ssam * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19164426Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20164426Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21164426Ssam * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22164426Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23164426Ssam * POSSIBILITY OF SUCH DAMAGE. 24164426Ssam */ 25164426Ssam 26164426Ssam#include <sys/cdefs.h> 27164426Ssam__FBSDID("$FreeBSD: releng/10.2/sys/arm/xscale/ixp425/ixp425_iic.c 236987 2012-06-13 04:38:09Z imp $"); 28164426Ssam 29164426Ssam#include <sys/param.h> 30164426Ssam#include <sys/systm.h> 31164426Ssam#include <sys/kernel.h> 32164426Ssam#include <sys/module.h> 33164426Ssam#include <sys/bus.h> 34164426Ssam#include <sys/uio.h> 35164426Ssam 36164426Ssam#include <arm/xscale/ixp425/ixp425reg.h> 37164426Ssam#include <arm/xscale/ixp425/ixp425var.h> 38164426Ssam#include <arm/xscale/ixp425/ixdp425reg.h> 39164426Ssam 40164426Ssam#include <dev/iicbus/iiconf.h> 41164426Ssam#include <dev/iicbus/iicbus.h> 42164426Ssam 43164426Ssam#include "iicbb_if.h" 44164426Ssam 45164426Ssam#define I2C_DELAY 10 46164426Ssam 47164426Ssam/* bit clr/set shorthands */ 48164426Ssam#define GPIO_CONF_CLR(sc, reg, mask) \ 49164426Ssam GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask)) 50164426Ssam#define GPIO_CONF_SET(sc, reg, mask) \ 51164426Ssam GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask)) 52164426Ssam 53164426Ssamstruct ixpiic_softc { 54164426Ssam device_t sc_dev; 55164426Ssam bus_space_tag_t sc_iot; 56164426Ssam bus_space_handle_t sc_gpio_ioh; 57164426Ssam 58164426Ssam device_t iicbb; 59164426Ssam}; 60164426Ssam 61164426Ssamstatic struct ixpiic_softc *ixpiic_sc = NULL; 62164426Ssam 63164426Ssamstatic int 64164426Ssamixpiic_probe(device_t dev) 65164426Ssam{ 66186352Ssam device_set_desc(dev, "IXP4XX GPIO-Based I2C Interface"); 67164426Ssam return (0); 68164426Ssam} 69164426Ssam 70164426Ssamstatic int 71164426Ssamixpiic_attach(device_t dev) 72164426Ssam{ 73164426Ssam struct ixpiic_softc *sc = device_get_softc(dev); 74164426Ssam struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); 75164426Ssam 76164426Ssam ixpiic_sc = sc; 77164426Ssam 78164426Ssam sc->sc_dev = dev; 79164426Ssam sc->sc_iot = sa->sc_iot; 80164426Ssam sc->sc_gpio_ioh = sa->sc_gpio_ioh; 81164426Ssam 82164426Ssam GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, 83164426Ssam GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT); 84164426Ssam GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, 85164426Ssam GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT); 86164426Ssam 87164426Ssam /* add generic bit-banging code */ 88164426Ssam if ((sc->iicbb = device_add_child(dev, "iicbb", -1)) == NULL) 89164426Ssam device_printf(dev, "could not add iicbb\n"); 90164426Ssam 91164426Ssam /* probe and attach the bit-banging code */ 92164426Ssam device_probe_and_attach(sc->iicbb); 93164426Ssam 94164426Ssam return (0); 95164426Ssam} 96164426Ssam 97164426Ssamstatic int 98194015Savgixpiic_callback(device_t dev, int index, caddr_t data) 99164426Ssam{ 100164426Ssam return (0); 101164426Ssam} 102164426Ssam 103236987Simpstatic int 104164426Ssamixpiic_getscl(device_t dev) 105164426Ssam{ 106164426Ssam struct ixpiic_softc *sc = ixpiic_sc; 107164426Ssam uint32_t reg; 108164426Ssam 109215319Sthompsa IXP4XX_GPIO_LOCK(); 110164426Ssam GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 111164426Ssam 112164426Ssam reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); 113215319Sthompsa IXP4XX_GPIO_UNLOCK(); 114164426Ssam return (reg & GPIO_I2C_SCL_BIT); 115164426Ssam} 116164426Ssam 117236987Simpstatic int 118164426Ssamixpiic_getsda(device_t dev) 119164426Ssam{ 120164426Ssam struct ixpiic_softc *sc = ixpiic_sc; 121164426Ssam uint32_t reg; 122164426Ssam 123215319Sthompsa IXP4XX_GPIO_LOCK(); 124164426Ssam GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 125164426Ssam 126164426Ssam reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR); 127215319Sthompsa IXP4XX_GPIO_UNLOCK(); 128164426Ssam return (reg & GPIO_I2C_SDA_BIT); 129164426Ssam} 130164426Ssam 131236987Simpstatic void 132194015Savgixpiic_setsda(device_t dev, int val) 133164426Ssam{ 134164426Ssam struct ixpiic_softc *sc = ixpiic_sc; 135164426Ssam 136215319Sthompsa IXP4XX_GPIO_LOCK(); 137164426Ssam GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT); 138164426Ssam if (val) 139164426Ssam GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 140164426Ssam else 141164426Ssam GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT); 142215319Sthompsa IXP4XX_GPIO_UNLOCK(); 143164426Ssam DELAY(I2C_DELAY); 144164426Ssam} 145164426Ssam 146236987Simpstatic void 147194015Savgixpiic_setscl(device_t dev, int val) 148164426Ssam{ 149164426Ssam struct ixpiic_softc *sc = ixpiic_sc; 150164426Ssam 151215319Sthompsa IXP4XX_GPIO_LOCK(); 152164426Ssam GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT); 153164426Ssam if (val) 154164426Ssam GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 155164426Ssam else 156164426Ssam GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT); 157215319Sthompsa IXP4XX_GPIO_UNLOCK(); 158164426Ssam DELAY(I2C_DELAY); 159164426Ssam} 160164426Ssam 161164426Ssamstatic int 162164426Ssamixpiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 163164426Ssam{ 164164426Ssam /* reset bus */ 165164426Ssam ixpiic_setsda(dev, 1); 166164426Ssam ixpiic_setscl(dev, 1); 167164426Ssam 168164426Ssam return (IIC_ENOADDR); 169164426Ssam} 170164426Ssam 171164426Ssamstatic device_method_t ixpiic_methods[] = { 172164426Ssam /* device interface */ 173164426Ssam DEVMETHOD(device_probe, ixpiic_probe), 174164426Ssam DEVMETHOD(device_attach, ixpiic_attach), 175164426Ssam 176164426Ssam /* iicbb interface */ 177164426Ssam DEVMETHOD(iicbb_callback, ixpiic_callback), 178164426Ssam DEVMETHOD(iicbb_setsda, ixpiic_setsda), 179164426Ssam DEVMETHOD(iicbb_setscl, ixpiic_setscl), 180164426Ssam DEVMETHOD(iicbb_getsda, ixpiic_getsda), 181164426Ssam DEVMETHOD(iicbb_getscl, ixpiic_getscl), 182164426Ssam DEVMETHOD(iicbb_reset, ixpiic_reset), 183164426Ssam 184164426Ssam { 0, 0 } 185164426Ssam}; 186164426Ssam 187164426Ssamstatic driver_t ixpiic_driver = { 188164426Ssam "ixpiic", 189164426Ssam ixpiic_methods, 190164426Ssam sizeof(struct ixpiic_softc), 191164426Ssam}; 192164426Ssamstatic devclass_t ixpiic_devclass; 193164426Ssam 194164426SsamDRIVER_MODULE(ixpiic, ixp, ixpiic_driver, ixpiic_devclass, 0, 0); 195181303SjhbDRIVER_MODULE(iicbb, ixpiic, iicbb_driver, iicbb_devclass, 0, 0); 196