summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarty <marty@NetBSD.org>2015-12-24 21:30:05 +0000
committermarty <marty@NetBSD.org>2015-12-24 21:30:05 +0000
commit8a82091c39a591ce8f3e310aa2bc5b36dfdf721e (patch)
tree19d9fcca93d9c82ae7dface71909e9c9f43b6963
parent606f48a166a5ab8d5ae3f3e12de7c024f8783f08 (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.c97
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);