Module Name: src Committed By: jmcneill Date: Tue Dec 30 17:15:31 UTC 2014
Modified Files: src/sys/arch/arm/rockchip: files.rockchip obio.c rockchip_board.c rockchip_var.h Added Files: src/sys/arch/arm/rockchip: rockchip_i2c.c rockchip_i2creg.h Log Message: add I2C driver To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/rockchip/files.rockchip cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/rockchip/obio.c cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/rockchip/rockchip_board.c cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/rockchip/rockchip_i2c.c \ src/sys/arch/arm/rockchip/rockchip_i2creg.h cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/rockchip/rockchip_var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/files.rockchip diff -u src/sys/arch/arm/rockchip/files.rockchip:1.3 src/sys/arch/arm/rockchip/files.rockchip:1.4 --- src/sys/arch/arm/rockchip/files.rockchip:1.3 Sat Dec 27 16:18:50 2014 +++ src/sys/arch/arm/rockchip/files.rockchip Tue Dec 30 17:15:31 2014 @@ -1,4 +1,4 @@ -# $NetBSD: files.rockchip,v 1.3 2014/12/27 16:18:50 jmcneill Exp $ +# $NetBSD: files.rockchip,v 1.4 2014/12/30 17:15:31 jmcneill Exp $ # # Configuration info for Rockchip ARM Peripherals # @@ -18,7 +18,7 @@ file arch/arm/rockchip/rockchip_dma.c file arch/arm/arm/bus_space_a4x.S obio # On-board I/O -device obio {[addr = -1], [size = -1], [width = -1], [intr = -1], [mult = 1]}: bus_space_generic +device obio {[addr = -1], [size = -1], [width = -1], [intr = -1], [mult = 1], [port = -1]}: bus_space_generic attach obio at mainbus file arch/arm/rockchip/obio.c obio @@ -26,6 +26,11 @@ file arch/arm/rockchip/obio.c obio attach com at obio with obiouart file arch/arm/rockchip/obio_com.c obiouart +# I2C controller +device rkiic: i2cbus, i2cexec +attach rkiic at obio +file arch/arm/rockchip/rockchip_i2c.c rkiic + # SD/MMC (Synopsys DesignWare) attach dwcmmc at obio with rkdwcmmc file arch/arm/rockchip/rockchip_dwcmmc.c rkdwcmmc Index: src/sys/arch/arm/rockchip/obio.c diff -u src/sys/arch/arm/rockchip/obio.c:1.4 src/sys/arch/arm/rockchip/obio.c:1.5 --- src/sys/arch/arm/rockchip/obio.c:1.4 Tue Dec 30 12:38:20 2014 +++ src/sys/arch/arm/rockchip/obio.c Tue Dec 30 17:15:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: obio.c,v 1.4 2014/12/30 12:38:20 jmcneill Exp $ */ +/* $NetBSD: obio.c,v 1.5 2014/12/30 17:15:31 jmcneill Exp $ */ /* * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. @@ -38,7 +38,7 @@ #include "opt_rockchip.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.4 2014/12/30 12:38:20 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.5 2014/12/30 17:15:31 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -120,6 +120,8 @@ obio_print(void *aux, const char *pnp) aprint_normal(" intr %d", obio->obio_intr); if (obio->obio_mult != OBIOCF_MULT_DEFAULT) aprint_normal(" mult %d", obio->obio_mult); + if (obio->obio_port != OBIOCF_PORT_DEFAULT) + aprint_normal(" port %d", obio->obio_port); return UNCONF; } @@ -147,6 +149,7 @@ obio_search(device_t parent, cfdata_t cf obio.obio_width = cf->cf_loc[OBIOCF_WIDTH]; obio.obio_intr = cf->cf_loc[OBIOCF_INTR]; obio.obio_mult = cf->cf_loc[OBIOCF_MULT]; + obio.obio_port = cf->cf_loc[OBIOCF_PORT]; obio.obio_dmat = &rockchip_bus_dma_tag; switch (cf->cf_loc[OBIOCF_MULT]) { @@ -249,10 +252,11 @@ static void obio_dump_clocks(void) { printf("APLL: %u Hz\n", rockchip_apll_get_rate()); + printf("CPLL: %u Hz\n", rockchip_cpll_get_rate()); printf("GPLL: %u Hz\n", rockchip_gpll_get_rate()); printf("CPU: %u Hz\n", rockchip_cpu_get_rate()); printf("AHB: %u Hz\n", rockchip_ahb_get_rate()); + printf("APB: %u Hz\n", rockchip_apb_get_rate()); printf("A9PERIPH: %u Hz\n", rockchip_a9periph_get_rate()); - printf("MMC0: %u Hz\n", rockchip_mmc0_get_rate()); } #endif Index: src/sys/arch/arm/rockchip/rockchip_board.c diff -u src/sys/arch/arm/rockchip/rockchip_board.c:1.6 src/sys/arch/arm/rockchip/rockchip_board.c:1.7 --- src/sys/arch/arm/rockchip/rockchip_board.c:1.6 Tue Dec 30 03:53:52 2014 +++ src/sys/arch/arm/rockchip/rockchip_board.c Tue Dec 30 17:15:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rockchip_board.c,v 1.6 2014/12/30 03:53:52 jmcneill Exp $ */ +/* $NetBSD: rockchip_board.c,v 1.7 2014/12/30 17:15:31 jmcneill Exp $ */ /*- * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include "opt_rockchip.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.6 2014/12/30 03:53:52 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.7 2014/12/30 17:15:31 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -115,6 +115,12 @@ rockchip_gpll_get_rate(void) } u_int +rockchip_cpll_get_rate(void) +{ + return rockchip_pll_get_rate(CRU_CPLL_CON0_REG, CRU_CPLL_CON1_REG); +} + +u_int rockchip_apll_get_rate(void) { return rockchip_pll_get_rate(CRU_APLL_CON0_REG, CRU_APLL_CON1_REG); @@ -364,6 +370,26 @@ rockchip_ahb_get_rate(void) } u_int +rockchip_apb_get_rate(void) +{ + bus_space_tag_t bst = &rockchip_bs_tag; + bus_space_handle_t bsh; + uint32_t clksel_con10; + uint32_t pclk_div, aclk_div; + + rockchip_get_cru_bsh(&bsh); + + clksel_con10 = bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(10)); + + pclk_div = __SHIFTOUT(clksel_con10, + CRU_CLKSEL_CON10_PERI_PCLK_DIV_CON) + 1; + aclk_div = 1 << __SHIFTOUT(clksel_con10, + CRU_CLKSEL_CON10_PERI_ACLK_DIV_CON); + + return rockchip_gpll_get_rate() / (pclk_div * aclk_div); +} + +u_int rockchip_mmc0_get_rate(void) { bus_space_tag_t bst = &rockchip_bs_tag; @@ -416,3 +442,13 @@ rockchip_mmc0_set_div(u_int div) return 0; } + +u_int +rockchip_i2c_get_rate(u_int port) +{ + if (port == 0 || port == 1) { + return rockchip_a9periph_get_rate(); + } else { + return rockchip_apb_get_rate(); + } +} Index: src/sys/arch/arm/rockchip/rockchip_var.h diff -u src/sys/arch/arm/rockchip/rockchip_var.h:1.7 src/sys/arch/arm/rockchip/rockchip_var.h:1.8 --- src/sys/arch/arm/rockchip/rockchip_var.h:1.7 Tue Dec 30 03:53:52 2014 +++ src/sys/arch/arm/rockchip/rockchip_var.h Tue Dec 30 17:15:31 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rockchip_var.h,v 1.7 2014/12/30 03:53:52 jmcneill Exp $ */ +/* $NetBSD: rockchip_var.h,v 1.8 2014/12/30 17:15:31 jmcneill Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -46,6 +46,7 @@ struct obio_attach_args { int obio_intr; /* irq */ int obio_width; /* bus width */ unsigned int obio_mult; /* multiplier */ + int obio_port; /* port */ bus_dma_tag_t obio_dmat; const char *obio_name; }; @@ -65,11 +66,14 @@ bool rockchip_is_chip(const char *); u_int rockchip_apll_get_rate(void); u_int rockchip_apll_set_rate(u_int); +u_int rockchip_cpll_get_rate(void); u_int rockchip_gpll_get_rate(void); u_int rockchip_cpu_get_rate(void); u_int rockchip_ahb_get_rate(void); +u_int rockchip_apb_get_rate(void); u_int rockchip_a9periph_get_rate(void); u_int rockchip_mmc0_get_rate(void); u_int rockchip_mmc0_set_div(u_int); +u_int rockchip_i2c_get_rate(u_int); #endif /* _ARM_ROCKCHIP_ROCKCHIP_VAR_H_ */ Added files: Index: src/sys/arch/arm/rockchip/rockchip_i2c.c diff -u /dev/null src/sys/arch/arm/rockchip/rockchip_i2c.c:1.1 --- /dev/null Tue Dec 30 17:15:31 2014 +++ src/sys/arch/arm/rockchip/rockchip_i2c.c Tue Dec 30 17:15:31 2014 @@ -0,0 +1,369 @@ +/* $NetBSD: rockchip_i2c.c,v 1.1 2014/12/30 17:15:31 jmcneill Exp $ */ + +/*- + * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca> + * 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 ``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 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 "locators.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: rockchip_i2c.c,v 1.1 2014/12/30 17:15:31 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/mutex.h> +#include <sys/condvar.h> + +#include <arm/rockchip/rockchip_reg.h> +#include <arm/rockchip/rockchip_var.h> + +#include <arm/rockchip/rockchip_i2creg.h> + +#include <dev/i2c/i2cvar.h> + +#define RKIIC_CLOCK_RATE 1000000 + +struct rkiic_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + void *sc_ih; + + struct i2c_controller sc_ic; + kmutex_t sc_lock; + kcondvar_t sc_cv; + device_t sc_i2cdev; + u_int sc_port; + + uint32_t sc_intr_ipd; +}; + +static int rkiic_match(device_t, cfdata_t, void *); +static void rkiic_attach(device_t, device_t, void *); + +static int rkiic_intr(void *); + +static int rkiic_acquire_bus(void *, int); +static void rkiic_release_bus(void *, int); +static int rkiic_exec(void *, i2c_op_t, i2c_addr_t, const void *, + size_t, void *, size_t, int); + +static int rkiic_wait(struct rkiic_softc *, uint32_t, int, int); +static int rkiic_read(struct rkiic_softc *, i2c_addr_t, + uint8_t *, size_t, int); +static int rkiic_write(struct rkiic_softc *, i2c_addr_t, + const uint8_t *, size_t, int); +static int rkiic_set_rate(struct rkiic_softc *, u_int); + +CFATTACH_DECL_NEW(rkiic, sizeof(struct rkiic_softc), + rkiic_match, rkiic_attach, NULL, NULL); + +#define I2C_WRITE(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) +#define I2C_READ(sc, reg) \ + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) + +static int +rkiic_match(device_t parent, cfdata_t cf, void *aux) +{ + struct obio_attach_args * const obio = aux; + + if (obio->obio_port == OBIOCF_PORT_DEFAULT) + return 0; + + return 1; +} + +static void +rkiic_attach(device_t parent, device_t self, void *aux) +{ + struct rkiic_softc *sc = device_private(self); + struct obio_attach_args * const obio = aux; + struct i2cbus_attach_args iba; + + sc->sc_dev = self; + sc->sc_bst = obio->obio_bst; + bus_space_subregion(obio->obio_bst, obio->obio_bsh, obio->obio_offset, + obio->obio_size, &sc->sc_bsh); + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED); + cv_init(&sc->sc_cv, device_xname(self)); + sc->sc_port = obio->obio_port; + + aprint_naive("\n"); + aprint_normal(": I2C%u\n", sc->sc_port); + + if (obio->obio_intr != OBIOCF_INTR_DEFAULT) { + sc->sc_ih = intr_establish(obio->obio_intr, IPL_SCHED, + IST_LEVEL, rkiic_intr, sc); + if (sc->sc_ih == NULL) { + aprint_error_dev(self, + "couldn't establish interrupt\n"); + /* Not fatal; will use polling mode */ + } + } + + sc->sc_ic.ic_cookie = sc; + sc->sc_ic.ic_acquire_bus = rkiic_acquire_bus; + sc->sc_ic.ic_release_bus = rkiic_release_bus; + sc->sc_ic.ic_exec = rkiic_exec; + + iba.iba_tag = &sc->sc_ic; + sc->sc_i2cdev = config_found_ia(self, "i2cbus", + &iba, iicbus_print); +} + +static int +rkiic_intr(void *priv) +{ + struct rkiic_softc *sc = priv; + uint32_t ipd; + + ipd = I2C_READ(sc, I2C_IPD_REG); + if (!ipd) + return 0; + + I2C_WRITE(sc, I2C_IPD_REG, ipd); + + mutex_enter(&sc->sc_lock); + sc->sc_intr_ipd |= ipd; + cv_broadcast(&sc->sc_cv); + mutex_exit(&sc->sc_lock); + + return 1; +} + +static int +rkiic_acquire_bus(void *priv, int flags) +{ + struct rkiic_softc *sc = priv; + + mutex_enter(&sc->sc_lock); + + return 0; +} + +static void +rkiic_release_bus(void *priv, int flags) +{ + struct rkiic_softc *sc = priv; + + mutex_exit(&sc->sc_lock); +} + +static int +rkiic_exec(void *priv, i2c_op_t op, i2c_addr_t addr, + const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) +{ + struct rkiic_softc *sc = priv; + uint32_t con; + u_int mode; + int error; + + KASSERT(mutex_owned(&sc->sc_lock)); + + if (sc->sc_ih == NULL) { + flags |= I2C_F_POLL; + } + + error = rkiic_set_rate(sc, RKIIC_CLOCK_RATE); + if (error) + return error; + + if (cmdlen > 0) { + if (I2C_OP_READ_P(op)) { + mode = I2C_CON_MODE_RRX; + } else { + mode = I2C_CON_MODE_TRX; + } + } else { + if (I2C_OP_READ_P(op)) { + mode = I2C_CON_MODE_RX; + } else { + mode = I2C_CON_MODE_TX; + } + } + con = I2C_CON_START | I2C_CON_EN | __SHIFTIN(mode, I2C_CON_MODE); + + I2C_WRITE(sc, I2C_CON_REG, con); + + if (cmdlen > 0) { + error = rkiic_write(sc, addr, cmdbuf, cmdlen, flags); + if (error) { + goto done; + } + } + + if (I2C_OP_READ_P(op)) { + error = rkiic_read(sc, addr, buf, len, flags); + } else { + error = rkiic_write(sc, addr, buf, len, flags); + } + +done: + if (I2C_OP_STOP_P(op)) { + I2C_WRITE(sc, I2C_CON_REG, I2C_CON_STOP); + } + + return error; +} + +static int +rkiic_wait(struct rkiic_softc *sc, uint32_t mask, int timeout, int flags) +{ + int retry, error; + + KASSERT(mutex_owned(&sc->sc_lock)); + + if (sc->sc_intr_ipd & mask) + return 0; + + if (flags & I2C_F_POLL) { + retry = (timeout / hz) * 1000000; + while (retry > 0) { + if (I2C_READ(sc, I2C_IPD_REG) & mask) + return 0; + delay(1); + --retry; + } + } else { + retry = timeout / hz; + + while (retry > 0) { + error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz); + if (error && error != EWOULDBLOCK) + return error; + if (sc->sc_intr_ipd & mask) + return 0; + --retry; + } + } + + return ETIMEDOUT; +} + +static int +rkiic_read(struct rkiic_softc *sc, i2c_addr_t addr, uint8_t *buf, + size_t buflen, int flags) +{ + u_int off, byte; + size_t resid; + int error; + + if (buflen > 32) + return EINVAL; + + sc->sc_intr_ipd = 0; + + if (!(flags & I2C_F_POLL)) { + I2C_WRITE(sc, I2C_IEN_REG, I2C_INT_MBRF); + } + + I2C_WRITE(sc, I2C_MRXCNT_REG, __SHIFTIN(buflen, I2C_MRXCNT_COUNT)); + + error = rkiic_wait(sc, I2C_INT_MBRF, hz, flags); + if (error) + goto done; + + for (off = 0, resid = buflen; off < 8 && resid > 0; off++) { + const uint32_t data = I2C_READ(sc, I2C_RXDATA_REG(off)); + for (byte = 0; byte < 4 && resid > 0; byte++, resid--) { + buf[off * 4 + byte] = (data >> (byte * 8)) & 0xff; + } + } + +done: + if (!(flags & I2C_F_POLL)) { + I2C_WRITE(sc, I2C_IEN_REG, 0); + } + + return error; +} + +static int +rkiic_write(struct rkiic_softc *sc, i2c_addr_t addr, const uint8_t *buf, + size_t buflen, int flags) +{ + u_int off, byte; + size_t resid; + int error; + + if (buflen > 32) + return EINVAL; + + sc->sc_intr_ipd = 0; + + if (!(flags & I2C_F_POLL)) { + I2C_WRITE(sc, I2C_IEN_REG, I2C_INT_MBTF); + } + + for (off = 0, resid = buflen; off < 8 && resid > 0; off++) { + uint32_t data = 0; + for (byte = 0; byte < 4 && resid > 0; byte++, resid--) { + data |= buf[off * 4 + byte] << (byte * 8); + } + I2C_WRITE(sc, I2C_TXDATA_REG(off), data); + } + + I2C_WRITE(sc, I2C_MTXCNT_REG, __SHIFTIN(buflen, I2C_MTXCNT_COUNT)); + + error = rkiic_wait(sc, I2C_INT_MBTF, hz, flags); + if (error) + goto done; + +done: + if (!(flags & I2C_F_POLL)) { + I2C_WRITE(sc, I2C_IEN_REG, 0); + } + + return error; + +} + +static int +rkiic_set_rate(struct rkiic_softc *sc, u_int rate) +{ + u_int i2c_rate = rockchip_i2c_get_rate(sc->sc_port); + u_int div, divh, divl; + + if (i2c_rate == 0) + return ENXIO; + + /* + * From RK3188 datasheet: + * SCL Divisor = 8*(CLKDIVL + CLKDIVH) + * SCL = PCLK/ SCLK Divisor + */ + div = howmany(i2c_rate, rate * 8); + divh = divl = howmany(div, 2); + I2C_WRITE(sc, I2C_CLKDIV_REG, + __SHIFTIN(divh, I2C_CON_CLKDIVH) | + __SHIFTIN(divl, I2C_CON_CLKDIVL)); + + return 0; +} Index: src/sys/arch/arm/rockchip/rockchip_i2creg.h diff -u /dev/null src/sys/arch/arm/rockchip/rockchip_i2creg.h:1.1 --- /dev/null Tue Dec 30 17:15:31 2014 +++ src/sys/arch/arm/rockchip/rockchip_i2creg.h Tue Dec 30 17:15:31 2014 @@ -0,0 +1,82 @@ +/* $NetBSD: rockchip_i2creg.h,v 1.1 2014/12/30 17:15:31 jmcneill Exp $ */ + +/*- + * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca> + * 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 ``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 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. + */ + +#ifndef _ROCKCHIP_I2CREG_H +#define _ROCKCHIP_I2CREG_H + +#define I2C_CON_REG 0x0000 +#define I2C_CLKDIV_REG 0x0004 +#define I2C_MRXADDR_REG 0x0008 +#define I2C_MRXRADDR_REG 0x000c +#define I2C_MTXCNT_REG 0x0010 +#define I2C_MRXCNT_REG 0x0014 +#define I2C_IEN_REG 0x0018 +#define I2C_IPD_REG 0x001c +#define I2C_FCNT_REG 0x0020 +#define I2C_TXDATA_REG(n) (0x100 + (4 * (n))) +#define I2C_RXDATA_REG(n) (0x200 + (4 * (n))) + +#define I2C_CON_ACT2NAK __BIT(6) +#define I2C_CON_ACK __BIT(5) +#define I2C_CON_STOP __BIT(4) +#define I2C_CON_START __BIT(3) +#define I2C_CON_MODE __BITS(2,1) +#define I2C_CON_MODE_TX 0 +#define I2C_CON_MODE_TRX 1 +#define I2C_CON_MODE_RX 2 +#define I2C_CON_MODE_RRX 3 +#define I2C_CON_EN __BIT(0) + +#define I2C_CON_CLKDIVH __BITS(31,16) +#define I2C_CON_CLKDIVL __BITS(15,0) + +#define I2C_MRXADDR_ADDHVLD __BIT(26) +#define I2C_MRXADDR_ADDMVLD __BIT(25) +#define I2C_MRXADDR_ADDLVLD __BIT(24) +#define I2C_MRXADDR_SADDR __BITS(23,0) + +#define I2C_MRXRADDR_SRADDHVLD __BIT(26) +#define I2C_MRXRADDR_SRADDMVLD __BIT(25) +#define I2C_MRXRADDR_SRADDLVLD __BIT(24) +#define I2C_MRXADDR_SADDR __BITS(23,0) + +#define I2C_MTXCNT_COUNT __BITS(5,0) + +#define I2C_MRXCNT_COUNT __BITS(5,0) + +#define I2C_INT_NAKRCV __BIT(6) +#define I2C_INT_STOP __BIT(5) +#define I2C_INT_START __BIT(4) +#define I2C_INT_MBRF __BIT(3) +#define I2C_INT_MBTF __BIT(2) +#define I2C_INT_BRF __BIT(1) +#define I2C_INT_BTF __BIT(0) + +#define I2C_FCNT_COUNT __BITS(5,0) + +#endif /* !_ROCKCHIP_I2CREG_H */