Hi,

came across some old crap i had using mgiic on arm, as the IP on
sunxis is actually from Mentor Graphics, not Marvell.

What is in the diff below is not finished for either however, for
sparc64 it'll likely remain broken because of missing delays, and
for !sparc64(=armv7&arm64) i haven't verified anything yet.

Should i move it to dev/ic, w/slim wrappers in sys/arch/sparc64/dev
and sys/dev/fdt/ or? or just let it rot?

-Artturi


diff --git a/sys/arch/sparc64/dev/mgiic.c b/home/aalm/mgiic.c
index 6d1206a95f4..2ea255e62c9 100644
--- a/sys/arch/sparc64/dev/mgiic.c
+++ b/home/aalm/mgiic.c
@@ -25,11 +25,22 @@
 #include <uvm/uvm_extern.h>
 
 #include <machine/bus.h>
+#ifdef __sparc64__
 #include <machine/autoconf.h>
 #include <machine/openfirm.h>
 
 #include <dev/i2c/i2cvar.h>
 #include <sparc64/dev/ofwi2cvar.h>
+#else
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_pinctrl.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/i2c/i2cvar.h>
+#endif
 
 #define MGSLAVEADDR            0x00
 #define MGSLAVEXADDR           0x08
@@ -62,6 +73,15 @@
 #define MGCLOCKCONTROL         0x28
 #define MGSOFTRESET            0x30
 
+#define        MGPOLLDELAY             1
+#define        MGRDWRDELAY             2
+
+#ifndef MGIICDEBUG
+#define        DPRINTF(a)      do {/* NO-OP */} while (0)
+#else
+#define        DPRINTF(a)      printf a
+#endif
+
 struct mgiic_softc {
        struct device sc_dev;
 
@@ -69,6 +89,9 @@ struct mgiic_softc {
        bus_space_handle_t      sc_regh;
 
 
+#ifndef __sparc64__
+       void                    *sc_ih;
+#endif
        int                     sc_poll;
 
        struct i2c_controller   sc_i2c;
@@ -94,8 +117,23 @@ int                 mgiic_i2c_exec(void *, i2c_op_t, 
i2c_addr_t, const void *,
 int                    mgiic_xmit(struct mgiic_softc *, u_int8_t, const 
u_int8_t *,
                            size_t);
 int                    mgiic_recv(struct mgiic_softc *, u_int8_t, u_int8_t *, 
size_t);
+#ifdef __sparc64__
 volatile u_int8_t      mgiic_read(struct mgiic_softc *, bus_size_t);
 volatile void          mgiic_write(struct mgiic_softc *, bus_size_t, u_int8_t);
+#else
+int                    mgiic_intr(void *);
+volatile u_int8_t      _mgiic_read(struct mgiic_softc *, bus_size_t);
+volatile void          _mgiic_write(struct mgiic_softc *, bus_size_t, 
u_int8_t);
+#define        mgiic_read(sc,r)        _mgiic_read_((sc), ((r) >> 1))
+#define        mgiic_write(sc,r,v)     _mgiic_write((sc), ((r) >> 1), (v))
+#define        mainbus_attach_args     fdt_attach_args
+#define        ma_bustag               fa_iot
+#define        ma_reg                  fa_reg
+#define        ur_paddr                addr
+#define        ur_len                  size
+#define        ma_node                 fa_node
+#endif
+
 volatile void          mgiic_control(struct mgiic_softc *, u_int8_t, u_int8_t);
 int                    mgiic_poll(struct mgiic_softc *);
 
@@ -103,6 +141,7 @@ int
 mgiic_match(struct device *parent, void *match, void *aux)
 {
        struct mainbus_attach_args *ma = aux;
+#ifdef __sparc64__
        char compat[32];
 
        if (strcmp(ma->ma_name, "i2c") != 0)
@@ -112,6 +151,10 @@ mgiic_match(struct device *parent, void *match, void *aux)
        if (strcmp(compat, "fire-i2c") == 0)
                return (1);
        return (0);
+#else
+       return (OF_is_compatible(ma->fa_node, "allwinner,sun4i-a10-i2c") ||
+           OF_is_compatible(ma->fa_node, "allwinner,sun7i-a20-i2c"));
+#endif
 }
 
 void
@@ -135,6 +178,31 @@ mgiic_attach(struct device *parent, struct device *self, 
void *aux)
        sc->sc_i2c.ic_release_bus = mgiic_i2c_release_bus;
        sc->sc_i2c.ic_exec = mgiic_i2c_exec;
 
+#ifndef __sparc64__
+       pinctrl_byname(ma->fa_node, "default");
+
+       /* Enable clock */
+       clock_enable(ma->fa_node, NULL);
+
+       /*
+        * Set clock rate to 100kHz. From the datasheet:
+        *   For 100Khz standard speed 2Wire, CLK_N=2, CLK_M=11
+        *   F0=48M/2^2=12Mhz, F1=F0/(10*(11+1)) = 0.1Mhz
+        */
+       mgiic_write(sc, MGCLOCKCONTROL, (11 << 3) | (2 << 0));
+
+       /* Put the controller into Soft Reset. */
+       mgiic_write(sc, MGSOFTRESET, 0);
+
+       /* Establish interrupt */
+       sc->sc_ih = arm_intr_establish_fdt(ma->fa_node, IPL_BIO,
+           mgiic_intr, sc, sc->sc_dev.dv_xname);
+       if (sc->sc_ih == NULL) {
+               printf(": failed to establish interrupt\n");
+               return;
+       }
+#endif
+
        printf("\n");
 
        bzero(&iba, sizeof(iba));
@@ -193,7 +261,7 @@ mgiic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr,
                        ret = mgiic_recv(sc, addr & 0x7f, buf, len);
        }
 done:
-       printf("e%d\n", ret);
+       DPRINTF(("e%d\n", ret));
        return (ret);
 }
 
@@ -201,38 +269,40 @@ int
 mgiic_xmit(struct mgiic_softc *sc, u_int8_t addr, const u_int8_t *buf,
     size_t len)
 {
-       int err = 1, i = 0;
+       int err = 1, i = 0, sta = 0;
 
 top:
-       printf("xmit s%02x STA ", mgiic_read(sc, MGSTATUS));
+       DPRINTF(("xmit s%02x STA ", mgiic_read(sc, MGSTATUS)));
        mgiic_control(sc, MGCONTROL_STA, MGCONTROL_IFLG);
 
        if (mgiic_poll(sc))
                goto bail;
-       printf("s%02x ", mgiic_read(sc, MGSTATUS));
-       if (mgiic_read(sc, MGSTATUS) != MGSTATUS_STARTSENT)
+       sta = mgiic_read(sc, MGSTATUS);
+       DPRINTF(("s%02x ", sta));
+       if (sta != MGSTATUS_STARTSENT)
                goto bail;
 
        mgiic_write(sc, MGDATA, addr << 1);
-       printf("a%02x ", addr << 1);
+       DPRINTF(("a%02x ", addr << 1));
        mgiic_control(sc, 0, MGCONTROL_IFLG);
 
        while (i < len) {
                if (mgiic_poll(sc))
                         goto bail;
-               printf("s%02x ", mgiic_read(sc, MGSTATUS));
-               switch (mgiic_read(sc, MGSTATUS)) {
+               sta = mgiic_read(sc, MGSTATUS);
+               DPRINTF(("s%02x ", sta));
+               switch (sta) {
                case MGSTATUS_ADDR_W_ACKR:
                case MGSTATUS_MDATA_ACKR:
                        mgiic_write(sc, MGDATA, buf[i]);
-                       printf("w%02x ", buf[i]);
+                       DPRINTF(("w%02x ", buf[i]));
                        i++;
                        mgiic_control(sc, 0, MGCONTROL_IFLG);
                        break;
                case MGSTATUS_ADDR_W_NOACKR:
                case MGSTATUS_MDATA_NOACKR:
                        mgiic_write(sc, MGDATA, buf[i]);
-                       printf("w%02x ", buf[i]);
+                       DPRINTF(("w%02x ", buf[i]));
                        mgiic_control(sc, 0, MGCONTROL_IFLG);
                        break;
                case MGSTATUS_BUSERR:
@@ -247,42 +317,44 @@ top:
                        goto bail;
                }
        }
-       printf("OK ");
+       DPRINTF(("OK "));
        err = 0;
 bail:
        if (err)
-               printf("BAIL STP s%02x\n", mgiic_read(sc, MGSTATUS));
+               DPRINTF(("BAIL STP s%02x\n", mgiic_read(sc, MGSTATUS)));
        mgiic_control(sc, MGCONTROL_STP, MGCONTROL_IFLG);
-       while (mgiic_read(sc, MGSTATUS) != MGSTATUS_IDLE)
-               ;
-       printf("s%02x\n", mgiic_read(sc, MGSTATUS));
+       sta = mgiic_read(sc, MGSTATUS);
+       while (sta != MGSTATUS_IDLE)    /* XXX timeout & reset hw ?*/
+               sta = mgiic_read(sc, MGSTATUS);
        return (err);
 }
 
 int
 mgiic_recv(struct mgiic_softc *sc, u_int8_t addr, u_int8_t *buf, size_t len)
 {
-       int err = 1, i = 0;
+       int err = 1, i = 0, sta = 0;
 
-       printf("recv s%02x ", mgiic_read(sc, MGSTATUS));
+       DPRINTF(("recv s%02x ", mgiic_read(sc, MGSTATUS)));
        mgiic_control(sc, MGCONTROL_STA, MGCONTROL_IFLG);
        if (mgiic_poll(sc))
                goto bail;
 
-       printf("s%02x ", mgiic_read(sc, MGSTATUS));
-       if (mgiic_read(sc, MGSTATUS) != MGSTATUS_STARTSENT)
+       sta = mgiic_read(sc, MGSTATUS);
+       DPRINTF(("s%02x ", sta));
+       if (sta != MGSTATUS_STARTSENT)
                goto bail;
 
 re_address:
        mgiic_write(sc, MGDATA, (addr << 1) | 0x01);
-       printf("a%02x ", (addr << 1) | 0x01);
+       DPRINTF(("a%02x ", (addr << 1) | 0x01));
        mgiic_control(sc, 0, MGCONTROL_IFLG);
 
        while (i < len) {
                if (mgiic_poll(sc))
                        goto bail;
-               printf("s%02x ", mgiic_read(sc, MGSTATUS));
-               switch (mgiic_read(sc, MGSTATUS)) {
+               sta = mgiic_read(sc, MGSTATUS);
+               DPRINTF(("s%02x ", sta));
+               switch (sta) {
                case MGSTATUS_ADDR_R_ACKR:
                        if (len - i > 1)
                                mgiic_control(sc, MGCONTROL_AAK, 
MGCONTROL_IFLG);
@@ -296,7 +368,7 @@ re_address:
                        goto re_address;
                case MGSTATUS_MDATA_ACKT:
                        buf[i] = mgiic_read(sc, MGDATA);
-                       printf("r%02x ", buf[i]);
+                       DPRINTF(("r%02x ", buf[i]));
                        i++;
                        if (len - i > 1)
                                mgiic_control(sc, MGCONTROL_AAK, 
MGCONTROL_IFLG);
@@ -305,33 +377,35 @@ re_address:
                        break;
                case MGSTATUS_MDATA_NOACKT:
                        buf[i] = mgiic_read(sc, MGDATA);
-                       printf("r%02x ", buf[i]);
+                       DPRINTF(("r%02x ", buf[i]));
                        i++;
                        if (len == i) {
-                               printf("DONE ");
+                               DPRINTF(("DONE "));
                                err = 0;
                                goto bail;
                        }
-                       printf("SHORT ");
+                       DPRINTF(("SHORT "));
                        goto bail;
                        break;
                default:
-                       printf("BAD");
+                       DPRINTF(("BAD"));
                        goto bail;
                }
        }
-       printf("OK ");
+       DPRINTF(("OK "));
        err = 0;
 bail:
        if (err)
-               printf("BAIL STP s%02x\n", mgiic_read(sc, MGSTATUS));
+               DPRINTF(("BAIL STP s%02x\n", mgiic_read(sc, MGSTATUS)));
        mgiic_control(sc, MGCONTROL_STP, MGCONTROL_IFLG | MGCONTROL_AAK);
-       while (mgiic_read(sc, MGSTATUS) != MGSTATUS_IDLE)
-               ;
-       printf("s%02x\n", mgiic_read(sc, MGSTATUS));
+       sta = mgiic_read(sc, MGSTATUS);
+       while (sta != MGSTATUS_IDLE)    /* XXX */
+               sta = mgiic_read(sc, MGSTATUS);
+
        return (err);
 }
 
+#ifdef __sparc64__
 volatile u_int8_t
 mgiic_read(struct mgiic_softc *sc, bus_size_t r)
 {
@@ -349,6 +423,39 @@ mgiic_write(struct mgiic_softc *sc, bus_size_t r, u_int8_t 
v)
        bus_space_barrier(sc->sc_bt, sc->sc_regh, r, 8,
            BUS_SPACE_BARRIER_WRITE);
 }
+#else
+int
+mgiic_intr(void *arg)
+{
+       struct mgiic_softc *sc = arg;
+       u_int val;
+
+       val = mgiic_read(sc, MGCONTROL);
+       if (val & MGCONTROL_IFLG) {
+               mgiic_write(sc, MG_CONTROL, val & ~MGCONTROL_IEN);
+               wakeup(&sc->sc_dev);
+               return 1;
+       }
+       return 0;
+}
+
+volatile u_int8_t
+_mgiic_read(struct mgiic_softc *sc, bus_size_t r)
+{
+       uint32_t val = bus_space_read_4(sc->sc_bt, sc->sc_regh, r);
+       delay(MGRDWRDELAY);
+       return val & 0xff;
+}
+
+volatile void
+_mgiic_write(struct mgiic_softc *sc, bus_size_t r, u_int8_t v)
+{
+       uint32_t val = v;
+
+       bus_space_write_4(sc->sc_bt, sc->sc_regh, r, val);
+       delay(MGRDWRDELAY);
+}
+#endif
 
 volatile void
 mgiic_control(struct mgiic_softc *sc, u_int8_t on, u_int8_t off)

Reply via email to