diff options
| author | marty <marty@NetBSD.org> | 2015-12-24 21:30:05 +0000 |
|---|---|---|
| committer | marty <marty@NetBSD.org> | 2015-12-24 21:30:05 +0000 |
| commit | 8a82091c39a591ce8f3e310aa2bc5b36dfdf721e (patch) | |
| tree | 19d9fcca93d9c82ae7dface71909e9c9f43b6963 | |
| parent | 606f48a166a5ab8d5ae3f3e12de7c024f8783f08 (diff) | |
XU4 I2C snapshot
This is a complete, but untested, driver; except that it needs to be able
to configure gpios and, afaict, we don't yet have an fdtbus_gpio_* function
that will do that.
| -rw-r--r-- | sys/arch/arm/samsung/exynos_i2c.c | 97 |
1 files changed, 77 insertions, 20 deletions
diff --git a/sys/arch/arm/samsung/exynos_i2c.c b/sys/arch/arm/samsung/exynos_i2c.c index 00aaad49471..709f9dc0904 100644 --- a/sys/arch/arm/samsung/exynos_i2c.c +++ b/sys/arch/arm/samsung/exynos_i2c.c @@ -1,4 +1,4 @@ -/* $NetBSD: exynos_i2c.c,v 1.7 2015/12/22 22:32:54 jmcneill Exp $ */ +/* $NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $ */ /* * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #include "opt_arm_debug.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.7 2015/12/22 22:32:54 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -61,8 +61,8 @@ struct exynos_i2c_softc { void * sc_ih; u_int sc_port; - struct fdtbus_gpio_pin sc_sda; - struct fdtbus_gpio_pin sc_slc; + struct fdtbus_gpio_pin *sc_sda; + struct fdtbus_gpio_pin *sc_scl; bool sc_sda_is_output; struct i2c_controller sc_ic; kmutex_t sc_lock; @@ -92,6 +92,14 @@ static void exynos_i2c_attach(device_t, device_t, void *); CFATTACH_DECL_NEW(exynos_i2c, sizeof(struct exynos_i2c_softc), exynos_i2c_match, exynos_i2c_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)) + +#define IICON 0 +#define IRQPEND (1<<4) + static int exynos_i2c_match(device_t self, cfdata_t cf, void *aux) { @@ -114,6 +122,12 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux) bus_size_t size; int error; + char result[64]; + int i2c_handle; + int len; + int handle; + int func /*, pud, drv */; + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { aprint_error(": couldn't get registers\n"); return; @@ -132,7 +146,7 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux) sc->sc_port = i2c_port++; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); cv_init(&sc->sc_cv, device_xname(self)); - aprint_normal(" @ 0x%08x", (uint)addr); + aprint_normal(" @ 0x%08x\n", (uint)addr); if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { aprint_error_dev(self, "failed to decode interrupt\n"); @@ -148,6 +162,50 @@ exynos_i2c_attach(device_t parent, device_t self, void *aux) } aprint_normal_dev(self, "interrupting on %s\n", intrstr); + len = OF_getprop(phandle, "pinctrl-0", (char *)&handle, + sizeof(handle)); + if (len != sizeof(int)) { + aprint_error_dev(self, "couldn't get pinctrl-0.\n"); + return; + } + + i2c_handle = fdtbus_get_phandle_from_native(be32toh(handle)); + len = OF_getprop(i2c_handle, "samsung,pins", result, sizeof(result)); + if (len <= 0) { + aprint_error_dev(self, "couldn't get pins.\n"); + return; + } + + len = OF_getprop(i2c_handle, "samsung,pin-function", + &handle, sizeof(handle)); + if (len <= 0) { + aprint_error_dev(self, "couldn't get pin-function.\n"); + return; + } else + func = be32toh(handle); + + sc->sc_sda = fdtbus_gpio_acquire(phandle, &result[0], func); + sc->sc_scl = fdtbus_gpio_acquire(phandle, &result[7], func); + + /* MJF: Need fdtbus_gpio_configure */ +#if 0 + len = OF_getprop(i2c_handle, "samsung,pin-pud", &handle, + sizeof(&handle)); + if (len <= 0) { + aprint_error_dev(self, "couldn't get pin-pud.\n"); + return; + } else + pud = be32toh(handle); + + len = OF_getprop(i2c_handle, "samsung,pin-drv", &handle, + sizeof(&handle)); + if (len <= 0) { + aprint_error_dev(self, "couldn't get pin-drv.\n"); + return; + } else + drv = be32toh(handle); + +#endif if (!exynos_i2c_attach_i2cbus(sc, &sc->sc_ic)) return; @@ -168,8 +226,6 @@ exynos_i2c_attach_i2cbus(struct exynos_i2c_softc *i2c_sc, i2c_cntr->ic_read_byte = exynos_i2c_read_byte; i2c_cntr->ic_write_byte = exynos_i2c_write_byte; - /*MJF: FIX ME needs gpio pins */ -// exynos_gpio_pinset_acquire(pinset); return 1; } @@ -182,28 +238,28 @@ static void exynos_i2c_bb_set_bits(void *cookie, uint32_t bits) { struct exynos_i2c_softc *i2c_sc = cookie; - int sda, slc; + int sda, scl; sda = (bits & EXYNOS_I2C_BB_SDA) ? true : false; - slc = (bits & EXYNOS_I2C_BB_SCL) ? true : false; + scl = (bits & EXYNOS_I2C_BB_SCL) ? true : false; if (i2c_sc->sc_sda_is_output) - fdtbus_gpio_write(&i2c_sc->sc_sda, sda); - fdtbus_gpio_write(&i2c_sc->sc_slc, slc); + fdtbus_gpio_write(i2c_sc->sc_sda, sda); + fdtbus_gpio_write(i2c_sc->sc_scl, scl); } static uint32_t exynos_i2c_bb_read_bits(void *cookie) { struct exynos_i2c_softc *i2c_sc = cookie; - int sda, slc; + int sda, scl; sda = 0; if (!i2c_sc->sc_sda_is_output) - sda = fdtbus_gpio_read(&i2c_sc->sc_sda); - slc = fdtbus_gpio_read(&i2c_sc->sc_slc); + sda = fdtbus_gpio_read(i2c_sc->sc_sda); + scl = fdtbus_gpio_read(i2c_sc->sc_scl); - return (sda ? EXYNOS_I2C_BB_SDA : 0) | (slc ? EXYNOS_I2C_BB_SCL : 0); + return (sda ? EXYNOS_I2C_BB_SDA : 0) | (scl ? EXYNOS_I2C_BB_SCL : 0); } static void @@ -218,7 +274,7 @@ exynos_i2c_bb_set_dir(void *cookie, uint32_t bits) flags = GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE; /* MJF: This is wrong but fdtbus has no ctrl operation */ - fdtbus_gpio_write(&i2c_sc->sc_sda, flags); + fdtbus_gpio_write(i2c_sc->sc_sda, flags); } static const struct i2c_bitbang_ops exynos_i2c_bbops = { @@ -238,10 +294,11 @@ exynos_i2c_intr(void *priv) { struct exynos_i2c_softc * const sc = priv; -// const uint32_t istatus = I2C_READ(sc, I2C_INTERRUPT_STATUS_REG); -// if (istatus == 0) -// return 0; -// I2C_WRITE(sc, I2C_INTERRUPT_STATUS_REG, istatus); + uint32_t istatus = I2C_READ(sc, IICON); + if (!(istatus & IRQPEND)) + return 0; + istatus &= ~IRQPEND; + I2C_WRITE(sc, IICON, istatus); mutex_enter(&sc->sc_lock); cv_broadcast(&sc->sc_cv); |
