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