iicbb is generic support for I2C bit-banging.
Other files: timeout management added to the I2C framework.
This commit is contained in:
parent
fbd78b40dd
commit
04f89a63cb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=40782
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: if_ic.c,v 1.1.1.11 1998/08/13 17:10:42 son Exp $
|
||||
* $Id: if_ic.c,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -213,7 +213,7 @@ icioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
iicbus_reset(parent, IIC_FASTEST);
|
||||
iicbus_reset(parent, IIC_FASTEST, 0, NULL);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iic.c,v 1.2 1998/09/04 17:53:35 nsouch Exp $
|
||||
* $Id: iic.c,v 1.3 1998/09/09 18:57:24 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
@ -219,7 +219,7 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
|
||||
|
||||
switch (cmd) {
|
||||
case I2CSTART:
|
||||
error = iicbus_start(parent, sc->sc_addr);
|
||||
error = iicbus_start(parent, sc->sc_addr, 0);
|
||||
break;
|
||||
|
||||
case I2CSTOP:
|
||||
@ -227,7 +227,7 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
|
||||
break;
|
||||
|
||||
case I2CRSTCARD:
|
||||
error = iicbus_reset(parent, 0);
|
||||
error = iicbus_reset(parent, 0, 0, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
323
sys/dev/iicbus/iicbb.c
Normal file
323
sys/dev/iicbus/iicbb.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*-
|
||||
* Copyright (c) 1998 Nicolas Souchu
|
||||
* 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$
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic I2C bit-banging code
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* iicbus
|
||||
* / \
|
||||
* iicbb pcf
|
||||
* | \
|
||||
* bti2c lpbb
|
||||
*
|
||||
* From Linux I2C generic interface
|
||||
* (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
|
||||
*
|
||||
* TODO: port Peter's generic bit-banging code <dufault@hda.com>
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <dev/iicbus/iiconf.h>
|
||||
#include <dev/iicbus/iicbus.h>
|
||||
|
||||
#include <dev/smbus/smbconf.h>
|
||||
|
||||
#include "iicbus_if.h"
|
||||
#include "iicbb_if.h"
|
||||
|
||||
struct iicbb_softc {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
static int iicbb_probe(device_t);
|
||||
static int iicbb_attach(device_t);
|
||||
static void iicbb_print_child(device_t, device_t);
|
||||
|
||||
static int iicbb_callback(device_t, int, caddr_t);
|
||||
static int iicbb_start(device_t, u_char, int);
|
||||
static int iicbb_stop(device_t);
|
||||
static int iicbb_write(device_t, char *, int, int *, int);
|
||||
static int iicbb_read(device_t, char *, int, int *, int, int);
|
||||
static int iicbb_reset(device_t, u_char, u_char, u_char *);
|
||||
|
||||
static device_method_t iicbb_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, iicbb_probe),
|
||||
DEVMETHOD(device_attach, iicbb_attach),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_print_child, iicbb_print_child),
|
||||
|
||||
/* iicbus interface */
|
||||
DEVMETHOD(iicbus_callback, iicbb_callback),
|
||||
DEVMETHOD(iicbus_start, iicbb_start),
|
||||
DEVMETHOD(iicbus_repeated_start, iicbb_start),
|
||||
DEVMETHOD(iicbus_stop, iicbb_stop),
|
||||
DEVMETHOD(iicbus_write, iicbb_write),
|
||||
DEVMETHOD(iicbus_read, iicbb_read),
|
||||
DEVMETHOD(iicbus_reset, iicbb_reset),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t iicbb_driver = {
|
||||
"iicbb",
|
||||
iicbb_methods,
|
||||
DRIVER_TYPE_MISC,
|
||||
sizeof(struct iicbb_softc),
|
||||
};
|
||||
|
||||
static devclass_t iicbb_devclass;
|
||||
|
||||
static int iicbb_probe(device_t dev)
|
||||
{
|
||||
device_set_desc(dev, "I2C generic bit-banging driver");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int iicbb_attach(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
iicbb_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
int error;
|
||||
u_char oldaddr;
|
||||
|
||||
/* retrieve the interface I2C address */
|
||||
error = IICBB_RESET(bus, IIC_FASTEST, 0, &oldaddr);
|
||||
if (error == IIC_ENOADDR) {
|
||||
printf(" on %s%d master-only", device_get_name(bus),
|
||||
device_get_unit(bus));
|
||||
|
||||
} else {
|
||||
/* restore the address */
|
||||
IICBB_RESET(bus, IIC_FASTEST, oldaddr, NULL);
|
||||
|
||||
printf(" on %s%d addr 0x%x", device_get_name(bus),
|
||||
device_get_unit(bus), oldaddr & 0xff);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define I2C_SET(dev,ctrl,data) \
|
||||
IICBB_SETLINES(device_get_parent(dev), ctrl, data)
|
||||
|
||||
#define I2C_GET(dev) (IICBB_GETDATALINE(device_get_parent(dev)))
|
||||
|
||||
static int i2c_debug = 0;
|
||||
#define I2C_DEBUG(x) if (i2c_debug) (x)
|
||||
|
||||
static void iicbb_one(device_t dev)
|
||||
{
|
||||
I2C_SET(dev,0,1);
|
||||
I2C_SET(dev,1,1);
|
||||
I2C_SET(dev,0,1);
|
||||
return;
|
||||
}
|
||||
|
||||
static void iicbb_zero(device_t dev)
|
||||
{
|
||||
I2C_SET(dev,0,0);
|
||||
I2C_SET(dev,1,0);
|
||||
I2C_SET(dev,0,0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Waiting for ACKNOWLEDGE.
|
||||
*
|
||||
* When a chip is being addressed or has received data it will issue an
|
||||
* ACKNOWLEDGE pulse. Therefore the MASTER must release the DATA line
|
||||
* (set it to high level) and then release the CLOCK line.
|
||||
* Now it must wait for the SLAVE to pull the DATA line low.
|
||||
* Actually on the bus this looks like a START condition so nothing happens
|
||||
* because of the fact that the IC's that have not been addressed are doing
|
||||
* nothing.
|
||||
*
|
||||
* When the SLAVE has pulled this line low the MASTER will take the CLOCK
|
||||
* line low and then the SLAVE will release the SDA (data) line.
|
||||
*/
|
||||
static int iicbb_ack(device_t dev, int timeout)
|
||||
{
|
||||
int noack;
|
||||
int k = timeout/10;
|
||||
|
||||
I2C_SET(dev,0,1);
|
||||
I2C_SET(dev,1,1);
|
||||
|
||||
do {
|
||||
noack = I2C_GET(dev);
|
||||
if (!noack)
|
||||
break;
|
||||
DELAY(10); /* XXX wait 10us */
|
||||
} while (k--);
|
||||
|
||||
I2C_SET(dev,0,1);
|
||||
I2C_DEBUG(printf("%c ",noack?'-':'+'));
|
||||
|
||||
return (noack);
|
||||
}
|
||||
|
||||
static void iicbb_sendbyte(device_t dev, u_char data)
|
||||
{
|
||||
int i;
|
||||
|
||||
I2C_SET(dev,0,0);
|
||||
for (i=7; i>=0; i--)
|
||||
(data&(1<<i)) ? iicbb_one(dev) : iicbb_zero(dev);
|
||||
I2C_DEBUG(printf("w%02x",(int)data));
|
||||
return;
|
||||
}
|
||||
|
||||
static u_char iicbb_readbyte(device_t dev, int last)
|
||||
{
|
||||
int i;
|
||||
unsigned char data=0;
|
||||
|
||||
I2C_SET(dev,0,1);
|
||||
for (i=7; i>=0; i--)
|
||||
{
|
||||
I2C_SET(dev,1,1);
|
||||
if (I2C_GET(dev))
|
||||
data |= (1<<i);
|
||||
I2C_SET(dev,0,1);
|
||||
}
|
||||
last ? iicbb_one(dev) : iicbb_zero(dev);
|
||||
I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+'));
|
||||
return data;
|
||||
}
|
||||
|
||||
static int iicbb_callback(device_t dev, int index, caddr_t data)
|
||||
{
|
||||
return (IICBB_CALLBACK(device_get_parent(dev), index, data));
|
||||
}
|
||||
|
||||
static int iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
|
||||
{
|
||||
return (IICBB_RESET(device_get_parent(dev), speed, addr, oldaddr));
|
||||
}
|
||||
|
||||
static int iicbb_start(device_t dev, u_char slave, int timeout)
|
||||
{
|
||||
int error;
|
||||
|
||||
I2C_DEBUG(printf("<"));
|
||||
|
||||
I2C_SET(dev,0,1);
|
||||
I2C_SET(dev,1,1);
|
||||
I2C_SET(dev,1,0);
|
||||
I2C_SET(dev,0,0);
|
||||
|
||||
/* send address */
|
||||
iicbb_sendbyte(dev, slave);
|
||||
|
||||
/* check for ack */
|
||||
if (iicbb_ack(dev, timeout)) {
|
||||
error = IIC_ENOACK;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
||||
error:
|
||||
iicbb_stop(dev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int iicbb_stop(device_t dev)
|
||||
{
|
||||
I2C_SET(dev,0,0);
|
||||
I2C_SET(dev,1,0);
|
||||
I2C_SET(dev,1,1);
|
||||
I2C_DEBUG(printf(">"));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int iicbb_write(device_t dev, char * buf, int len, int *sent,
|
||||
int timeout)
|
||||
{
|
||||
int bytes, error = 0;
|
||||
|
||||
bytes = 0;
|
||||
while (len) {
|
||||
/* send byte */
|
||||
iicbb_sendbyte(dev,(u_char)*buf++);
|
||||
|
||||
/* check for ack */
|
||||
if (iicbb_ack(dev, timeout)) {
|
||||
error = IIC_ENOACK;
|
||||
goto error;
|
||||
}
|
||||
bytes ++;
|
||||
len --;
|
||||
}
|
||||
|
||||
error:
|
||||
*sent = bytes;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int iicbb_read(device_t dev, char * buf, int len, int *read,
|
||||
int last, int delay)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = 0;
|
||||
while (len) {
|
||||
/* XXX should insert delay here */
|
||||
*buf++ = (char)iicbb_readbyte(dev, (len == 1) ? 1 : 0);
|
||||
|
||||
bytes ++;
|
||||
len --;
|
||||
}
|
||||
|
||||
*read = bytes;
|
||||
return (0);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(iicbb, bti2c, iicbb_driver, iicbb_devclass, 0, 0);
|
||||
DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0);
|
65
sys/dev/iicbus/iicbb_if.m
Normal file
65
sys/dev/iicbus/iicbb_if.m
Normal file
@ -0,0 +1,65 @@
|
||||
#
|
||||
# Copyright (c) 1998 Nicolas Souchu
|
||||
# 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$
|
||||
#
|
||||
|
||||
INTERFACE iicbb
|
||||
|
||||
#
|
||||
# iicbus callback
|
||||
#
|
||||
METHOD int callback {
|
||||
device_t dev;
|
||||
int index;
|
||||
caddr_t data;
|
||||
};
|
||||
|
||||
#
|
||||
# Set I2C bus lines
|
||||
#
|
||||
METHOD void setlines {
|
||||
device_t dev;
|
||||
int ctrl;
|
||||
int data;
|
||||
};
|
||||
|
||||
#
|
||||
# Get I2C bus lines
|
||||
#
|
||||
#
|
||||
METHOD int getdataline {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
#
|
||||
# Reset interface
|
||||
#
|
||||
METHOD int reset {
|
||||
device_t dev;
|
||||
u_char speed;
|
||||
u_char addr;
|
||||
u_char *oldaddr;
|
||||
};
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iicbus.c,v 1.1.2.7 1998/08/29 16:54:16 son Exp $
|
||||
* $Id: iicbus.c,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -54,6 +54,7 @@ struct iicbus_device {
|
||||
int iicd_class; /* driver or slave device class */
|
||||
const char *iicd_desc; /* device descriptor */
|
||||
u_char iicd_addr; /* address of the device */
|
||||
int iicd_waitack; /* wait for ack timeout or delay */
|
||||
int iicd_alive; /* 1 if device found */
|
||||
};
|
||||
|
||||
@ -61,8 +62,8 @@ struct iicbus_device {
|
||||
* Common I2C addresses
|
||||
*/
|
||||
#define I2C_GENERAL_CALL 0x0
|
||||
#define I2C_MASTER_ADDRESS 0xaa
|
||||
#define I2C_INET_ADDRESS 0xaa
|
||||
#define PCF_MASTER_ADDRESS 0xaa
|
||||
#define FIRST_SLAVE_ADDR 0x2
|
||||
|
||||
#define MAXSLAVE 256
|
||||
|
||||
@ -74,11 +75,13 @@ struct iicbus_device {
|
||||
* list of known devices
|
||||
*/
|
||||
struct iicbus_device iicbus_children[] = {
|
||||
{ "iic", IICBUS_DRIVER_CLASS, "General Call", I2C_GENERAL_CALL },
|
||||
{ "iicsmb", IICBUS_DRIVER_CLASS, "I2C to SMB bridge" },
|
||||
{ "iic", IICBUS_DEVICE_CLASS, "PCF8574 I2C to 8 bits parallel i/o", 64},
|
||||
{ "iic", IICBUS_DEVICE_CLASS, "PCF8584 as slave", I2C_MASTER_ADDRESS },
|
||||
{ "ic", IICBUS_DEVICE_CLASS, "network interface", I2C_INET_ADDRESS },
|
||||
{ "iic", IICBUS_DEVICE_CLASS, "PCF8584 as slave", PCF_MASTER_ADDRESS },
|
||||
{ "ic", IICBUS_DEVICE_CLASS, "network interface", PCF_MASTER_ADDRESS },
|
||||
#if 0
|
||||
{ "iic", IICBUS_DRIVER_CLASS, "General Call", I2C_GENERAL_CALL },
|
||||
#endif
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@ -91,6 +94,7 @@ static int iicbus_probe(device_t);
|
||||
static int iicbus_attach(device_t);
|
||||
static void iicbus_print_child(device_t, device_t);
|
||||
static int iicbus_read_ivar(device_t , device_t, int, u_long *);
|
||||
static int iicbus_write_ivar(device_t , device_t, int, u_long);
|
||||
|
||||
static device_method_t iicbus_methods[] = {
|
||||
/* device interface */
|
||||
@ -102,7 +106,7 @@ static device_method_t iicbus_methods[] = {
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_print_child, iicbus_print_child),
|
||||
DEVMETHOD(bus_read_ivar, iicbus_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_write_ivar, iicbus_write_ivar),
|
||||
DEVMETHOD(bus_create_intr, bus_generic_create_intr),
|
||||
DEVMETHOD(bus_connect_intr, bus_generic_connect_intr),
|
||||
|
||||
@ -116,50 +120,85 @@ static driver_t iicbus_driver = {
|
||||
sizeof(struct iicbus_softc),
|
||||
};
|
||||
|
||||
/*
|
||||
* At 'probe' time, we add all the devices which we know about to the
|
||||
* bus. The generic attach routine will probe and attach them if they
|
||||
* are alive.
|
||||
*/
|
||||
static int
|
||||
iicbus_probe(device_t dev)
|
||||
{
|
||||
struct iicbus_softc *sc = device_get_softc(dev);
|
||||
struct iicbus_device *iicdev;
|
||||
device_t child;
|
||||
/* always present if probed */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* XXX should query parent */
|
||||
sc->ownaddr = I2C_MASTER_ADDRESS;
|
||||
#define MAXADDR 256
|
||||
static int iicdev_found[MAXADDR];
|
||||
|
||||
iicbus_reset(dev, IIC_FASTEST);
|
||||
static int
|
||||
iic_probe_device(device_t dev, u_char addr)
|
||||
{
|
||||
int count;
|
||||
char byte;
|
||||
|
||||
for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) {
|
||||
|
||||
/* probe devices, not drivers */
|
||||
switch (iicdev->iicd_class) {
|
||||
case IICBUS_DEVICE_CLASS:
|
||||
if (!iicbus_start(dev, iicdev->iicd_addr)) {
|
||||
iicbus_stop(dev);
|
||||
iicdev->iicd_alive = 1;
|
||||
}
|
||||
break;
|
||||
case IICBUS_DRIVER_CLASS:
|
||||
iicdev->iicd_addr = sc->ownaddr;
|
||||
break;
|
||||
default:
|
||||
panic("%s: unknown class!", __FUNCTION__);
|
||||
if ((addr & 1) == 0) {
|
||||
/* is device writable? */
|
||||
if (!iicbus_start(dev, (u_char)addr, 0)) {
|
||||
iicbus_stop(dev);
|
||||
return (1);
|
||||
}
|
||||
|
||||
child = device_add_child(dev, iicdev->iicd_name, -1, iicdev);
|
||||
device_set_desc(child, iicdev->iicd_desc);
|
||||
} else {
|
||||
/* is device readable? */
|
||||
if (!iicbus_block_read(dev, (u_char)addr, &byte, 1, &count))
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We add all the devices which we know about.
|
||||
* The generic attach routine will attach them if they are alive.
|
||||
*/
|
||||
static int
|
||||
iicbus_attach(device_t dev)
|
||||
{
|
||||
struct iicbus_softc *sc = device_get_softc(dev);
|
||||
struct iicbus_device *iicdev;
|
||||
device_t child;
|
||||
int addr, count;
|
||||
char byte;
|
||||
|
||||
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
|
||||
|
||||
printf("Probing for devices on iicbus%d:", device_get_unit(dev));
|
||||
|
||||
/* probe any devices */
|
||||
for (addr = FIRST_SLAVE_ADDR; addr < MAXADDR; addr++) {
|
||||
if (iic_probe_device(dev, (u_char)addr)) {
|
||||
printf(" <%x>", addr);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* attach known devices */
|
||||
for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) {
|
||||
/* probe devices, not drivers */
|
||||
switch (iicdev->iicd_class) {
|
||||
case IICBUS_DEVICE_CLASS:
|
||||
if (iic_probe_device(dev, iicdev->iicd_addr))
|
||||
iicdev->iicd_alive = 1;
|
||||
break;
|
||||
|
||||
case IICBUS_DRIVER_CLASS:
|
||||
iicdev->iicd_alive = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("%s: unknown class!", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (iicdev->iicd_alive) {
|
||||
child = device_add_child(dev, iicdev->iicd_name,
|
||||
-1, iicdev);
|
||||
device_set_desc(child, iicdev->iicd_desc);
|
||||
}
|
||||
}
|
||||
bus_generic_attach(dev);
|
||||
|
||||
return (0);
|
||||
@ -171,6 +210,18 @@ iicbus_generic_intr(device_t dev, int event, char *buf)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
iicbus_null_callback(device_t dev, int index, caddr_t data)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
iicbus_null_repeated_start(device_t dev, u_char addr)
|
||||
{
|
||||
return (IIC_ENOTSUPP);
|
||||
}
|
||||
|
||||
static void
|
||||
iicbus_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
@ -178,9 +229,8 @@ iicbus_print_child(device_t bus, device_t dev)
|
||||
|
||||
switch (iicdev->iicd_class) {
|
||||
case IICBUS_DEVICE_CLASS:
|
||||
printf(" on %s%d addr %d %s", device_get_name(bus),
|
||||
device_get_unit(bus), iicdev->iicd_addr,
|
||||
(iicdev->iicd_alive) ? "found" : "not found");
|
||||
printf(" on %s%d addr 0x%x", device_get_name(bus),
|
||||
device_get_unit(bus), iicdev->iicd_addr);
|
||||
break;
|
||||
|
||||
case IICBUS_DRIVER_CLASS:
|
||||
@ -212,4 +262,19 @@ iicbus_read_ivar(device_t bus, device_t dev, int index, u_long* result)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_write_ivar(device_t bus, device_t dev, int index, u_long val)
|
||||
{
|
||||
struct iicbus_device* iicdev = DEVTOIICBUS(dev);
|
||||
|
||||
switch (index) {
|
||||
default:
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
|
||||
DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);
|
||||
DRIVER_MODULE(iicbus, bti2c, iicbus_driver, iicbus_devclass, 0, 0);
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iicbus.h,v 1.1.2.3 1998/08/13 17:10:43 son Exp $
|
||||
* $Id: iicbus.h,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __IICBUS_H
|
||||
@ -31,7 +31,6 @@
|
||||
|
||||
struct iicbus_softc {
|
||||
|
||||
u_char ownaddr; /* address of the adapter */
|
||||
device_t owner; /* iicbus owner device structure */
|
||||
};
|
||||
|
||||
|
@ -23,13 +23,13 @@
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $Id: iicbus_if.m,v 1.1.2.4 1998/08/13 17:10:43 son Exp $
|
||||
# $Id: iicbus_if.m,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
#
|
||||
|
||||
INTERFACE iicbus
|
||||
|
||||
#
|
||||
# Interprete interrupt
|
||||
# Interpret interrupt
|
||||
#
|
||||
METHOD int intr {
|
||||
device_t dev;
|
||||
@ -37,12 +37,22 @@ METHOD int intr {
|
||||
char *buf;
|
||||
};
|
||||
|
||||
#
|
||||
# iicbus callback
|
||||
#
|
||||
METHOD int callback {
|
||||
device_t dev;
|
||||
int index;
|
||||
caddr_t data;
|
||||
};
|
||||
|
||||
#
|
||||
# Send REPEATED_START condition
|
||||
#
|
||||
METHOD int repeated_start {
|
||||
device_t dev;
|
||||
u_char slave;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
#
|
||||
@ -51,6 +61,7 @@ METHOD int repeated_start {
|
||||
METHOD int start {
|
||||
device_t dev;
|
||||
u_char slave;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
#
|
||||
@ -68,6 +79,8 @@ METHOD int read {
|
||||
char *buf;
|
||||
int len;
|
||||
int *bytes;
|
||||
int last;
|
||||
int delay;
|
||||
};
|
||||
|
||||
#
|
||||
@ -78,6 +91,7 @@ METHOD int write {
|
||||
char *buf;
|
||||
int len;
|
||||
int *bytes;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
#
|
||||
@ -86,4 +100,6 @@ METHOD int write {
|
||||
METHOD int reset {
|
||||
device_t dev;
|
||||
u_char speed;
|
||||
u_char addr;
|
||||
u_char *oldaddr;
|
||||
};
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iiconf.c,v 1.1.1.11 1998/08/29 17:02:05 son Exp $
|
||||
* $Id: iiconf.c,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
@ -71,6 +71,28 @@ iicbus_alloc_bus(device_t parent)
|
||||
return (child);
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_poll(struct iicbus_softc *sc, int how)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (how) {
|
||||
case (IIC_WAIT | IIC_INTR):
|
||||
error = tsleep(sc, IICPRI|PCATCH, "iicreq", 0);
|
||||
break;
|
||||
|
||||
case (IIC_WAIT | IIC_NOINTR):
|
||||
error = tsleep(sc, IICPRI, "iicreq", 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EWOULDBLOCK);
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* iicbus_request_bus()
|
||||
*
|
||||
@ -84,25 +106,20 @@ iicbus_request_bus(device_t bus, device_t dev, int how)
|
||||
struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
|
||||
int s, error = 0;
|
||||
|
||||
/* first, ask the underlying layers if the request is ok */
|
||||
do {
|
||||
error = IICBUS_CALLBACK(device_get_parent(bus),
|
||||
IIC_REQUEST_BUS, (caddr_t)&how);
|
||||
if (error)
|
||||
error = iicbus_poll(sc, how);
|
||||
} while (error);
|
||||
|
||||
while (!error) {
|
||||
s = splhigh();
|
||||
if (sc->owner) {
|
||||
splx(s);
|
||||
|
||||
switch (how) {
|
||||
case (IIC_WAIT | IIC_INTR):
|
||||
error = tsleep(sc, IICPRI|PCATCH, "iicreq", 0);
|
||||
break;
|
||||
|
||||
case (IIC_WAIT | IIC_NOINTR):
|
||||
error = tsleep(sc, IICPRI, "iicreq", 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EWOULDBLOCK);
|
||||
break;
|
||||
}
|
||||
|
||||
error = iicbus_poll(sc, how);
|
||||
} else {
|
||||
sc->owner = dev;
|
||||
|
||||
@ -123,7 +140,13 @@ int
|
||||
iicbus_release_bus(device_t bus, device_t dev)
|
||||
{
|
||||
struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
|
||||
int s;
|
||||
int s, error;
|
||||
|
||||
/* first, ask the underlying layers if the release is ok */
|
||||
error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
s = splhigh();
|
||||
if (sc->owner != dev) {
|
||||
@ -151,10 +174,10 @@ iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent)
|
||||
u_char addr = slave & ~LSB;
|
||||
int error;
|
||||
|
||||
if ((error = iicbus_start(bus, addr)))
|
||||
if ((error = iicbus_start(bus, addr, 0)))
|
||||
return (error);
|
||||
|
||||
error = iicbus_write(bus, buf, len, sent);
|
||||
error = iicbus_write(bus, buf, len, sent, 0);
|
||||
|
||||
iicbus_stop(bus);
|
||||
|
||||
@ -172,12 +195,12 @@ iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read)
|
||||
u_char addr = slave | LSB;
|
||||
int error;
|
||||
|
||||
if ((error = iicbus_start(bus, addr)))
|
||||
if ((error = iicbus_start(bus, addr, 0)))
|
||||
return (error);
|
||||
|
||||
error = iicbus_read(bus, buf, len, read);
|
||||
error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0);
|
||||
|
||||
/* STOP condition sent at adapter level */
|
||||
iicbus_stop(bus);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -197,11 +220,3 @@ iicbus_get_addr(device_t dev)
|
||||
|
||||
return ((u_char)addr);
|
||||
}
|
||||
|
||||
u_char
|
||||
iicbus_get_own_address(device_t bus)
|
||||
{
|
||||
struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
|
||||
|
||||
return (sc->ownaddr);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iiconf.h,v 1.1.1.10 1998/08/13 17:10:43 son Exp $
|
||||
* $Id: iiconf.h,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*/
|
||||
#ifndef __IICONF_H
|
||||
#define __IICONF_H
|
||||
@ -59,6 +59,14 @@
|
||||
#define IIC_FAST 0x2
|
||||
#define IIC_FASTEST 0x3
|
||||
|
||||
#define IIC_LAST_READ 0x1
|
||||
|
||||
/*
|
||||
* callback index
|
||||
*/
|
||||
#define IIC_REQUEST_BUS 0x1
|
||||
#define IIC_RELEASE_BUS 0x2
|
||||
|
||||
/*
|
||||
* interrupt events
|
||||
*/
|
||||
@ -81,6 +89,8 @@
|
||||
#define IIC_ESTATUS 0x5 /* status error */
|
||||
#define IIC_EUNDERFLOW 0x6 /* slave ready for more data */
|
||||
#define IIC_EOVERFLOW 0x7 /* too much data */
|
||||
#define IIC_ENOTSUPP 0x8 /* request not supported */
|
||||
#define IIC_ENOADDR 0x9 /* no address assigned to the interface */
|
||||
|
||||
/*
|
||||
* ivars codes
|
||||
@ -93,23 +103,25 @@ extern device_t iicbus_alloc_bus(device_t);
|
||||
|
||||
extern void iicbus_intr(device_t, int, char *);
|
||||
|
||||
#define iicbus_repeated_start(bus,slave) \
|
||||
(IICBUS_REPEATED_START(device_get_parent(bus), slave))
|
||||
#define iicbus_start(bus,slave) \
|
||||
(IICBUS_START(device_get_parent(bus), slave))
|
||||
extern int iicbus_null_repeated_start(device_t, u_char);
|
||||
extern int iicbus_null_callback(device_t, int, caddr_t);
|
||||
|
||||
#define iicbus_repeated_start(bus,slave,timeout) \
|
||||
(IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))
|
||||
#define iicbus_start(bus,slave,timeout) \
|
||||
(IICBUS_START(device_get_parent(bus), slave, timeout))
|
||||
#define iicbus_stop(bus) \
|
||||
(IICBUS_STOP(device_get_parent(bus)))
|
||||
#define iicbus_reset(bus,speed) \
|
||||
(IICBUS_RESET(device_get_parent(bus), speed))
|
||||
#define iicbus_write(bus,buf,len,sent) \
|
||||
(IICBUS_WRITE(device_get_parent(bus), buf, len, sent))
|
||||
#define iicbus_read(bus,buf,len,sent) \
|
||||
(IICBUS_READ(device_get_parent(bus), buf, len, sent))
|
||||
#define iicbus_reset(bus,speed,addr,oldaddr) \
|
||||
(IICBUS_RESET(device_get_parent(bus), speed, addr, oldaddr))
|
||||
#define iicbus_write(bus,buf,len,sent,timeout) \
|
||||
(IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout))
|
||||
#define iicbus_read(bus,buf,len,sent,last,delay) \
|
||||
(IICBUS_READ(device_get_parent(bus), buf, len, sent, last, delay))
|
||||
|
||||
extern int iicbus_block_write(device_t, u_char, char *, int, int *);
|
||||
extern int iicbus_block_read(device_t, u_char, char *, int, int *);
|
||||
|
||||
extern u_char iicbus_get_addr(device_t);
|
||||
extern u_char iicbus_get_own_address(device_t);
|
||||
|
||||
#endif
|
||||
|
@ -23,12 +23,26 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: iicsmb.c,v 1.1.2.2 1998/08/13 17:10:44 son Exp $
|
||||
* $Id: iicsmb.c,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* I2C to SMB bridge
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* smb bttv
|
||||
* \ /
|
||||
* smbus
|
||||
* / \
|
||||
* iicsmb bti2c
|
||||
* |
|
||||
* iicbus
|
||||
* / | \
|
||||
* iicbb pcf ...
|
||||
* |
|
||||
* lpbb
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -72,6 +86,7 @@ static int iicsmb_attach(device_t);
|
||||
static void iicsmb_print_child(device_t, device_t);
|
||||
|
||||
static void iicsmb_intr(device_t dev, int event, char *buf);
|
||||
static int iicsmb_callback(device_t dev, int index, caddr_t data);
|
||||
static int iicsmb_quick(device_t dev, u_char slave, int how);
|
||||
static int iicsmb_sendb(device_t dev, u_char slave, char byte);
|
||||
static int iicsmb_recvb(device_t dev, u_char slave, char *byte);
|
||||
@ -97,6 +112,7 @@ static device_method_t iicsmb_methods[] = {
|
||||
DEVMETHOD(iicbus_intr, iicsmb_intr),
|
||||
|
||||
/* smbus interface */
|
||||
DEVMETHOD(smbus_callback, iicsmb_callback),
|
||||
DEVMETHOD(smbus_quick, iicsmb_quick),
|
||||
DEVMETHOD(smbus_sendb, iicsmb_sendb),
|
||||
DEVMETHOD(smbus_recvb, iicsmb_recvb),
|
||||
@ -222,6 +238,32 @@ iicsmb_intr(device_t dev, int event, char *buf)
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
iicsmb_callback(device_t dev, int index, caddr_t data)
|
||||
{
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error = 0;
|
||||
int how;
|
||||
|
||||
switch (index) {
|
||||
case SMB_REQUEST_BUS:
|
||||
/* request underlying iicbus */
|
||||
how = *(int *)data;
|
||||
error = iicbus_request_bus(parent, dev, how);
|
||||
break;
|
||||
|
||||
case SMB_RELEASE_BUS:
|
||||
/* release underlying iicbus */
|
||||
error = iicbus_release_bus(parent, dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
iicsmb_quick(device_t dev, u_char slave, int how)
|
||||
{
|
||||
@ -230,11 +272,11 @@ iicsmb_quick(device_t dev, u_char slave, int how)
|
||||
|
||||
switch (how) {
|
||||
case SMB_QWRITE:
|
||||
error = iicbus_start(parent, slave & ~LSB);
|
||||
error = iicbus_start(parent, slave & ~LSB, 0);
|
||||
break;
|
||||
|
||||
case SMB_QREAD:
|
||||
error = iicbus_start(parent, slave | LSB);
|
||||
error = iicbus_start(parent, slave | LSB, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -254,10 +296,10 @@ iicsmb_sendb(device_t dev, u_char slave, char byte)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, sent;
|
||||
|
||||
error = iicbus_start(parent, slave & ~LSB);
|
||||
error = iicbus_start(parent, slave & ~LSB, 0);
|
||||
|
||||
if (!error) {
|
||||
error = iicbus_write(parent, &byte, 1, &sent);
|
||||
error = iicbus_write(parent, &byte, 1, &sent, 0);
|
||||
|
||||
iicbus_stop(parent);
|
||||
}
|
||||
@ -271,10 +313,13 @@ iicsmb_recvb(device_t dev, u_char slave, char *byte)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, read;
|
||||
|
||||
error = iicbus_start(parent, slave | LSB);
|
||||
error = iicbus_start(parent, slave | LSB, 0);
|
||||
|
||||
if (!error)
|
||||
error = iicbus_read(parent, byte, 1, &read);
|
||||
if (!error) {
|
||||
error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, 0);
|
||||
|
||||
iicbus_stop(parent);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -285,11 +330,11 @@ iicsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, sent;
|
||||
|
||||
error = iicbus_start(parent, slave & ~LSB);
|
||||
error = iicbus_start(parent, slave & ~LSB, 0);
|
||||
|
||||
if (!error) {
|
||||
if (!(error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
error = iicbus_write(parent, &byte, 1, &sent);
|
||||
if (!(error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
error = iicbus_write(parent, &byte, 1, &sent, 0);
|
||||
|
||||
iicbus_stop(parent);
|
||||
}
|
||||
@ -306,12 +351,12 @@ iicsmb_writew(device_t dev, u_char slave, char cmd, short word)
|
||||
char low = (char)(word & 0xff);
|
||||
char high = (char)((word & 0xff00) >> 8);
|
||||
|
||||
error = iicbus_start(parent, slave & ~LSB);
|
||||
error = iicbus_start(parent, slave & ~LSB, 0);
|
||||
|
||||
if (!error) {
|
||||
if (!(error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if (!(error = iicbus_write(parent, &low, 1, &sent)))
|
||||
error = iicbus_write(parent, &high, 1, &sent);
|
||||
if (!(error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
if (!(error = iicbus_write(parent, &low, 1, &sent, 0)))
|
||||
error = iicbus_write(parent, &high, 1, &sent, 0);
|
||||
|
||||
iicbus_stop(parent);
|
||||
}
|
||||
@ -325,19 +370,20 @@ iicsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, sent, read;
|
||||
|
||||
if ((error = iicbus_start(parent, slave & ~LSB)))
|
||||
if ((error = iicbus_start(parent, slave & ~LSB, 0)))
|
||||
return (error);
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_read(parent, byte, 1, &read)))
|
||||
if ((error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, 0)))
|
||||
goto error;
|
||||
|
||||
error:
|
||||
iicbus_stop(parent);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -351,22 +397,23 @@ iicsmb_readw(device_t dev, u_char slave, char cmd, short *word)
|
||||
int error, sent, read;
|
||||
char buf[2];
|
||||
|
||||
if ((error = iicbus_start(parent, slave & ~LSB)))
|
||||
if ((error = iicbus_start(parent, slave & ~LSB, 0)))
|
||||
return (error);
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_read(parent, buf, 2, &read)))
|
||||
if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, 0)))
|
||||
goto error;
|
||||
|
||||
/* first, receive low, then high byte */
|
||||
*word = BUF2SHORT(buf[0], buf[1]);
|
||||
|
||||
error:
|
||||
iicbus_stop(parent);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -377,29 +424,30 @@ iicsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
|
||||
int error, sent, read;
|
||||
char buf[2];
|
||||
|
||||
if ((error = iicbus_start(parent, slave & ~LSB)))
|
||||
goto error;
|
||||
if ((error = iicbus_start(parent, slave & ~LSB, 0)))
|
||||
return (error);
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
/* first, send low, then high byte */
|
||||
buf[0] = (char)(sdata & 0xff);
|
||||
buf[1] = (char)((sdata & 0xff00) >> 8);
|
||||
|
||||
if ((error = iicbus_write(parent, buf, 2, &sent)))
|
||||
if ((error = iicbus_write(parent, buf, 2, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB)))
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_read(parent, buf, 2, &read)))
|
||||
if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, 0)))
|
||||
goto error;
|
||||
|
||||
/* first, receive low, then high byte */
|
||||
*rdata = BUF2SHORT(buf[0], buf[1]);
|
||||
|
||||
error:
|
||||
iicbus_stop(parent);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -409,13 +457,13 @@ iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, sent;
|
||||
|
||||
if ((error = iicbus_start(parent, slave & ~LSB)))
|
||||
if ((error = iicbus_start(parent, slave & ~LSB, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_write(parent, buf, (int)count, &sent)))
|
||||
if ((error = iicbus_write(parent, buf, (int)count, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_stop(parent)))
|
||||
@ -431,19 +479,21 @@ iicsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
|
||||
device_t parent = device_get_parent(dev);
|
||||
int error, sent, read;
|
||||
|
||||
if ((error = iicbus_start(parent, slave & ~LSB)))
|
||||
if ((error = iicbus_start(parent, slave & ~LSB, 0)))
|
||||
return (error);
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_write(parent, &cmd, 1, &sent)))
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_repeated_start(parent, slave | LSB)))
|
||||
goto error;
|
||||
|
||||
if ((error = iicbus_read(parent, buf, (int)count, &read)))
|
||||
if ((error = iicbus_read(parent, buf, (int)count, &read,
|
||||
IIC_LAST_READ, 0)))
|
||||
goto error;
|
||||
|
||||
error:
|
||||
iicbus_stop(parent);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user