iicbb.c revision 61722
153553Stanimura/*- 253553Stanimura * Copyright (c) 1998 Nicolas Souchu 353553Stanimura * All rights reserved. 453553Stanimura * 553553Stanimura * Redistribution and use in source and binary forms, with or without 653553Stanimura * modification, are permitted provided that the following conditions 753553Stanimura * are met: 853553Stanimura * 1. Redistributions of source code must retain the above copyright 953553Stanimura * notice, this list of conditions and the following disclaimer. 1053553Stanimura * 2. Redistributions in binary form must reproduce the above copyright 1153553Stanimura * notice, this list of conditions and the following disclaimer in the 1253553Stanimura * documentation and/or other materials provided with the distribution. 1353553Stanimura * 1453553Stanimura * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1553553Stanimura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1653553Stanimura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1753553Stanimura * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1853553Stanimura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1953553Stanimura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2053553Stanimura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2153553Stanimura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2253553Stanimura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2353553Stanimura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2453553Stanimura * SUCH DAMAGE. 2553553Stanimura * 2653553Stanimura * $FreeBSD: head/sys/dev/iicbus/iicbb.c 61722 2000-06-16 07:20:29Z jake $ 2753553Stanimura * 2853553Stanimura */ 2953553Stanimura 3054462Scg/* 3162483Scg * Generic I2C bit-banging code 3253553Stanimura * 3354824Scg * Example: 3454824Scg * 3554824Scg * iicbus 3654824Scg * / \ 3754824Scg * iicbb pcf 3854824Scg * | \ 3954824Scg * bti2c lpbb 4054824Scg * 4154824Scg * From Linux I2C generic interface 4254824Scg * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 4353553Stanimura * 4453553Stanimura * TODO: port Peter's generic bit-banging code <dufault@hda.com> 4553553Stanimura */ 4654462Scg 4754824Scg#include <sys/param.h> 4854824Scg#include <sys/kernel.h> 4954824Scg#include <sys/systm.h> 5054462Scg#include <sys/module.h> 5154824Scg#include <sys/bus.h> 5254824Scg#include <sys/uio.h> 5354824Scg 5454462Scg#include <machine/clock.h> 5554824Scg 5654824Scg#include <dev/iicbus/iiconf.h> 5754824Scg#include <dev/iicbus/iicbus.h> 5854462Scg 5954824Scg#include <dev/smbus/smbconf.h> 6054824Scg 6154824Scg#include "iicbus_if.h" 6254824Scg#include "iicbb_if.h" 6354462Scg 6453553Stanimurastruct iicbb_softc { 6553553Stanimura int dummy; 6653553Stanimura}; 6753553Stanimura 6854824Scgstatic int iicbb_probe(device_t); 6954824Scgstatic int iicbb_attach(device_t); 7053553Stanimurastatic int iicbb_print_child(device_t, device_t); 7154462Scg 7253553Stanimurastatic int iicbb_callback(device_t, int, caddr_t); 7354462Scgstatic int iicbb_start(device_t, u_char, int); 7454824Scgstatic int iicbb_stop(device_t); 7554824Scgstatic int iicbb_write(device_t, char *, int, int *, int); 7654824Scgstatic int iicbb_read(device_t, char *, int, int *, int, int); 7754824Scgstatic int iicbb_reset(device_t, u_char, u_char, u_char *); 7854824Scg 7953553Stanimurastatic device_method_t iicbb_methods[] = { 8054462Scg /* device interface */ 8154462Scg DEVMETHOD(device_probe, iicbb_probe), 8253553Stanimura DEVMETHOD(device_attach, iicbb_attach), 8353553Stanimura DEVMETHOD(device_detach, bus_generic_detach), 8453553Stanimura 8554462Scg /* bus interface */ 8654462Scg DEVMETHOD(bus_print_child, iicbb_print_child), 8760711Snyan 8860711Snyan /* iicbus interface */ 8960711Snyan DEVMETHOD(iicbus_callback, iicbb_callback), 9060711Snyan DEVMETHOD(iicbus_start, iicbb_start), 9160711Snyan DEVMETHOD(iicbus_repeated_start, iicbb_start), 9260711Snyan DEVMETHOD(iicbus_stop, iicbb_stop), 9360711Snyan DEVMETHOD(iicbus_write, iicbb_write), 9460711Snyan DEVMETHOD(iicbus_read, iicbb_read), 9560711Snyan DEVMETHOD(iicbus_reset, iicbb_reset), 9660711Snyan 9760711Snyan { 0, 0 } 9860711Snyan}; 9960711Snyan 10060711Snyanstatic driver_t iicbb_driver = { 10154462Scg "iicbb", 10254462Scg iicbb_methods, 10354462Scg sizeof(struct iicbb_softc), 10454462Scg}; 10554462Scg 10654462Scgstatic devclass_t iicbb_devclass; 10754462Scg 10854462Scgstatic int iicbb_probe(device_t dev) 10954462Scg{ 11054462Scg device_set_desc(dev, "I2C generic bit-banging driver"); 11154462Scg 11254462Scg return (0); 11354462Scg} 11454462Scg 11554462Scgstatic int iicbb_attach(device_t dev) 11654462Scg{ 11754462Scg return (0); 11854462Scg} 11954462Scg 12054462Scgstatic int 12154462Scgiicbb_print_child(device_t bus, device_t dev) 12254462Scg{ 12354462Scg int error; 12454462Scg int retval = 0; 12554462Scg u_char oldaddr; 12654462Scg 12754462Scg retval += bus_print_child_header(bus, dev); 12854462Scg /* retrieve the interface I2C address */ 12954462Scg error = IICBB_RESET(device_get_parent(bus), IIC_FASTEST, 0, &oldaddr); 13054462Scg if (error == IIC_ENOADDR) { 13154462Scg retval += printf(" on %s master-only\n", 13254462Scg device_get_nameunit(bus)); 13354462Scg } else { 13454462Scg /* restore the address */ 13554462Scg IICBB_RESET(device_get_parent(bus), IIC_FASTEST, oldaddr, NULL); 13654462Scg 13754462Scg retval += printf(" on %s addr 0x%x\n", 13854462Scg device_get_nameunit(bus), oldaddr & 0xff); 13954462Scg } 14054462Scg 14154462Scg return (retval); 14254462Scg} 14354462Scg 14454462Scg#define I2C_SET(dev,ctrl,data) \ 14554462Scg IICBB_SETLINES(device_get_parent(dev), ctrl, data) 14654462Scg 14754462Scg#define I2C_GET(dev) (IICBB_GETDATALINE(device_get_parent(dev))) 14854462Scg 14954462Scgstatic int i2c_debug = 0; 15054462Scg#define I2C_DEBUG(x) if (i2c_debug) (x) 15154462Scg 15254462Scgstatic void iicbb_one(device_t dev) 15354462Scg{ 15454462Scg I2C_SET(dev,0,1); 15554462Scg I2C_SET(dev,1,1); 15654462Scg I2C_SET(dev,0,1); 15754462Scg return; 15854462Scg} 15954462Scg 16054462Scgstatic void iicbb_zero(device_t dev) 16154462Scg{ 16254462Scg I2C_SET(dev,0,0); 16354462Scg I2C_SET(dev,1,0); 16454462Scg I2C_SET(dev,0,0); 16554462Scg return; 16654462Scg} 16754462Scg 16854462Scg/* 16954462Scg * Waiting for ACKNOWLEDGE. 17054462Scg * 17154462Scg * When a chip is being addressed or has received data it will issue an 17254462Scg * ACKNOWLEDGE pulse. Therefore the MASTER must release the DATA line 17354462Scg * (set it to high level) and then release the CLOCK line. 17454462Scg * Now it must wait for the SLAVE to pull the DATA line low. 17554462Scg * Actually on the bus this looks like a START condition so nothing happens 17654462Scg * because of the fact that the IC's that have not been addressed are doing 17754462Scg * nothing. 17854462Scg * 17954462Scg * When the SLAVE has pulled this line low the MASTER will take the CLOCK 18054462Scg * line low and then the SLAVE will release the SDA (data) line. 18154462Scg */ 18254462Scgstatic int iicbb_ack(device_t dev, int timeout) 18354462Scg{ 18454462Scg int noack; 18554462Scg int k = timeout/10; 18654462Scg 18754462Scg I2C_SET(dev,0,1); 18854462Scg I2C_SET(dev,1,1); 18954462Scg 19054462Scg do { 19154462Scg noack = I2C_GET(dev); 19254462Scg if (!noack) 19354462Scg break; 19454462Scg DELAY(10); /* XXX wait 10us */ 19554462Scg } while (k--); 19654462Scg 19754462Scg I2C_SET(dev,0,1); 19854462Scg I2C_DEBUG(printf("%c ",noack?'-':'+')); 19954462Scg 20054462Scg return (noack); 20154462Scg} 20254462Scg 20354462Scgstatic void iicbb_sendbyte(device_t dev, u_char data) 20454462Scg{ 20554462Scg int i; 20654462Scg 20754462Scg I2C_SET(dev,0,0); 20854118Stanimura for (i=7; i>=0; i--) 20954961Speter (data&(1<<i)) ? iicbb_one(dev) : iicbb_zero(dev); 21054961Speter I2C_DEBUG(printf("w%02x",(int)data)); 21154961Speter return; 21254961Speter} 21354961Speter 21454961Speterstatic u_char iicbb_readbyte(device_t dev, int last) 21554961Speter{ 21654462Scg int i; 21758385Scg unsigned char data=0; 21854961Speter 21958385Scg I2C_SET(dev,0,1); 22054462Scg for (i=7; i>=0; i--) 22156721Sgallatin { 22254961Speter I2C_SET(dev,1,1); 22361061Skuriyama if (I2C_GET(dev)) 22454961Speter data |= (1<<i); 22561569Sbrian I2C_SET(dev,0,1); 22654961Speter } 22755848Sdeischen last ? iicbb_one(dev) : iicbb_zero(dev); 22854961Speter I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+')); 22954961Speter return data; 23054961Speter} 23164845Scg 23254118Stanimurastatic int iicbb_callback(device_t dev, int index, caddr_t data) 23354118Stanimura{ 23454118Stanimura return (IICBB_CALLBACK(device_get_parent(dev), index, data)); 23553553Stanimura} 23653553Stanimura 23753553Stanimurastatic int iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) 23854462Scg{ 23956774Scg return (IICBB_RESET(device_get_parent(dev), speed, addr, oldaddr)); 24056774Scg} 24156774Scg 24256774Scgstatic int iicbb_start(device_t dev, u_char slave, int timeout) 24356774Scg{ 24456774Scg int error; 24556774Scg 24654462Scg I2C_DEBUG(printf("<")); 24754462Scg 24854462Scg I2C_SET(dev,0,1); 24954462Scg I2C_SET(dev,1,1); 25054462Scg I2C_SET(dev,1,0); 25153553Stanimura I2C_SET(dev,0,0); 25260711Snyan 25360711Snyan /* send address */ 25460711Snyan iicbb_sendbyte(dev, slave); 25560711Snyan 25654462Scg /* check for ack */ 25754462Scg if (iicbb_ack(dev, timeout)) { 25860711Snyan error = IIC_ENOACK; 25954462Scg goto error; 26060711Snyan } 26160711Snyan 26260711Snyan return(0); 26354462Scg 26454462Scgerror: 26554462Scg iicbb_stop(dev); 26654462Scg return (error); 26754462Scg} 26854462Scg 26954462Scgstatic int iicbb_stop(device_t dev) 27054462Scg{ 27154462Scg I2C_SET(dev,0,0); 27254462Scg I2C_SET(dev,1,0); 27354462Scg I2C_SET(dev,1,1); 27454462Scg I2C_DEBUG(printf(">")); 27554462Scg return (0); 27654462Scg} 27754462Scg 27854462Scgstatic int iicbb_write(device_t dev, char * buf, int len, int *sent, 27954462Scg int timeout) 28054462Scg{ 28154462Scg int bytes, error = 0; 28254462Scg 28354462Scg bytes = 0; 28454462Scg while (len) { 28554462Scg /* send byte */ 28654462Scg iicbb_sendbyte(dev,(u_char)*buf++); 28754462Scg 28853553Stanimura /* check for ack */ 28953553Stanimura if (iicbb_ack(dev, timeout)) { 29053553Stanimura error = IIC_ENOACK; 29153553Stanimura goto error; 29253553Stanimura } 29354791Scg bytes ++; 29454462Scg len --; 29554462Scg } 29654118Stanimura 29754462Scgerror: 29854462Scg *sent = bytes; 29954824Scg return (error); 30053553Stanimura} 30154462Scg 30254462Scgstatic int iicbb_read(device_t dev, char * buf, int len, int *read, 30354462Scg int last, int delay) 30454462Scg{ 30554462Scg int bytes; 30653553Stanimura 30753553Stanimura bytes = 0; 30854462Scg while (len) { 30954791Scg /* XXX should insert delay here */ 31054462Scg *buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0); 31153553Stanimura 31254791Scg bytes ++; 31354462Scg len --; 31454791Scg } 31554462Scg 31654462Scg *read = bytes; 31754791Scg return (0); 31858385Scg} 31954462Scg 32054462ScgDRIVER_MODULE(iicbb, bti2c, iicbb_driver, iicbb_devclass, 0, 0); 32154462ScgDRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0); 32254462Scg