Keyboard drivers, polling vs. non-polling mode

Maxim Ignatenko gelraen.ua at gmail.com
Tue May 13 21:26:36 UTC 2014


On 13 May 2014 11:17, Maxim Ignatenko <gelraen.ua at gmail.com> wrote:
> On 13 May 2014 09:40, Ruslan Bukin <br at bsdpad.com> wrote:
>> On Sun, May 11, 2014 at 11:33:42PM +0100, Maxim Ignatenko wrote:
>>> Hello,
>>>
>>> I'm trying trying to get keyboard working in DDB on HP Chromebook 11 (ARM).
>>> br@ said that it doesn't work there because polling mode is not implemented yet.
>>> Where can I read about the difference between polling and non-polling
>>> modes (and about keyboard drivers in general)?
>>> sys/dev/kbd/kbdreg.h describes some structures and method signatures,
>>> but I have no clue what is the expected behaviour of those methods.
>>>
>>> My current guess is that in polling mode keyboard driver just queues
>>> up all the input coming from keyboard and then gives it to consumer
>>> upon request, while in non-polling mode it invokes some callback
>>> instead of queueing. But I cannot find any documentation to confirm or
>>> disprove that.
>>>
>>
>> Chrome Embedded Controller (EC) provides interrupt (KB_GPIO_INT pin, active low)
>> reporting that there are pending data and you need to read the data using
>> ec_command(..). After all data was read, pin comes to 1 (not active).
>>
>> We have no interrupts in KDB, so you have to check pin status manually and
>> if status == 0 (active) then read new data.
>>
>> Probably you can start with patch attached (I did't tested).
>
> Thanks, I've tried something like that, except with invoking
> ec_command immediately and comparing returned state to previous one
> rather than reading status bit from GPIO pin.
> I keep getting "fdb0: i2c transfer returned 6" and none of the printfs
> I've added to iicbus_transfer_gen in sys/dev/iicbus/iiconf.c.

Here's what I have now. After booting kernel from flash drive I get
kdb prompt (because of panic() call in exynos5_ehci.c) and when I
press any key - screen gets spammed with "fdb0: i2c transfer returned
6". printfs added to dev/iicbus/*.c are not triggered. Any ideas?

-- 
Best regards,
Maxim
-------------- next part --------------
Index: arm/samsung/exynos/chrome_kb.c
===================================================================
--- arm/samsung/exynos/chrome_kb.c	(revision 265915)
+++ arm/samsung/exynos/chrome_kb.c	(working copy)
@@ -131,6 +131,7 @@
 	int			rows;
 	int			cols;
 	device_t		dev;
+	device_t		gpio_dev;
 	struct thread		*sc_poll_thread;
 
 	uint8_t			*scan_local;
@@ -331,6 +332,7 @@
 	uint16_t key;
 	int oldbit;
 	int newbit;
+	int status;
 
 	sc = kbd->kb_data;
 
@@ -347,7 +349,20 @@
 	};
 
 	if (sc->sc_flags & CKB_FLAG_POLLING) {
-		/* TODO */
+		for (;;) {
+			GPIO_PIN_GET(sc->gpio_dev, KB_GPIO_INT, &status);
+			if (status == 0) {
+				if (ec_command(EC_CMD_MKBP_STATE, sc->scan, sc->cols,
+				    sc->scan, sc->cols)) {
+					return (NOKEY);
+				}
+				break;
+			}
+			if (!wait) {
+				return (NOKEY);
+			}
+			DELAY(1000);
+		}
 	};
 
 	for (i = 0; i < sc->cols; i++) {
@@ -710,7 +725,12 @@
 	if ((error = parse_dts(sc)) != 0)
 		return error;
 
-#if 0
+	sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+	if (sc->gpio_dev == NULL) {
+		device_printf(sc->dev, "cant find gpio_dev\n");
+		return (1);
+	}
+#if 1
 	device_printf(sc->dev, "Keyboard matrix [%dx%d]\n",
 	    sc->cols, sc->rows);
 #endif
Index: arm/samsung/exynos/exynos5_ehci.c
===================================================================
--- arm/samsung/exynos/exynos5_ehci.c	(revision 265915)
+++ arm/samsung/exynos/exynos5_ehci.c	(working copy)
@@ -63,6 +63,7 @@
 #define	GPIO_OUTPUT	1
 #define	GPIO_INPUT	0
 #define	PIN_USB		161
+#define PIN_RESET_HUB   181
 
 /* PWR control */
 #define	EXYNOS5_PWR_USBHOST_PHY		0x708
@@ -179,11 +181,23 @@
 	return (0);
 }
 
+static void
+do_panic(void *unused) {
+	panic("paniq requested");
+}
+
 static int
 phy_init(struct exynos_ehci_softc *esc)
 {
 	int reg;
+	device_t gpio_dev;
 
+	/* Get the GPIO device, we need this to give power to USB */
+	gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
+	if (gpio_dev == NULL) {
+		device_printf(esc->dev, "cant find gpio_dev\n");
+		return (1);
+	}
 	gpio_ctrl(esc, GPIO_INPUT, 1);
 
 	/* set USB HOST mode */
@@ -200,20 +214,45 @@
 	    HOST_CTRL_RESET_PHY_ALL |
 	    HOST_CTRL_SIDDQ |
 	    HOST_CTRL_SUSPEND |
-	    HOST_CTRL_SLEEP);
+	    HOST_CTRL_SLEEP | (1<<9));
 
 	reg |= (HOST_CTRL_CLK_24MHZ |
-	    HOST_CTRL_RESET_LINK);
+	    HOST_CTRL_RESET_LINK | 0x04);
 	bus_space_write_4(esc->host_bst, esc->host_bsh, 0x0, reg);
 
 	DELAY(10);
 
 	reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x0);
-	reg &= ~(HOST_CTRL_RESET_LINK);
+	reg &= ~(HOST_CTRL_RESET_LINK | 0x04);
 	bus_space_write_4(esc->host_bst, esc->host_bsh, 0x0, reg);
 
+	DELAY(20);
+	reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x30);
+	reg |= (1<<29) | (1<<28) | (1<<27) | (1<<26);
+	bus_space_write_4(esc->host_bst, esc->host_bsh, 0x30, reg);
+
+	if (1) {
+		GPIO_PIN_SETFLAGS(gpio_dev, PIN_RESET_HUB, GPIO_PIN_OUTPUT);
+		GPIO_PIN_SET(gpio_dev, PIN_RESET_HUB, GPIO_PIN_LOW);
+		DELAY(100);
+		GPIO_PIN_SET(gpio_dev, PIN_RESET_HUB, GPIO_PIN_HIGH);
+		DELAY(5000);
+
+		reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x10);
+		reg &= ~(HOST_CTRL_SIDDQ | HOST_CTRL_SUSPEND | HOST_CTRL_SLEEP);
+		reg |= HOST_CTRL_RESET_PHY;
+		bus_space_write_4(esc->host_bst, esc->host_bsh, 0x10, reg);
+		DELAY(10);
+		reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x10);
+		reg &= ~HOST_CTRL_RESET_PHY;
+		bus_space_write_4(esc->host_bst, esc->host_bsh, 0x10, reg);
+	}
+	DELAY(50000);
+
 	gpio_ctrl(esc, GPIO_OUTPUT, 1);
 
+	timeout(do_panic, NULL, 10);
+
 	return (0);
 }
 
Index: arm/samsung/exynos/exynos5_i2c.c
===================================================================
--- arm/samsung/exynos/exynos5_i2c.c	(revision 265915)
+++ arm/samsung/exynos/exynos5_i2c.c	(working copy)
@@ -93,7 +93,7 @@
 #define	 SDAOUT_DELAY_M	0x3		/* SDA Line Delay Length */
 #define	 SDAOUT_DELAY_S	0
 
-#ifdef DEBUG
+#if 1
 #define DPRINTF(fmt, args...) \
 	printf(fmt, ##args)
 #else
Index: dev/iicbus/iicbb.c
===================================================================
--- dev/iicbus/iicbb.c	(revision 265915)
+++ dev/iicbus/iicbb.c	(working copy)
@@ -456,10 +456,15 @@
 	int error;
 
 	error = IICBB_PRE_XFER(device_get_parent(dev));
-	if (error)
+	if (error) {
+		printf("IICBB_PRE_XFER(device_get_parent(dev)) returned %d\n", error);
 		return (error);
+	}
 
 	error = iicbus_transfer_gen(dev, msgs, nmsgs);
+	if (error) {
+		printf("iicbus_transfer_gen returned %d\n", error);
+	}
 
 	IICBB_POST_XFER(device_get_parent(dev));
 	return (error);
Index: dev/iicbus/iiconf.c
===================================================================
--- dev/iicbus/iiconf.c	(revision 265915)
+++ dev/iicbus/iiconf.c	(working copy)
@@ -366,8 +366,11 @@
 	int i, error, lenread, lenwrote, nkid, rpstart, addr;
 	device_t *children, bus;
 
-	if ((error = device_get_children(dev, &children, &nkid)) != 0)
+	device_printf(dev, "iicbus_transfer_gen called\n");
+	if ((error = device_get_children(dev, &children, &nkid)) != 0) {
+		printf("device_get_children returned %d\n", error);
 		return (error);
+	}
 	if (nkid != 1) {
 		free(children, M_TEMP);
 		return (EIO);
@@ -383,21 +386,27 @@
 			addr &= ~LSB;
 
 		if (!(msgs[i].flags & IIC_M_NOSTART)) {
-			if (rpstart)
+			if (rpstart) {
 				error = iicbus_repeated_start(bus, addr, 0);
-			else
+				if (error) { printf("iicbus_repeated_start returned %d\n", error); }
+			} else {
 				error = iicbus_start(bus, addr, 0);
+				if (error) { printf("iicbus_start returned %d\n", error); }
+			}
 		}
 
 		if (error)
 			break;
 
-		if (msgs[i].flags & IIC_M_RD)
+		if (msgs[i].flags & IIC_M_RD) {
 			error = iicbus_read(bus, msgs[i].buf, msgs[i].len,
 			    &lenread, IIC_LAST_READ, 0);
-		else
+			if (error) { printf("iicbus_read returned %d\n", error); }
+		} else {
 			error = iicbus_write(bus, msgs[i].buf, msgs[i].len,
 			    &lenwrote, 0);
+			if (error) { printf("iicbus_write returned %d\n", error); }
+		}
 
 		if (!(msgs[i].flags & IIC_M_NOSTOP)) {
 			rpstart = 0;
@@ -406,5 +415,6 @@
 			rpstart = 1;	/* Next message gets repeated start */
 		}
 	}
+	if (error) {printf("iicbus_transfer_gen returns %d\n", error);}
 	return (error);
 }



More information about the freebsd-hackers mailing list