summaryrefslogtreecommitdiffstats
path: root/sys/dev/bktr/bktr_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/bktr/bktr_i2c.c')
-rw-r--r--sys/dev/bktr/bktr_i2c.c300
1 files changed, 110 insertions, 190 deletions
diff --git a/sys/dev/bktr/bktr_i2c.c b/sys/dev/bktr/bktr_i2c.c
index 4f61e5c..20342d1 100644
--- a/sys/dev/bktr/bktr_i2c.c
+++ b/sys/dev/bktr/bktr_i2c.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,10 +33,13 @@
* From brooktree848.c <fsmp@freefall.org>
*/
+#include "opt_bktr.h"
+
#include "bktr.h"
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
@@ -62,196 +65,91 @@
#include <pci/pcireg.h>
#include <machine/ioctl_meteor.h>
#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
-#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_reg.h>
#include <dev/bktr/bktr_i2c.h>
-#include <dev/iicbus/iiconf.h>
-#include <dev/iicbus/iicbus.h>
-
#include <dev/smbus/smbconf.h>
-
-#include "iicbb_if.h"
-#include "smbus_if.h"
-
-
+#include <dev/iicbus/iiconf.h>
#define I2C_DELAY 40
#define BTI2C_DEBUG(x) if (bti2c_debug) (x)
static int bti2c_debug = 0;
-struct bti2c_softc {
-
- bus_space_tag_t memt; /* Bus space register access */
- bus_space_handle_t memh; /* Bus space register access */
-
- int iic_owned; /* 1 if we own the iicbus */
- int smb_owned; /* 1 if we own the smbbus */
-
- device_t smbus;
- device_t iicbus;
-};
-
-struct bt_data {
- bus_space_tag_t memt;
- bus_space_handle_t memh;
-};
-struct bt_data btdata[NBKTR];
-
-static int bti2c_probe(device_t);
-static int bti2c_attach(device_t);
-
-static int bti2c_iic_callback(device_t, int, caddr_t *);
-static void bti2c_iic_setlines(device_t, int, int);
-static int bti2c_iic_getdataline(device_t);
-static int bti2c_iic_reset(device_t, u_char, u_char, u_char *);
-
-static int bti2c_smb_callback(device_t, int, caddr_t *);
-static int bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte);
-static int bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word);
-static int bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte);
-
-static devclass_t bti2c_devclass;
-
-static device_method_t bti2c_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, bti2c_probe),
- DEVMETHOD(device_attach, bti2c_attach),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- /* iicbb interface */
- DEVMETHOD(iicbb_callback, bti2c_iic_callback),
- DEVMETHOD(iicbb_setlines, bti2c_iic_setlines),
- DEVMETHOD(iicbb_getdataline, bti2c_iic_getdataline),
- DEVMETHOD(iicbb_reset, bti2c_iic_reset),
-
- /* smbus interface */
- DEVMETHOD(smbus_callback, bti2c_smb_callback),
- DEVMETHOD(smbus_writeb, bti2c_smb_writeb),
- DEVMETHOD(smbus_writew, bti2c_smb_writew),
- DEVMETHOD(smbus_readb, bti2c_smb_readb),
-
- { 0, 0 }
-};
-
-#if (__FreeBSD_version < 400000)
-/* FreeBSD 3.x needs DRIVER_TYPE_MISC */
-static driver_t bti2c_driver = {
- "bti2c",
- bti2c_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct bti2c_softc),
-};
-#endif
-
-#if (__FreeBSD_version >=400000)
- static driver_t bti2c_driver = {
- "bti2c",
- bti2c_methods,
- sizeof(struct bti2c_softc),
-};
-#endif
-
/*
* Call this to pass the address of the bktr device to the
* bti2c_i2c layer and initialize all the I2C bus architecture
*/
-int
-bt848_i2c_attach(int unit, struct bktr_softc * bktr, struct bktr_i2c_softc *i2c_sc)
+int bt848_i2c_attach(device_t dev)
{
- device_t interface;
- device_t bitbang;
+ struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
+ struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
- btdata[unit].memh = bktr->memh;
- btdata[unit].memt = bktr->memt;
+ device_t *list;
+ int count;
- /* XXX add the I2C interface to the root_bus until pcibus is ready */
-#if (__FreeBSD_version < 400000)
- interface = device_add_child(root_bus, "bti2c", unit, NULL);
-#else
- interface = device_add_child(root_bus, "bti2c", unit);
-#endif
+ sc->smbus = device_add_child(dev, "smbus", -1);
+ sc->iicbb = device_add_child(dev, "iicbb", -1);
- /* add bit-banging generic code onto bti2c interface */
-#if (__FreeBSD_version < 400000)
- bitbang = device_add_child(interface, "iicbb", -1, NULL);
-#else
- bitbang = device_add_child(interface, "iicbb", -1);
-#endif
-
- /* probe and attach the interface, we need it NOW
- * bit-banging code is also probed and attached */
- device_probe_and_attach(interface);
- device_probe_and_attach(bitbang);
+ if (!sc->iicbb || !sc->smbus)
+ return ENXIO;
- /* smb and i2c interfaces are available for the bt848 chip
- * connect bit-banging generic code to an iicbus */
- if ((i2c_sc->iicbus = iicbus_alloc_bus(bitbang)))
- device_probe_and_attach(i2c_sc->iicbus);
+ bus_generic_attach(dev);
- /* hardware i2c is actually smb over the bti2c interface */
- if ((i2c_sc->smbus = smbus_alloc_bus(interface)))
- device_probe_and_attach(i2c_sc->smbus);
+ /* the iicbus is the first child of device iicbb */
+ device_get_children(sc->iicbb, &list, &count);
+ if (count) {
+ sc->iicbus = list[0];
+ free(list, M_TEMP);
+ }
return (0);
};
-/*
- * Not a real probe, we know the device exists since the device has
- * been added after the successfull pci probe.
- */
-static int
-bti2c_probe(device_t dev)
+int bt848_i2c_detach(device_t dev)
{
- device_set_desc(dev, "bt848 Hard/Soft I2C controller");
+ struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
+ struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
+ int error = 0;
- return (0);
-}
+ if ((error = bus_generic_detach(dev)))
+ goto error;
-static int
-bti2c_attach(device_t dev)
-{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ if (sc->iicbb && (error = device_delete_child(dev, sc->iicbb)))
+ goto error;
- /* XXX should use ivars with pcibus or pcibus methods to access
- * onboard memory */
- sc->memh = btdata[device_get_unit(dev)].memh;
- sc->memt = btdata[device_get_unit(dev)].memt;
+ if (sc->smbus && (error = device_delete_child(dev, sc->smbus)))
+ goto error;
- return (0);
+error:
+ return (error);
}
-static int
-bti2c_smb_callback(device_t dev, int index, caddr_t *data)
+int bti2c_smb_callback(device_t dev, int index, caddr_t *data)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
+ struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
int error = 0;
- int how;
/* test each time if we already have/haven't the iicbus
* to avoid deadlocks
*/
switch (index) {
case SMB_REQUEST_BUS:
- if (!sc->iic_owned) {
- /* request the iicbus */
- how = *(int *)data;
- error = iicbus_request_bus(sc->iicbus, dev, how);
- if (!error)
- sc->iic_owned = 1;
- }
+ /* XXX test & set */
+ if (!sc->bus_owned) {
+ sc->bus_owned = 1;
+ } else
+ error = EWOULDBLOCK;
break;
case SMB_RELEASE_BUS:
- if (sc->iic_owned) {
- /* release the iicbus */
- error = iicbus_release_bus(sc->iicbus, dev);
- if (!error)
- sc->iic_owned = 0;
- }
+ /* XXX test & set */
+ if (sc->bus_owned) {
+ sc->bus_owned = 0;
+ } else
+ error = EINVAL;
break;
default:
@@ -261,34 +159,30 @@ bti2c_smb_callback(device_t dev, int index, caddr_t *data)
return (error);
}
-static int
-bti2c_iic_callback(device_t dev, int index, caddr_t *data)
+int bti2c_iic_callback(device_t dev, int index, caddr_t *data)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
+ struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
int error = 0;
- int how;
/* test each time if we already have/haven't the smbus
* to avoid deadlocks
*/
switch (index) {
case IIC_REQUEST_BUS:
- if (!sc->smb_owned) {
- /* request the smbus */
- how = *(int *)data;
- error = smbus_request_bus(sc->smbus, dev, how);
- if (!error)
- sc->smb_owned = 1;
- }
+ /* XXX test & set */
+ if (!sc->bus_owned) {
+ sc->bus_owned = 1;
+ } else
+ error = EWOULDBLOCK;
break;
case IIC_RELEASE_BUS:
- if (sc->smb_owned) {
- /* release the smbus */
- error = smbus_release_bus(sc->smbus, dev);
- if (!error)
- sc->smb_owned = 0;
- }
+ /* XXX test & set */
+ if (sc->bus_owned) {
+ sc->bus_owned = 0;
+ } else
+ error = EINVAL;
break;
default:
@@ -298,8 +192,7 @@ bti2c_iic_callback(device_t dev, int index, caddr_t *data)
return (error);
}
-static int
-bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
+int bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
{
if (oldaddr)
*oldaddr = 0; /* XXX */
@@ -307,48 +200,77 @@ bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
return (IIC_ENOADDR);
}
-static void
-bti2c_iic_setlines(device_t dev, int ctrl, int data)
+void bti2c_iic_setsda(device_t dev, int val)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
+ int clock;
+
+ clock = INL(sc, BKTR_I2C_DATA_CTL) & 0x2;
+
+ if (val)
+ OUTL(sc, BKTR_I2C_DATA_CTL, clock | 1);
+ else
+ OUTL(sc, BKTR_I2C_DATA_CTL, clock);
- OUTL(sc, BKTR_I2C_DATA_CTL, (ctrl << 1) | data);;
DELAY(I2C_DELAY);
return;
}
-static int
-bti2c_iic_getdataline(device_t dev)
+void bti2c_iic_setscl(device_t dev, int val)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
+ int data;
+
+ data = INL(sc, BKTR_I2C_DATA_CTL) & 0x1;
+
+ if (val)
+ OUTL(sc, BKTR_I2C_DATA_CTL, 0x2 | data);
+ else
+ OUTL(sc, BKTR_I2C_DATA_CTL, data);
- return ( INL(sc,BKTR_I2C_DATA_CTL) & 0x1);
+ DELAY(I2C_DELAY);
+
+ return;
+}
+
+int
+bti2c_iic_getsda(device_t dev)
+{
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
+
+ return (INL(sc,BKTR_I2C_DATA_CTL) & 0x1);
+}
+
+int
+bti2c_iic_getscl(device_t dev)
+{
+ return (0);
}
static int
-bti2c_write(struct bti2c_softc* bti2c_sc, u_long data)
+bti2c_write(struct bktr_softc *sc, u_long data)
{
u_long x;
/* clear status bits */
- OUTL(bti2c_sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE));
+ OUTL(sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE));
BTI2C_DEBUG(printf("w%lx", data));
/* write the address and data */
- OUTL(bti2c_sc, BKTR_I2C_DATA_CTL, data);
+ OUTL(sc, BKTR_I2C_DATA_CTL, data);
/* wait for completion */
for ( x = 0x7fffffff; x; --x ) { /* safety valve */
- if ( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_I2CDONE )
+ if ( INL(sc, BKTR_INT_STAT) & BT848_INT_I2CDONE )
break;
}
/* check for ACK */
- if ( !x || !( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_RACK) ) {
+ if ( !x || !( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK) ) {
BTI2C_DEBUG(printf("%c%c", (!x)?'+':'-',
- (!( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-'));
+ (!( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-'));
return (SMB_ENOACK);
}
BTI2C_DEBUG(printf("+"));
@@ -357,10 +279,10 @@ bti2c_write(struct bti2c_softc* bti2c_sc, u_long data)
return( 0 );
}
-static int
+int
bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
u_long data;
data = ((slave & 0xff) << 24) | ((byte & 0xff) << 16) | (u_char)cmd;
@@ -372,10 +294,10 @@ bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
* byte1 becomes low byte of word
* byte2 becomes high byte of word
*/
-static int
+int
bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
u_long data;
char low, high;
@@ -391,10 +313,10 @@ bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word)
/*
* The Bt878 and Bt879 differed on the treatment of i2c commands
*/
-static int
+int
bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
{
- struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev);
+ struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev);
u_long x;
/* clear status bits */
@@ -422,5 +344,3 @@ bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
return (0);
}
-
-DRIVER_MODULE(bti2c, root, bti2c_driver, bti2c_devclass, 0, 0);
OpenPOWER on IntegriCloud