Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/marvell Add a i2c driver for the onboard i2c/twsi co...



details:   https://anonhg.NetBSD.org/src/rev/548b861ac2f3
branches:  trunk
changeset: 573588:548b861ac2f3
user:      matt <matt%NetBSD.org@localhost>
date:      Tue Feb 01 20:58:46 2005 +0000

description:
Add a i2c driver for the onboard i2c/twsi controller on the GT642x0

diffstat:

 sys/dev/marvell/gti2c.c    |  278 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/marvell/gti2creg.h |   83 +++++++++++++
 2 files changed, 361 insertions(+), 0 deletions(-)

diffs (truncated from 369 to 300 lines):

diff -r 4693d90a93df -r 548b861ac2f3 sys/dev/marvell/gti2c.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/marvell/gti2c.c   Tue Feb 01 20:58:46 2005 +0000
@@ -0,0 +1,278 @@
+/*     $NetBSD: gti2c.c,v 1.1 2005/02/01 20:58:46 matt Exp $   */
+
+/*
+ * Copyright (c) 2005 Brocade Communcations, inc.
+ * All rights reserved.
+ *
+ * Written by Matt Thomas for Brocade Communcations, Inc.
+ *
+ * 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.
+ * 3. The name of Brocade Communications, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``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 EITHER BROCADE COMMUNICATIONS, INC. 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: gti2c.c,v 1.1 2005/02/01 20:58:46 matt Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/marvell/gtintrreg.h>
+#include <dev/marvell/gti2creg.h>
+
+#include <dev/marvell/gtvar.h>
+
+#include <dev/i2c/i2cvar.h>
+
+struct gti2c_softc {
+       struct device sc_dev;
+       struct evcnt sc_ev_intr;
+       struct i2c_controller sc_i2c;
+       struct gt_softc *sc_gt;
+       struct lock sc_lock;
+};
+
+static int gt_i2c_match(struct device *, struct cfdata *, void *);
+static void gt_i2c_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(gtiic, sizeof(struct gti2c_softc),
+    gt_i2c_match, gt_i2c_attach, NULL, NULL);
+
+extern struct cfdriver gtiic_cd;
+
+static int
+gt_i2c_wait(struct gti2c_softc *sc, uint32_t control,
+    uint32_t desired_status, int flags)
+{
+       uint32_t status;
+       int error = 0;
+
+    again:
+       if (flags & I2C_F_POLL)
+               control |= I2C_Control_IntEn;
+       if (desired_status != I2C_Status_MasterReadAck)
+               gt_write(sc->sc_gt, I2C_REG_Control, control);
+
+       for (;;) {
+               control = gt_read(sc->sc_gt, I2C_REG_Control);
+               if (control & I2C_Control_IFlg)
+                       break;
+               error = tsleep(sc, PZERO, "gti2cwait",
+                   (flags & I2C_F_POLL) ? 1 : 0);
+               if (error && (error != ETIMEDOUT || !(flags & I2C_F_POLL)))
+                       return error;
+       }
+
+       status = gt_read(sc->sc_gt, I2C_REG_Status);
+       if (status != desired_status)
+               return EIO;
+
+       if ((flags & I2C_F_LAST) &&
+           desired_status != I2C_Status_MasterReadAck) {
+               control = I2C_Control_Stop;
+               goto again;
+       }
+
+       return error;
+}
+
+static int
+gt_i2c_acquire_bus(void *cookie, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+       uint32_t status;
+       int error;
+
+       if (flags & I2C_F_POLL)
+               return 0;
+
+       error = lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
+       if (error)
+               return error;
+
+       status = gt_read(sc->sc_gt, I2C_REG_Status);
+       if (status != I2C_Status_Idle) {
+               gt_write(sc->sc_gt, I2C_REG_SoftReset, 1);
+       }
+
+       return 0;
+}
+
+static void
+gt_i2c_release_bus(void *cookie, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+
+       lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
+}
+
+static int
+gt_i2c_send_start(void *cookie, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+
+       return gt_i2c_wait(sc, I2C_Control_Start, I2C_Status_Started, flags);
+}
+
+static int
+gt_i2c_send_stop(void *cookie, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+
+       return gt_i2c_wait(sc, I2C_Control_Stop, I2C_Status_Idle, flags);
+}
+
+static int
+gt_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+       uint32_t data, wanted_status;
+       uint8_t read_mask = (flags & I2C_F_READ) != 0;
+       int error;
+
+       if (read_mask) {
+               wanted_status = I2C_Status_AddrReadAck;
+       } else {
+               wanted_status = I2C_Status_AddrWriteAck;
+       }
+       /*
+        * First byte contains whether this xfer is a read or write.
+        */
+       data = read_mask;
+       if (addr > 0x7f) {
+               /*
+                * If this is a 10bit request, the first address byte is
+                * 0b11110<b9><b8><r/w>.
+                */
+               data |= 0xf0 | ((addr & 0x30) >> 7);
+               gt_write(sc->sc_gt, I2C_REG_Data, data);
+               error = gt_i2c_wait(sc, 0, wanted_status, flags);
+               if (error)
+                       return error;
+               /*
+                * The first address byte has been sent, now to send
+                * the second one.
+                */
+               if (read_mask) {
+                       wanted_status = I2C_Status_2ndAddrReadAck;
+               } else {
+                       wanted_status = I2C_Status_2ndAddrWriteAck;
+               }
+               data = (uint8_t) addr;
+       } else {
+               data |= (addr << 1);
+       }
+
+       gt_write(sc->sc_gt, I2C_REG_Data, data);
+       return gt_i2c_wait(sc, 0, wanted_status, flags);
+}
+
+static int
+gt_i2c_read_byte(void *cookie, uint8_t *dp, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+       int error;
+
+       gt_write(sc->sc_gt, I2C_REG_Data, *dp);
+       error = gt_i2c_wait(sc, 0, I2C_Status_MasterReadAck, flags);
+       if (error == 0) {
+               *dp = gt_read(sc->sc_gt, I2C_REG_Data);
+       }
+       if (flags & I2C_F_LAST)
+               gt_write(sc->sc_gt, I2C_REG_Control, 0);
+       return error;
+}
+
+static int
+gt_i2c_write_byte(void *cookie, uint8_t v, int flags)
+{
+       struct gti2c_softc * const sc = cookie;
+
+       gt_write(sc->sc_gt, I2C_REG_Data, v);
+       return gt_i2c_wait(sc, 0, I2C_Status_MasterWriteAck, flags);
+}
+
+static int
+gt_i2c_intr(void *aux)
+{
+       struct gti2c_softc * const sc = aux;
+       uint32_t v;
+
+       v = gt_read(sc->sc_gt, I2C_REG_Control);
+       if ((v & I2C_Control_IFlg) == 0)
+               return 0;
+       gt_write(sc->sc_gt, I2C_REG_Control, v & ~I2C_Control_IntEn);
+
+       sc->sc_ev_intr.ev_count++;
+
+       wakeup(sc);
+       return 1;
+}
+
+int
+gt_i2c_match(struct device *parent, struct cfdata *cfdata, void *aux)
+{
+       struct gt_softc * const gt = (void *) parent;
+       struct gt_attach_args * const ga = aux;
+
+       return GT_I2COK(gt, ga, &gtiic_cd);
+}
+
+void
+gt_i2c_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct gt_softc * const gt = (void *) parent;
+       struct gti2c_softc * const sc = (void *) self;
+       struct gt_attach_args * const ga = aux;
+       struct i2cbus_attach_args iba;
+
+       sc->sc_gt = gt;
+
+       GT_I2CFOUND(gt, ga);
+
+       lockinit(&sc->sc_lock, PZERO, sc->sc_dev.dv_xname, 0, 0);
+
+       sc->sc_i2c.ic_cookie = sc;
+       sc->sc_i2c.ic_acquire_bus = gt_i2c_acquire_bus;
+       sc->sc_i2c.ic_release_bus = gt_i2c_release_bus;
+       sc->sc_i2c.ic_release_bus = gt_i2c_release_bus;
+       sc->sc_i2c.ic_send_start = gt_i2c_send_start;
+       sc->sc_i2c.ic_send_stop = gt_i2c_send_stop;
+       sc->sc_i2c.ic_initiate_xfer = gt_i2c_initiate_xfer;
+       sc->sc_i2c.ic_read_byte = gt_i2c_read_byte;
+       sc->sc_i2c.ic_write_byte = gt_i2c_write_byte;
+
+       intr_establish(IRQ_I2C, IST_LEVEL, IPL_I2C, gt_i2c_intr, sc);
+
+       evcnt_attach_dynamic(&sc->sc_ev_intr, EVCNT_TYPE_INTR, NULL,
+               sc->sc_dev.dv_xname, "intr");
+
+       iba.iba_name = "iic";
+       iba.iba_tag = &sc->sc_i2c;
+       config_found(self, &iba, iicbus_print);
+}
diff -r 4693d90a93df -r 548b861ac2f3 sys/dev/marvell/gti2creg.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/marvell/gti2creg.h        Tue Feb 01 20:58:46 2005 +0000
@@ -0,0 +1,83 @@
+/*     $NetBSD: gti2creg.h,v 1.1 2005/02/01 20:58:46 matt Exp $        */
+
+/*
+ * Copyright (c) 2005 Brocade Communcations, inc.
+ * All rights reserved.
+ *
+ * Written by Matt Thomas for Brocade Communcations, Inc.
+ *
+ * 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



Home | Main Index | Thread Index | Old Index