Module Name:    src
Committed By:   marty
Date:           Wed Dec 30 04:30:27 UTC 2015

Modified Files:
        src/sys/arch/arm/samsung: exynos_combiner.c exynos_gpio.c exynos_i2c.c
            exynos_pinctrl.c exynos_var.h

Log Message:
XU4 i2c, gpio & pinctrl changes

modify exynos_gpio.c to support the new pinctrl model.
set up the new pinctrl model in exynos_pinctrl.c

Flesh out exynos_i2c.c and set it up to use the new pinctrl model.  NOTE:
exynos_i2c.c is still incomplete.  I need to figure out what to set the
prescaler and scaler to.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/samsung/exynos_combiner.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/samsung/exynos_gpio.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/samsung/exynos_i2c.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/samsung/exynos_pinctrl.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/samsung/exynos_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/samsung/exynos_combiner.c
diff -u src/sys/arch/arm/samsung/exynos_combiner.c:1.3 src/sys/arch/arm/samsung/exynos_combiner.c:1.4
--- src/sys/arch/arm/samsung/exynos_combiner.c:1.3	Thu Dec 24 21:20:17 2015
+++ src/sys/arch/arm/samsung/exynos_combiner.c	Wed Dec 30 04:30:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $ */
+/*	$NetBSD: exynos_combiner.c,v 1.4 2015/12/30 04:30:27 marty Exp $ */
 
 /*-
 * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.4 2015/12/30 04:30:27 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -197,7 +197,7 @@ exynos_combiner_intrstr(device_t dev, in
 
 	kmem_free(interrupts, len);
 
-	snprintf(buf, buflen, "LIC irq %d", irq);
+	snprintf(buf, buflen, "combiner irq %d", irq);
 
 	return true;
 }

Index: src/sys/arch/arm/samsung/exynos_gpio.c
diff -u src/sys/arch/arm/samsung/exynos_gpio.c:1.21 src/sys/arch/arm/samsung/exynos_gpio.c:1.22
--- src/sys/arch/arm/samsung/exynos_gpio.c:1.21	Sun Dec 27 12:42:14 2015
+++ src/sys/arch/arm/samsung/exynos_gpio.c	Wed Dec 30 04:30:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_gpio.c,v 1.21 2015/12/27 12:42:14 jmcneill Exp $ */
+/*	$NetBSD: exynos_gpio.c,v 1.22 2015/12/30 04:30:27 marty Exp $ */
 
 /*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.21 2015/12/27 12:42:14 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.22 2015/12/30 04:30:27 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -53,16 +53,6 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.
 
 #include <dev/fdt/fdtvar.h>
 
-struct exynos_gpio_pin_cfg {
-	uint32_t cfg;
-	uint32_t pud;
-	uint32_t drv;
-	uint32_t conpwd;
-	uint32_t pudpwd;
-};
-
-struct exynos_gpio_softc;
-
 struct exynos_gpio_bank {
 	const char		bank_name[6];
 	device_t		bank_dev;
@@ -80,12 +70,6 @@ struct exynos_gpio_bank {
 	struct exynos_gpio_bank * bank_next;
 };
 
-struct exynos_gpio_softc {
-	device_t		sc_dev;
-	bus_space_tag_t		sc_bst;
-	bus_space_handle_t	sc_bsh;
-};
-
 struct exynos_gpio_pin {
 	struct exynos_gpio_softc *pin_sc;
 	int			  pin_no;
@@ -144,7 +128,7 @@ static struct exynos_gpio_bank exynos5_b
 	GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2),
 	GPIO_GRP(5, MUXD, 0x0100, gph0, 4),
 
-	GPIO_GRP(5, MUXE, 0x0000, gpz0, 7),
+	GPIO_GRP(5, MUXE, 0x0000, gpz, 7),
 
 };
 
@@ -159,7 +143,6 @@ static void exynos_gpio_fdt_release(devi
 
 static int exynos_gpio_fdt_read(device_t, void *, bool);
 static void exynos_gpio_fdt_write(device_t, void *, int, bool);
-static struct exynos_gpio_bank *exynos_gpio_bank_lookup(const char *);
 static int exynos_gpio_cfprint(void *, const char *);
 
 struct fdtbus_gpio_controller_func exynos_gpio_funcs = {
@@ -279,7 +262,27 @@ exynos_gpio_pin_ctl(void *cookie, int pi
 	exynos_gpio_update_cfg_regs(bank, &ncfg);
 }
 
-void
+void exynos_gpio_pin_ctl_read(const struct exynos_gpio_bank *bank,
+			      struct exynos_gpio_pin_cfg *cfg)
+{
+	cfg->cfg = GPIO_READ(bank, EXYNOS_GPIO_CON);
+	cfg->pud = GPIO_READ(bank, EXYNOS_GPIO_PUD);
+	cfg->drv = GPIO_READ(bank, EXYNOS_GPIO_DRV);
+	cfg->conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
+	cfg->pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
+}
+
+void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank,
+			       const struct exynos_gpio_pin_cfg *cfg)
+{
+		GPIO_WRITE(bank, EXYNOS_GPIO_CON, cfg->cfg);
+		GPIO_WRITE(bank, EXYNOS_GPIO_PUD, cfg->pud);
+		GPIO_WRITE(bank, EXYNOS_GPIO_DRV, cfg->drv);
+		GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, cfg->conpwd);
+		GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, cfg->pudpwd);
+}
+
+struct exynos_gpio_softc *
 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent,
 			const struct fdt_attach_args *faa, int node)
 {
@@ -294,13 +297,14 @@ exynos_gpio_bank_config(struct exynos_pi
 	if (bank == NULL) {
 		aprint_error_dev(parent->sc_dev, "no bank found for %s\n",
 		    result);
-		return;
+		return NULL;
 	}
 	
 	sc->sc_dev = parent->sc_dev;
 	sc->sc_bst = &armv7_generic_bs_tag;
 	sc->sc_bsh = parent->sc_bsh;
-	
+	sc->sc_bank = bank;
+
 	gc_tag = &bank->bank_gc;
 	gc_tag->gp_cookie = bank;
 	gc_tag->gp_pin_read  = exynos_gpio_pin_read;
@@ -327,14 +331,23 @@ exynos_gpio_bank_config(struct exynos_pi
 
 	fdtbus_register_gpio_controller(bank->bank_dev, node,
 					&exynos_gpio_funcs);
+	return sc;
 }
 
-static struct exynos_gpio_bank *
+/*
+ * This function is a bit funky.  Given a string that may look like
+ * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before
+ * the '-', or the four character string if the dash is not present.
+ */
+struct exynos_gpio_bank *
 exynos_gpio_bank_lookup(const char *name)
 {
+	struct exynos_gpio_bank *bank;
+
 	for (u_int n = 0; n < __arraycount(exynos5_banks); n++) {
-		struct exynos_gpio_bank *bank = &exynos_gpio_banks[n];
-		if (strncmp(bank->bank_name, name, strlen(name)) == 0) {
+		bank = &exynos_gpio_banks[n];
+		if (!strncmp(bank->bank_name, name,
+			     strlen(bank->bank_name))) {
 			return bank;
 		}
 	}

Index: src/sys/arch/arm/samsung/exynos_i2c.c
diff -u src/sys/arch/arm/samsung/exynos_i2c.c:1.8 src/sys/arch/arm/samsung/exynos_i2c.c:1.9
--- src/sys/arch/arm/samsung/exynos_i2c.c:1.8	Thu Dec 24 21:30:05 2015
+++ src/sys/arch/arm/samsung/exynos_i2c.c	Wed Dec 30 04:30:27 2015
@@ -1,12 +1,9 @@
-/*	$NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $ */
+/*	$NetBSD: exynos_i2c.c,v 1.9 2015/12/30 04:30:27 marty Exp $ */
 
 /*
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
  * All rights reserved.
  *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Reinoud Zandijk.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -34,16 +31,18 @@
 #include "opt_arm_debug.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.8 2015/12/24 21:30:05 marty Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exynos_i2c.c,v 1.9 2015/12/30 04:30:27 marty 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/kmem.h>
 
 #include <arm/samsung/exynos_reg.h>
+#include <arm/samsung/exynos_var.h>
 #include <arm/samsung/exynos_intr.h>
 
 #include <sys/gpio.h>
@@ -59,19 +58,18 @@ struct exynos_i2c_softc {
 	bus_space_tag_t		sc_bst;
 	bus_space_handle_t	sc_bsh;
 	void *			sc_ih;
-	u_int			sc_port;
+	struct clk *		sc_clk;
 
-	struct fdtbus_gpio_pin  *sc_sda;
-	struct fdtbus_gpio_pin  *sc_scl;
+	struct fdtbus_pinctrl_pin  *sc_sda;
+	struct fdtbus_pinctrl_pin  *sc_scl;
 	bool			sc_sda_is_output;
+
 	struct i2c_controller 	sc_ic;
 	kmutex_t		sc_lock;
 	kcondvar_t		sc_cv;
 	device_t		sc_i2cdev;
 };
 
-static u_int i2c_port;
-
 static int	exynos_i2c_intr(void *);
 
 static int	exynos_i2c_acquire_bus(void *, int);
@@ -83,22 +81,46 @@ static int	exynos_i2c_initiate_xfer(void
 static int	exynos_i2c_read_byte(void *, uint8_t *, int);
 static int	exynos_i2c_write_byte(void *, uint8_t , int);
 
-static bool exynos_i2c_attach_i2cbus(struct exynos_i2c_softc *,
-				     struct i2c_controller *);
+static int	exynos_i2c_wait(struct exynos_i2c_softc *, int);
+
 
 static int exynos_i2c_match(device_t, cfdata_t, void *);
 static void exynos_i2c_attach(device_t, device_t, void *);
 
+static i2c_tag_t exynos_i2c_get_tag(device_t);
+
+struct fdtbus_i2c_controller_func exynos_i2c_funcs = {
+	.get_tag = exynos_i2c_get_tag
+};
+
 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))
+    bus_space_write_1((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
 #define I2C_READ(sc, reg) \
-    bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+    bus_space_read_1((sc)->sc_bst, (sc)->sc_bsh, (reg))
 
-#define IICON 0
-#define IRQPEND (1<<4)
+#define IICCON  0x00
+#define IICSTAT 0x04
+#define IICADD  0x08
+#define IICDS   0x0C
+
+#define ACKENABLE  (1<<7)
+#define TXPRESCALE (1<<6)
+#define INTENABLE  (1<<5)
+#define IRQPEND    (1<<4)
+#define PRESCALE   (0x0f)
+
+#define MODESELECT  (3<<6)
+#define BUSYSTART   (1<<5)
+#define BUSENABLE   (1<<4)
+#define ARBITRATION (1<<3)
+#define SLAVESTATUS (1<<2)
+#define ZEROSTATUS  (1<<1)
+#define LASTBIT     (1<<0)
+
+#define READBIT     (1<<7)
 
 static int
 exynos_i2c_match(device_t self, cfdata_t cf, void *aux)
@@ -126,7 +148,7 @@ exynos_i2c_attach(device_t parent, devic
 	int i2c_handle;
 	int len;
 	int handle;
-	int func /*, pud, drv */;
+	int func, pud, drv;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
 		aprint_error(": couldn't get registers\n");
@@ -143,7 +165,6 @@ exynos_i2c_attach(device_t parent, devic
 		return;
 	}
 
-	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\n", (uint)addr);
@@ -184,11 +205,18 @@ exynos_i2c_attach(device_t parent, devic
 	} else
 		func = be32toh(handle);
 
-	sc->sc_sda = fdtbus_gpio_acquire(phandle, &result[0], func);
-	sc->sc_scl = fdtbus_gpio_acquire(phandle, &result[7], func);
+	sc->sc_sda = fdtbus_pinctrl_acquire(phandle, &result[0]);
+	if (sc->sc_sda == NULL) {
+		printf("could not acquire sda gpio %s\n", &result[0]);
+		return;
+	}
+	
+	sc->sc_scl = fdtbus_pinctrl_acquire(phandle, &result[7]);
+	if (sc->sc_scl == NULL) {
+		printf("could not acquire scl gpio %s\n", &result[7]);
+		return;
+	}
 
-	/* MJF: Need fdtbus_gpio_configure */
-#if 0
 	len = OF_getprop(i2c_handle, "samsung,pin-pud", &handle,
 			 sizeof(&handle));
 	if (len <= 0) {
@@ -205,100 +233,47 @@ exynos_i2c_attach(device_t parent, devic
 	} else
 		drv = be32toh(handle);
 
-#endif
-	if (!exynos_i2c_attach_i2cbus(sc, &sc->sc_ic))
-		return;
+	struct exynos_gpio_pin_cfg cfg;
+	cfg.cfg = func;
+	cfg.pud = pud;
+	cfg.drv = drv;
+	cfg.conpwd = 0;
+	cfg.pudpwd = 0;
+
+	fdtbus_pinctrl_set_cfg(sc->sc_scl, &cfg);
+	fdtbus_pinctrl_set_cfg(sc->sc_sda, &cfg);
+
+	sc->sc_ic.ic_cookie = sc;
+	sc->sc_ic.ic_acquire_bus = exynos_i2c_acquire_bus;
+	sc->sc_ic.ic_release_bus = exynos_i2c_release_bus;
+	sc->sc_ic.ic_send_start  = exynos_i2c_send_start;
+	sc->sc_ic.ic_send_stop   = exynos_i2c_send_stop;
+	sc->sc_ic.ic_initiate_xfer = exynos_i2c_initiate_xfer;
+	sc->sc_ic.ic_read_byte   = exynos_i2c_read_byte;
+	sc->sc_ic.ic_write_byte  = exynos_i2c_write_byte;
 
 	sc->sc_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print);
 
 }
 
-static bool
-exynos_i2c_attach_i2cbus(struct exynos_i2c_softc *i2c_sc,
-			 struct i2c_controller *i2c_cntr)
-{
-	i2c_cntr->ic_cookie = i2c_sc;
-	i2c_cntr->ic_acquire_bus = exynos_i2c_acquire_bus;
-	i2c_cntr->ic_release_bus = exynos_i2c_release_bus;
-	i2c_cntr->ic_send_start  = exynos_i2c_send_start;
-	i2c_cntr->ic_send_stop   = exynos_i2c_send_stop;
-	i2c_cntr->ic_initiate_xfer = exynos_i2c_initiate_xfer;
-	i2c_cntr->ic_read_byte   = exynos_i2c_read_byte;
-	i2c_cntr->ic_write_byte  = exynos_i2c_write_byte;
-
-	return 1;
-}
-
-#define EXYNOS_I2C_BB_SDA	__BIT(1)
-#define EXYNOS_I2C_BB_SCL	__BIT(2)
-#define EXYNOS_I2C_BB_SDA_OUT	__BIT(3)
-#define EXYNOS_I2C_BB_SDA_IN	0
-
-static void
-exynos_i2c_bb_set_bits(void *cookie, uint32_t bits)
-{
-	struct exynos_i2c_softc *i2c_sc = cookie;
-	int sda, scl;
-
-	sda = (bits & EXYNOS_I2C_BB_SDA) ? 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_scl, scl);
-}
-
-static uint32_t
-exynos_i2c_bb_read_bits(void *cookie)
+static i2c_tag_t
+exynos_i2c_get_tag(device_t dev)
 {
-	struct exynos_i2c_softc *i2c_sc = cookie;
-	int sda, scl;
-
-	sda = 0;
-	if (!i2c_sc->sc_sda_is_output)
-		sda = fdtbus_gpio_read(i2c_sc->sc_sda);
-	scl = fdtbus_gpio_read(i2c_sc->sc_scl);
+	struct exynos_i2c_softc * const sc = device_private(dev);
 
-	return (sda ? EXYNOS_I2C_BB_SDA : 0) | (scl ? EXYNOS_I2C_BB_SCL : 0);
+	return &sc->sc_ic;
 }
 
-static void
-exynos_i2c_bb_set_dir(void *cookie, uint32_t bits)
-{
-	struct exynos_i2c_softc *i2c_sc = cookie;
-	int flags;
-
-	flags = GPIO_PIN_INPUT | GPIO_PIN_TRISTATE;
-	i2c_sc->sc_sda_is_output = ((bits & EXYNOS_I2C_BB_SDA_OUT) != 0);
-	if (i2c_sc->sc_sda_is_output)
-		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);
-}
-
-static const struct i2c_bitbang_ops exynos_i2c_bbops = {
-	exynos_i2c_bb_set_bits,
-	exynos_i2c_bb_set_dir,
-	exynos_i2c_bb_read_bits,
-	{
-		EXYNOS_I2C_BB_SDA,
-		EXYNOS_I2C_BB_SCL,
-		EXYNOS_I2C_BB_SDA_OUT,
-		EXYNOS_I2C_BB_SDA_IN,
-	}
-};
-
 static int
 exynos_i2c_intr(void *priv)
 {
 	struct exynos_i2c_softc * const sc = priv;
 
-	uint32_t istatus = I2C_READ(sc, IICON);
+	uint8_t istatus = I2C_READ(sc, IICCON);
 	if (!(istatus & IRQPEND))
 		return 0;
 	istatus &= ~IRQPEND;
-	I2C_WRITE(sc, IICON, istatus);
+	I2C_WRITE(sc, IICCON, istatus);
 
 	mutex_enter(&sc->sc_lock);
 	cv_broadcast(&sc->sc_cv);
@@ -312,9 +287,6 @@ exynos_i2c_acquire_bus(void *cookie, int
 {
 	struct exynos_i2c_softc *i2c_sc = cookie;
 
-	/* XXX what to do in polling case? could another cpu help */
-	if (flags & I2C_F_POLL)
-		return 0;
 	mutex_enter(&i2c_sc->sc_lock);
 	return 0;
 }
@@ -324,41 +296,94 @@ exynos_i2c_release_bus(void *cookie, int
 {
 	struct exynos_i2c_softc *i2c_sc = cookie;
 
-	/* XXX what to do in polling case? could another cpu help */
-	if (flags & I2C_F_POLL)
-		return;
 	mutex_exit(&i2c_sc->sc_lock);
 }
 
 static int
+exynos_i2c_wait(struct exynos_i2c_softc *sc, int flags)
+{
+	int error, retry;
+	uint8_t stat = 0;
+
+	retry = (flags & I2C_F_POLL) ? 100000 : 100;
+
+	while (--retry > 0) {
+		if ((flags & I2C_F_POLL) == 0) {
+			error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock,
+			    max(mstohz(10), 1));
+			if (error) {
+				return error;
+			}
+		}
+		stat = I2C_READ(sc, IICSTAT);
+		if (!(stat & BUSYSTART)) {
+			break;
+		}
+		if (flags & I2C_F_POLL) {
+			delay(10);
+		}
+	}
+	if (retry == 0) {
+		stat = I2C_READ(sc, IICSTAT);
+		device_printf(sc->sc_dev, "timed out, status = %#x\n", stat);
+		return ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+
+static int
 exynos_i2c_send_start(void *cookie, int flags)
 {
-	return i2c_bitbang_send_start(cookie, flags, &exynos_i2c_bbops);
+	struct exynos_i2c_softc *sc = cookie;
+	I2C_WRITE(sc, IICSTAT, 0xF0);
+	return 0;
 }
 
 static int
 exynos_i2c_send_stop(void *cookie, int flags)
 {
-	return i2c_bitbang_send_stop(cookie, flags, &exynos_i2c_bbops);
+	struct exynos_i2c_softc *sc = cookie;
+	I2C_WRITE(sc, IICSTAT, 0xD0);
+	return 0;
 }
 
 static int
 exynos_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
 {
-	return i2c_bitbang_initiate_xfer(cookie, addr, flags,
-					 &exynos_i2c_bbops);
+	struct exynos_i2c_softc *sc = cookie;
+	uint8_t byte = addr & 0x7f;
+	if (flags & I2C_F_READ)
+		byte |= READBIT;
+	else
+		byte &= ~READBIT;
+	I2C_WRITE(sc, IICADD, addr);
+	exynos_i2c_send_start(cookie, flags);
+	exynos_i2c_write_byte(cookie, byte, flags);
+	return exynos_i2c_wait(cookie, flags);
 }
 
 static int
 exynos_i2c_read_byte(void *cookie, uint8_t *bytep, int flags)
 {
-	return i2c_bitbang_read_byte(cookie, bytep, flags,
-				     &exynos_i2c_bbops);
+	struct exynos_i2c_softc *sc = cookie;
+	int error = exynos_i2c_wait(sc, flags);
+	if (error)
+		return error;
+	*bytep = I2C_READ(sc, IICDS) & 0xff;
+	if (flags & I2C_F_STOP)
+		exynos_i2c_send_stop(cookie, flags);
+	return 0;
 }
 
 static int
 exynos_i2c_write_byte(void *cookie, uint8_t byte, int flags)
 {
-	return i2c_bitbang_write_byte(cookie, byte, flags,
-				      &exynos_i2c_bbops);
+	struct exynos_i2c_softc *sc = cookie;
+	int error = exynos_i2c_wait(sc, flags);
+	if (error)
+		return error;
+	I2C_WRITE(sc, IICDS, byte);
+	return 0;
 }

Index: src/sys/arch/arm/samsung/exynos_pinctrl.c
diff -u src/sys/arch/arm/samsung/exynos_pinctrl.c:1.7 src/sys/arch/arm/samsung/exynos_pinctrl.c:1.8
--- src/sys/arch/arm/samsung/exynos_pinctrl.c:1.7	Sun Dec 27 12:21:37 2015
+++ src/sys/arch/arm/samsung/exynos_pinctrl.c	Wed Dec 30 04:30:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_pinctrl.c,v 1.7 2015/12/27 12:21:37 jmcneill Exp $ */
+/*	$NetBSD: exynos_pinctrl.c,v 1.8 2015/12/30 04:30:27 marty Exp $ */
 
 /*-
 * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.7 2015/12/27 12:21:37 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.8 2015/12/30 04:30:27 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -56,6 +56,18 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_pinct
 static int exynos_pinctrl_match(device_t, cfdata_t, void *);
 static void exynos_pinctrl_attach(device_t, device_t, void *);
 
+static void *exynos_pinctrl_acquire(device_t, const char *);
+static void  exynos_pinctrl_release(device_t, void *);
+static void  exynos_pinctrl_get_cfg(struct fdtbus_pinctrl_pin *, void *);
+static void  exynos_pinctrl_set_cfg(struct fdtbus_pinctrl_pin *, void *);
+
+static struct fdtbus_pinctrl_controller_func exynos_pinctrl_controller_func = {
+	.acquire = exynos_pinctrl_acquire,
+	.release = exynos_pinctrl_release,
+	.get     = exynos_pinctrl_get_cfg,
+	.set     = exynos_pinctrl_set_cfg,
+};
+
 CFATTACH_DECL_NEW(exynos_pinctrl, sizeof(struct exynos_pinctrl_softc),
 	exynos_pinctrl_match, exynos_pinctrl_attach, NULL, NULL);
 
@@ -74,6 +86,7 @@ exynos_pinctrl_attach(device_t parent, d
 	struct exynos_pinctrl_softc * const sc
 		= kmem_zalloc(sizeof(*sc), KM_SLEEP);
 	struct fdt_attach_args * const faa = aux;
+	struct exynos_gpio_softc *child_sc;
 	bus_addr_t addr;
 	bus_size_t size;
 	int error;
@@ -101,6 +114,41 @@ exynos_pinctrl_attach(device_t parent, d
 	     child = OF_peer(child)) {
 		if (of_getprop_bool(child, "gpio-controller") == false)
 			continue;
-		exynos_gpio_bank_config(sc, faa, child);
+		child_sc = exynos_gpio_bank_config(sc, faa, child);
+		fdtbus_register_pinctrl_controller(child_sc->sc_dev, child,
+					    &exynos_pinctrl_controller_func);
 	}
 }
+
+
+static void *exynos_pinctrl_acquire(device_t self, const char *name)
+{
+	return exynos_gpio_bank_lookup(name);
+}
+
+static void exynos_pinctrl_release(device_t self, void *cookie)
+{
+}
+
+static void exynos_pinctrl_get_cfg(struct fdtbus_pinctrl_pin *pin,
+				   void *cookie)
+{
+	struct exynos_gpio_bank *bank = pin->pp_priv;
+	struct exynos_gpio_pin_cfg *cfg  = cookie;
+	struct exynos_gpio_pin_cfg **cfgp = &cfg;
+	struct exynos_gpio_pin_cfg *newcfg = kmem_zalloc(sizeof(*newcfg),
+							 KM_SLEEP);
+	if (newcfg == NULL)
+		return;
+	exynos_gpio_pin_ctl_read(bank, newcfg);
+	*cfgp = newcfg;
+	return;
+}
+
+static void exynos_pinctrl_set_cfg(struct fdtbus_pinctrl_pin *pin,
+				   void *cookie)
+{
+	struct exynos_gpio_bank *bank = pin->pp_priv;
+	struct exynos_gpio_pin_cfg *cfg = cookie;
+	exynos_gpio_pin_ctl_write(bank, cfg);
+}

Index: src/sys/arch/arm/samsung/exynos_var.h
diff -u src/sys/arch/arm/samsung/exynos_var.h:1.22 src/sys/arch/arm/samsung/exynos_var.h:1.23
--- src/sys/arch/arm/samsung/exynos_var.h:1.22	Thu Dec 24 01:10:51 2015
+++ src/sys/arch/arm/samsung/exynos_var.h	Wed Dec 30 04:30:27 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_var.h,v 1.22 2015/12/24 01:10:51 marty Exp $	*/
+/*	$NetBSD: exynos_var.h,v 1.23 2015/12/30 04:30:27 marty Exp $	*/
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -104,6 +104,21 @@ struct exynos_gpio_pindata {
 	int pd_pin;
 };
 
+struct exynos_gpio_pin_cfg {
+	uint32_t cfg;
+	uint32_t pud;
+	uint32_t drv;
+	uint32_t conpwd;
+	uint32_t pudpwd;
+};
+
+struct exynos_gpio_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+	struct exynos_gpio_bank *sc_bank;
+	int			sc_phandle;
+};
 
 #define EXYNOS_MAX_IIC_BUSSES 9
 struct i2c_controller;
@@ -127,8 +142,10 @@ extern void exynos_bootstrap(vaddr_t, va
 extern void exynos_dma_bootstrap(psize_t memsize);
 
 struct exynos_pinctrl_softc;
+struct exynos_gpio_softc;
 struct fdt_attach_args;
-extern void exynos_gpio_bank_config(struct exynos_pinctrl_softc *,
+
+extern struct exynos_gpio_softc * exynos_gpio_bank_config(struct exynos_pinctrl_softc *,
 				    const struct fdt_attach_args *, int);
 extern void exynos_wdt_reset(void);
 
@@ -146,13 +163,17 @@ extern void exynos_usb_soc_powerup(void)
 extern void exyo_device_register(device_t self, void *aux);
 extern void exyo_device_register_post_config(device_t self, void *aux);
 
+extern struct exynos_gpio_bank *exynos_gpio_bank_lookup(const char *name);
 extern bool exynos_gpio_pinset_available(const struct exynos_gpio_pinset *);
 extern void exynos_gpio_pinset_acquire(const struct exynos_gpio_pinset *);
 extern void exynos_gpio_pinset_release(const struct exynos_gpio_pinset *);
 extern void exynos_gpio_pinset_to_pindata(const struct exynos_gpio_pinset *,
 	int pinnr, struct exynos_gpio_pindata *);
 extern bool exynos_gpio_pin_reserve(const char *, struct exynos_gpio_pindata *);
-
+extern void exynos_gpio_pin_ctl_read(const struct exynos_gpio_bank *,
+				     struct exynos_gpio_pin_cfg *);
+extern void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *,
+				      const struct exynos_gpio_pin_cfg *);
 static inline void
 exynos_gpio_pindata_write(const struct exynos_gpio_pindata *pd, int value)
 {

Reply via email to