Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/ti Handle different register layout on OMAP3



details:   https://anonhg.NetBSD.org/src/rev/6cdb86a5f960
branches:  trunk
changeset: 460700:6cdb86a5f960
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Thu Oct 31 10:21:29 2019 +0000

description:
Handle different register layout on OMAP3

diffstat:

 sys/arch/arm/ti/ti_iic.c    |  193 +++++++++++++++++++++++++++++--------------
 sys/arch/arm/ti/ti_iicreg.h |   69 ++++-----------
 2 files changed, 149 insertions(+), 113 deletions(-)

diffs (truncated from 507 to 300 lines):

diff -r 842d423ca9a2 -r 6cdb86a5f960 sys/arch/arm/ti/ti_iic.c
--- a/sys/arch/arm/ti/ti_iic.c  Thu Oct 31 09:44:13 2019 +0000
+++ b/sys/arch/arm/ti/ti_iic.c  Thu Oct 31 10:21:29 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_iic.c,v 1.2 2019/10/29 22:19:13 jmcneill Exp $ */
+/* $NetBSD: ti_iic.c,v 1.3 2019/10/31 10:21:29 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2013 Manuel Bouyer.  All rights reserved.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ti_iic.c,v 1.2 2019/10/29 22:19:13 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ti_iic.c,v 1.3 2019/10/31 10:21:29 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -81,10 +81,75 @@
 #define DPRINTF(args)
 #endif
 
+enum ti_iic_type {
+       TI_IIC_OMAP3,
+       TI_IIC_OMAP4,
+       TI_NTYPES
+};
+
+enum {
+       I2C_SYSC,
+       I2C_IRQSTATUS_RAW,
+       I2C_IRQSTATUS,
+       I2C_IRQENABLE,          /* OMAP3 */
+       I2C_IRQENABLE_SET,      /* OMAP4 */
+       I2C_IRQENABLE_CLR,      /* OMAP4 */
+       I2C_SYSS,
+       I2C_BUF,
+       I2C_CNT,
+       I2C_DATA,
+       I2C_CON,
+       I2C_OA,
+       I2C_SA,
+       I2C_PSC,
+       I2C_SCLL,
+       I2C_SCLH,
+       I2C_BUFSTAT,
+       TI_NREGS
+};
+
+static const u_int ti_iic_regmap[TI_NTYPES][TI_NREGS] = {
+       [TI_IIC_OMAP3] = {
+               [I2C_SYSC] = 0x20,
+               [I2C_IRQSTATUS_RAW] = 0x08,
+               [I2C_IRQSTATUS] = 0x08,
+               [I2C_IRQENABLE] = 0x04,
+               [I2C_SYSS] = 0x10,
+               [I2C_BUF] = 0x14,
+               [I2C_CNT] = 0x18,
+               [I2C_DATA] = 0x1c,
+               [I2C_CON] = 0x24,
+               [I2C_OA] = 0x28,
+               [I2C_SA] = 0x2c,
+               [I2C_PSC] = 0x30,
+               [I2C_SCLL] = 0x34,
+               [I2C_SCLH] = 0x38,
+               [I2C_BUFSTAT] = 0x40,
+       },
+       [TI_IIC_OMAP4] = {
+               [I2C_SYSC] = 0x10,
+               [I2C_IRQSTATUS_RAW] = 0x24,
+               [I2C_IRQSTATUS] = 0x28,
+               [I2C_IRQENABLE_SET] = 0x2c,
+               [I2C_IRQENABLE_CLR] = 0x30,
+               [I2C_SYSS] = 0x90,
+               [I2C_BUF] = 0x94,
+               [I2C_CNT] = 0x98,
+               [I2C_DATA] = 0x9c,
+               [I2C_CON] = 0xa4,
+               [I2C_OA] = 0xa8,
+               [I2C_SA] = 0xac,
+               [I2C_PSC] = 0xb0,
+               [I2C_SCLL] = 0xb4,
+               [I2C_SCLH] = 0xb8,
+               [I2C_BUFSTAT] = 0xc0,
+       },
+};
+
 static const struct of_compat_data compat_data[] = {
-       /* compatible           reg shift */
-       { "ti,omap3-i2c",       2 },
-       { "ti,omap4-i2c",       0 },
+       /* compatible           type */
+       { "ti,omap3-i2c",       TI_IIC_OMAP3 },
+       { "ti,omap4-i2c",       TI_IIC_OMAP4 },
        { NULL }
 };
 
@@ -105,7 +170,7 @@
        bus_space_tag_t         sc_iot;
        bus_space_handle_t      sc_ioh;
 
-       u_int                   sc_reg_shift;
+       enum ti_iic_type        sc_type;
 
        void                    *sc_ih;
        kmutex_t                sc_mtx;
@@ -122,13 +187,13 @@
 };
 
 #define I2C_READ_REG(sc, reg)          \
-       bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg) << (sc)->sc_reg_shift)
+       bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)])
 #define I2C_READ_DATA(sc)              \
-       bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, OMAP2_I2C_DATA << (sc)->sc_reg_shift);
+       bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA])
 #define I2C_WRITE_REG(sc, reg, val)    \
-       bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg) << (sc)->sc_reg_shift, (val))
+       bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][(reg)], (val))
 #define I2C_WRITE_DATA(sc, val)                \
-       bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, OMAP2_I2C_DATA << (sc)->sc_reg_shift, (val))
+       bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, ti_iic_regmap[(sc)->sc_type][I2C_DATA], (val))
 
 static int     ti_iic_match(device_t, cfdata_t, void *);
 static void    ti_iic_attach(device_t, device_t, void *);
@@ -174,11 +239,11 @@
        struct ti_iic_softc *sc = device_private(self);
        struct fdt_attach_args * const faa = opaque;
        const int phandle = faa->faa_phandle;
-       int scheme, major, minor, fifodepth, fifo;
+       int fifodepth, fifo;
+       const char *modname;
        char intrstr[128];
        bus_addr_t addr;
        bus_size_t size;
-       uint16_t rev;
 
        if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
                aprint_error(": couldn't get registers\n");
@@ -208,7 +273,7 @@
                aprint_error(": couldn't map registers\n");
                return;
        }
-       sc->sc_reg_shift = of_search_compatible(phandle, compat_data)->data;
+       sc->sc_type = of_search_compatible(phandle, compat_data)->data;
 
        sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_NET, 0,
            ti_iic_intr, sc);
@@ -217,22 +282,16 @@
                return;
        }
 
-       scheme = I2C_REVNB_HI_SCHEME(I2C_READ_REG(sc, OMAP2_I2C_REVNB_HI));
-       rev = I2C_READ_REG(sc, OMAP2_I2C_REVNB_LO);
-       if (scheme == 0) {
-               major = I2C_REV_SCHEME_0_MAJOR(rev);
-               minor = I2C_REV_SCHEME_0_MINOR(rev);
-       } else {
-               major = I2C_REVNB_LO_MAJOR(rev);
-               minor = I2C_REVNB_LO_MINOR(rev);
-       }
-       aprint_normal(": rev %d.%d, scheme %d\n", major, minor, scheme);
+       modname = fdtbus_get_string(phandle, "ti,hwmods");
+       if (modname == NULL)
+               modname = fdtbus_get_string(OF_parent(phandle), "ti,hwmods");
+
+       fifodepth = I2C_BUFSTAT_FIFODEPTH(I2C_READ_REG(sc, I2C_BUFSTAT));
+       fifo = OMAP2_I2C_FIFOBYTES(fifodepth);
+       sc->sc_rxthres = sc->sc_txthres = fifo >> 1;
+
        aprint_naive("\n");
-
-       fifodepth = I2C_BUFSTAT_FIFODEPTH(I2C_READ_REG(sc, OMAP2_I2C_BUFSTAT));
-       fifo = OMAP2_I2C_FIFOBYTES(fifodepth);
-       aprint_normal_dev(self, "%d-bytes FIFO\n", fifo);
-       sc->sc_rxthres = sc->sc_txthres = fifo >> 1;
+       aprint_normal(": I2C controller (%s), %d-bytes FIFO\n", modname, fifo);
 
        ti_iic_reset(sc);
        ti_iic_flush(sc);
@@ -250,10 +309,10 @@
 
        mutex_enter(&sc->sc_mtx);
        DPRINTF(("ti_iic_intr\n"));
-       stat = I2C_READ_REG(sc, OMAP2_I2C_IRQSTATUS);
+       stat = I2C_READ_REG(sc, I2C_IRQSTATUS);
        DPRINTF(("ti_iic_intr pre handle sc->sc_op eq %#x\n", sc->sc_op));
        ti_iic_handle_intr(sc, stat);
-       I2C_WRITE_REG(sc, OMAP2_I2C_IRQSTATUS, stat);
+       I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat);
        if (sc->sc_op == TI_I2CERROR || sc->sc_op == TI_I2CDONE) {
                DPRINTF(("ti_iic_intr post handle sc->sc_op %#x\n", sc->sc_op));
                cv_broadcast(&sc->sc_cv);
@@ -342,19 +401,19 @@
        DPRINTF(("ti_iic_reset\n"));
 
        /* Disable */
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, 0);
+       I2C_WRITE_REG(sc, I2C_CON, 0);
        /* Soft reset */
-       I2C_WRITE_REG(sc, OMAP2_I2C_SYSC, I2C_SYSC_SRST);
+       I2C_WRITE_REG(sc, I2C_SYSC, I2C_SYSC_SRST);
        delay(1000);
        /* enable so that we can check for reset complete */
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, I2C_CON_EN);
+       I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN);
        delay(1000);
        for (i = 0; i < 1000; i++) { /* 1s delay for reset */
-               if (I2C_READ_REG(sc, OMAP2_I2C_SYSS) & I2C_SYSS_RDONE)
+               if (I2C_READ_REG(sc, I2C_SYSS) & I2C_SYSS_RDONE)
                        break;
        }
        /* Disable again */
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, 0);
+       I2C_WRITE_REG(sc, I2C_CON, 0);
        delay(50000);
 
        if (i >= 1000) {
@@ -369,19 +428,19 @@
        sclh = 55;
 
        /* Clocks */
-       I2C_WRITE_REG(sc, OMAP2_I2C_PSC, psc);
-       I2C_WRITE_REG(sc, OMAP2_I2C_SCLL, scll);
-       I2C_WRITE_REG(sc, OMAP2_I2C_SCLH, sclh);
+       I2C_WRITE_REG(sc, I2C_PSC, psc);
+       I2C_WRITE_REG(sc, I2C_SCLL, scll);
+       I2C_WRITE_REG(sc, I2C_SCLH, sclh);
 
        /* Own I2C address */
-       I2C_WRITE_REG(sc, OMAP2_I2C_OA, OMAP2_I2C_SLAVE_ADDR);
+       I2C_WRITE_REG(sc, I2C_OA, OMAP2_I2C_SLAVE_ADDR);
 
        /* 5 bytes fifo */
-       I2C_WRITE_REG(sc, OMAP2_I2C_BUF,
+       I2C_WRITE_REG(sc, I2C_BUF,
            I2C_BUF_RXTRSH(sc->sc_rxthres) | I2C_BUF_TXTRSH(sc->sc_txthres));
 
        /* Enable */
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, I2C_CON_EN);
+       I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN);
 
        return 0;
 }
@@ -426,21 +485,25 @@
        sc->sc_buflen = buflen;
        sc->sc_bufidx = 0;
 
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, I2C_CON_EN | I2C_CON_MST | I2C_CON_STP);
+       I2C_WRITE_REG(sc, I2C_CON, I2C_CON_EN | I2C_CON_MST | I2C_CON_STP);
        DPRINTF(("ti_iic_op: op %d con 0x%x ", op, con));
-       I2C_WRITE_REG(sc, OMAP2_I2C_CNT, buflen);
-       I2C_WRITE_REG(sc, OMAP2_I2C_SA, (addr & I2C_SA_MASK));
-       DPRINTF(("SA 0x%x len %d\n", I2C_READ_REG(sc, OMAP2_I2C_SA), I2C_READ_REG(sc, OMAP2_I2C_CNT)));
+       I2C_WRITE_REG(sc, I2C_CNT, buflen);
+       I2C_WRITE_REG(sc, I2C_SA, (addr & I2C_SA_MASK));
+       DPRINTF(("SA 0x%x len %d\n", I2C_READ_REG(sc, I2C_SA), I2C_READ_REG(sc, I2C_CNT)));
 
        if ((flags & I2C_F_POLL) == 0) {
                /* clear any pending interrupt */
-               I2C_WRITE_REG(sc, OMAP2_I2C_IRQSTATUS,
-                   I2C_READ_REG(sc, OMAP2_I2C_IRQSTATUS));
+               I2C_WRITE_REG(sc, I2C_IRQSTATUS,
+                   I2C_READ_REG(sc, I2C_IRQSTATUS));
                /* and enable */
-               I2C_WRITE_REG(sc, OMAP2_I2C_IRQENABLE_SET, mask);
+               if (sc->sc_type == TI_IIC_OMAP4) {
+                       I2C_WRITE_REG(sc, I2C_IRQENABLE_SET, mask);
+               } else {
+                       I2C_WRITE_REG(sc, I2C_IRQENABLE, mask);
+               }
        }
        /* start transfer */
-       I2C_WRITE_REG(sc, OMAP2_I2C_CON, con);
+       I2C_WRITE_REG(sc, I2C_CON, con);
 
        if ((flags & I2C_F_POLL) == 0) {
                /* and wait for completion */
@@ -455,7 +518,11 @@
                DPRINTF(("ti_iic_op waiting done, op %#x\n", sc->sc_op));
 
                /* disable interrupts */
-               I2C_WRITE_REG(sc, OMAP2_I2C_IRQENABLE_CLR, 0xffff);
+               if (sc->sc_type == TI_IIC_OMAP4) {
+                       I2C_WRITE_REG(sc, I2C_IRQENABLE_CLR, 0xffff);
+               } else {
+                       I2C_WRITE_REG(sc, I2C_IRQENABLE, 0);
+               }
        } else {
                /* poll for completion */
                DPRINTF(("ti_iic_op polling, op %x\n", sc->sc_op));
@@ -468,14 +535,14 @@
                        } else {
                                ti_iic_handle_intr(sc, stat);
                        }
-                       I2C_WRITE_REG(sc, OMAP2_I2C_IRQSTATUS, stat);
+                       I2C_WRITE_REG(sc, I2C_IRQSTATUS, stat);
                }
                DPRINTF(("ti_iic_op polling done, op now %x\n", sc->sc_op));
        }
        mutex_exit(&sc->sc_mtx);



Home | Main Index | Thread Index | Old Index