summaryrefslogtreecommitdiffstats
path: root/sys/arm/samsung
diff options
context:
space:
mode:
authorbr <br@FreeBSD.org>2014-05-30 06:45:50 +0000
committerbr <br@FreeBSD.org>2014-05-30 06:45:50 +0000
commit63848ea4f517025be7c372012b1dea891487328c (patch)
treed45bffec0a2c4fea2d9784e2c8aa17acf8681b8a /sys/arm/samsung
parent42ea4ae3d693701c927755bccb272a71ce4e9d5a (diff)
downloadFreeBSD-src-63848ea4f517025be7c372012b1dea891487328c.zip
FreeBSD-src-63848ea4f517025be7c372012b1dea891487328c.tar.gz
o Make keyboard-related properties to be compatible with vendor standard
o Allow setting keymap in FDT, use hardcoded one by default o Represent fallback keymap as a list rather than directly usable M*N array Submitted by: Maxim Ignatenko <gelraen.ua@gmail.com>
Diffstat (limited to 'sys/arm/samsung')
-rw-r--r--sys/arm/samsung/exynos/chrome_kb.c161
-rw-r--r--sys/arm/samsung/exynos/chrome_kb.h160
2 files changed, 214 insertions, 107 deletions
diff --git a/sys/arm/samsung/exynos/chrome_kb.c b/sys/arm/samsung/exynos/chrome_kb.c
index 4b3d202..d5d55e9 100644
--- a/sys/arm/samsung/exynos/chrome_kb.c
+++ b/sys/arm/samsung/exynos/chrome_kb.c
@@ -105,9 +105,6 @@ __FBSDID("$FreeBSD$");
#define CKB_FLAG_POLLING 0x2
#define KBD_DRIVER_NAME "ckbd"
-/* TODO: take interrupt from DTS */
-#define KB_GPIO_INT 146
-
struct ckb_softc {
keyboard_t sc_kbd;
keymap_t sc_keymap;
@@ -130,9 +127,11 @@ struct ckb_softc {
int flag;
int rows;
int cols;
+ int gpio;
device_t dev;
device_t gpio_dev;
struct thread *sc_poll_thread;
+ uint16_t *keymap;
uint8_t *scan_local;
uint8_t *scan;
@@ -199,7 +198,7 @@ static int
ckb_intr(keyboard_t *kbd, void *arg)
{
- return (0);
+ return (0);
}
/* lock the access to the keyboard, not used */
@@ -207,7 +206,7 @@ static int
ckb_lock(keyboard_t *kbd, int lock)
{
- return (1);
+ return (1);
}
/* clear the internal state of the keyboard */
@@ -309,20 +308,33 @@ ckb_read(keyboard_t *kbd, int wait)
return (0);
}
-int scantokey(int i, int j);
-
-int
-scantokey(int i, int j)
+static uint16_t
+keymap_read(struct ckb_softc *sc, int col, int row)
{
- int k;
- for (k = 0; k < KEYMAP_LEN; k++)
- if ((keymap[k].col == i) && (keymap[k].row == j))
- return (keymap[k].key);
+ KASSERT(sc->keymap != NULL, "keymap_read: no keymap");
+ if (col >= 0 && col < sc->cols &&
+ row >= 0 && row < sc->rows) {
+ return sc->keymap[row * sc->cols + col];
+ }
return (0);
}
+static int
+keymap_write(struct ckb_softc *sc, int col, int row, uint16_t key)
+{
+
+ KASSERT(sc->keymap != NULL, "keymap_write: no keymap");
+ if (col >= 0 && col < sc->cols &&
+ row >= 0 && row < sc->rows) {
+ sc->keymap[row * sc->cols + col] = key;
+ return (0);
+ }
+
+ return (-1);
+}
+
/* read char from the keyboard */
static uint32_t
ckb_read_char_locked(keyboard_t *kbd, int wait)
@@ -350,9 +362,10 @@ ckb_read_char_locked(keyboard_t *kbd, int wait)
if (sc->sc_flags & CKB_FLAG_POLLING) {
for (;;) {
- GPIO_PIN_GET(sc->gpio_dev, KB_GPIO_INT, &status);
+ GPIO_PIN_GET(sc->gpio_dev, sc->gpio, &status);
if (status == 0) {
- if (ec_command(EC_CMD_MKBP_STATE, sc->scan, sc->cols,
+ if (ec_command(EC_CMD_MKBP_STATE, sc->scan,
+ sc->cols,
sc->scan, sc->cols)) {
return (NOKEY);
}
@@ -373,7 +386,7 @@ ckb_read_char_locked(keyboard_t *kbd, int wait)
if (oldbit == newbit)
continue;
- key = scantokey(i,j);
+ key = keymap_read(sc, i, j);
if (key == 0) {
continue;
};
@@ -666,27 +679,109 @@ dummy_kbd_configure(int flags)
KEYBOARD_DRIVER(ckbd, ckbdsw, dummy_kbd_configure);
+/*
+ * Parses 'keymap' into sc->keymap.
+ * Requires sc->cols and sc->rows to be set.
+ */
+static int
+parse_keymap(struct ckb_softc *sc, pcell_t *keymap, size_t len)
+{
+ int i;
+
+ sc->keymap = malloc(sc->cols * sc->rows * sizeof(sc->keymap[0]),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (sc->keymap == NULL) {
+ return (ENOMEM);
+ }
+
+ for (i = 0; i < len; i++) {
+ /*
+ * Return value is ignored, we just write whatever fits into
+ * specified number of rows and columns and silently ignore
+ * everything else.
+ * Keymap entries follow this format: 0xRRCCKKKK
+ * RR - row number, CC - column number, KKKK - key code
+ */
+ keymap_write(sc, (keymap[i] >> 16) & 0xff,
+ (keymap[i] >> 24) & 0xff,
+ keymap[i] & 0xffff);
+ }
+
+ return (0);
+}
+
+/* Allocates a new array for keymap and returns it in 'keymap'. */
+static int
+read_keymap(phandle_t node, const char *prop, pcell_t **keymap, size_t *len)
+{
+
+ if ((*len = OF_getproplen(node, prop)) <= 0) {
+ return (ENXIO);
+ }
+ if ((*keymap = malloc(*len, M_DEVBUF, M_NOWAIT)) == NULL) {
+ return (ENOMEM);
+ }
+ if (OF_getencprop(node, prop, *keymap, *len) != *len) {
+ return (ENXIO);
+ }
+ return (0);
+}
+
static int
parse_dts(struct ckb_softc *sc)
{
phandle_t node;
pcell_t dts_value;
- int len;
+ pcell_t *keymap;
+ int len, ret;
+ const char *keymap_prop = NULL;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
- if ((len = OF_getproplen(node, "keypad,num-rows")) <= 0)
+ if ((len = OF_getproplen(node, "google,key-rows")) <= 0)
return (ENXIO);
- OF_getprop(node, "keypad,num-rows", &dts_value, len);
+ OF_getprop(node, "google,key-rows", &dts_value, len);
sc->rows = fdt32_to_cpu(dts_value);
- if ((len = OF_getproplen(node, "keypad,num-columns")) <= 0)
+ if ((len = OF_getproplen(node, "google,key-columns")) <= 0)
return (ENXIO);
- OF_getprop(node, "keypad,num-columns", &dts_value, len);
+ OF_getprop(node, "google,key-columns", &dts_value, len);
sc->cols = fdt32_to_cpu(dts_value);
- if ((sc->rows == 0) || (sc->cols == 0))
+ if ((len = OF_getproplen(node, "freebsd,intr-gpio")) <= 0)
+ return (ENXIO);
+ OF_getprop(node, "freebsd,intr-gpio", &dts_value, len);
+ sc->gpio = fdt32_to_cpu(dts_value);
+
+ if (OF_hasprop(node, "freebsd,keymap")) {
+ keymap_prop = "freebsd,keymap";
+ device_printf(sc->dev, "using FreeBSD-specific keymap from FDT\n");
+ } else if (OF_hasprop(node, "linux,keymap")) {
+ keymap_prop = "linux,keymap";
+ device_printf(sc->dev, "using Linux keymap from FDT\n");
+ } else {
+ device_printf(sc->dev, "using built-in keymap\n");
+ }
+
+ if (keymap_prop != NULL) {
+ if ((ret = read_keymap(node, keymap_prop, &keymap, &len))) {
+ device_printf(sc->dev,
+ "failed to read keymap from FDT: %d\n", ret);
+ return (ret);
+ }
+ ret = parse_keymap(sc, keymap, len);
+ free(keymap, M_DEVBUF);
+ if (ret) {
+ return (ret);
+ }
+ } else {
+ if ((ret = parse_keymap(sc, default_keymap, KEYMAP_LEN))) {
+ return (ret);
+ }
+ }
+
+ if ((sc->rows == 0) || (sc->cols == 0) || (sc->gpio == 0))
return (ENXIO);
return (0);
@@ -721,6 +816,7 @@ chrome_kb_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
+ sc->keymap = NULL;
if ((error = parse_dts(sc)) != 0)
return error;
@@ -736,8 +832,7 @@ chrome_kb_attach(device_t dev)
sc->cols, sc->rows);
#endif
- /* TODO: take interrupt from DTS */
- pad_setup_intr(KB_GPIO_INT, ckb_ec_intr, sc);
+ pad_setup_intr(sc->gpio, ckb_ec_intr, sc);
kbd = &sc->sc_kbd;
rid = 0;
@@ -786,7 +881,8 @@ chrome_kb_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb")) {
+ if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb") ||
+ ofw_bus_is_compatible(dev, "google,mkbp-keyb")) {
device_set_desc(dev, "Chrome EC Keyboard");
return (BUS_PROBE_DEFAULT);
}
@@ -794,9 +890,24 @@ chrome_kb_probe(device_t dev)
return (ENXIO);
}
+static int
+chrome_kb_detach(device_t dev)
+{
+ struct ckb_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->keymap != NULL) {
+ free(sc->keymap, M_DEVBUF);
+ }
+
+ return 0;
+}
+
static device_method_t chrome_kb_methods[] = {
DEVMETHOD(device_probe, chrome_kb_probe),
DEVMETHOD(device_attach, chrome_kb_attach),
+ DEVMETHOD(device_detach, chrome_kb_detach),
{ 0, 0 }
};
diff --git a/sys/arm/samsung/exynos/chrome_kb.h b/sys/arm/samsung/exynos/chrome_kb.h
index 3903a9b..6ff0386 100644
--- a/sys/arm/samsung/exynos/chrome_kb.h
+++ b/sys/arm/samsung/exynos/chrome_kb.h
@@ -26,97 +26,93 @@
* $FreeBSD$
*/
-void ckb_ec_intr(void *);
+#include <dev/ofw/openfirm.h>
-struct key {
- uint8_t row;
- uint8_t col;
- uint8_t key;
-};
+void ckb_ec_intr(void *);
#define KEYMAP_LEN 75
-struct key keymap[KEYMAP_LEN] = {
- { 0x00, 0x01, 0x7d }, /* lmeta */
- { 0x00, 0x02, 0x3b }, /* F1 */
- { 0x00, 0x03, 0x30 }, /* B */
- { 0x00, 0x04, 0x44 }, /* F10 */
- { 0x00, 0x06, 0x31 }, /* N */
- { 0x00, 0x08, 0x0d }, /* = */
- { 0x00, 0x0a, 0x64 }, /* ralt */
+pcell_t default_keymap[KEYMAP_LEN] = {
+ 0x0001007d, /* lmeta */
+ 0x0002003b, /* F1 */
+ 0x00030030, /* B */
+ 0x00040044, /* F10 */
+ 0x00060031, /* N */
+ 0x0008000d, /* = */
+ 0x000a0064, /* ralt */
- { 0x01, 0x01, 0x01 }, /* escape */
- { 0x01, 0x02, 0x3e }, /* F4 */
- { 0x01, 0x03, 0x22 }, /* G */
- { 0x01, 0x04, 0x41 }, /* F7 */
- { 0x01, 0x06, 0x23 }, /* H */
- { 0x01, 0x08, 0x28 }, /* ' */
- { 0x01, 0x09, 0x43 }, /* F9 */
- { 0x01, 0x0b, 0x0e }, /* backspace */
+ 0x01010001, /* escape */
+ 0x0102003e, /* F4 */
+ 0x01030022, /* G */
+ 0x01040041, /* F7 */
+ 0x01060023, /* H */
+ 0x01080028, /* ' */
+ 0x01090043, /* F9 */
+ 0x010b000e, /* backspace */
- { 0x02, 0x00, 0x1d }, /* lctrl */
- { 0x02, 0x01, 0x0f }, /* tab */
- { 0x02, 0x02, 0x3d }, /* F3 */
- { 0x02, 0x03, 0x14 }, /* t */
- { 0x02, 0x04, 0x40 }, /* F6 */
- { 0x02, 0x05, 0x1b }, /* ] */
- { 0x02, 0x06, 0x15 }, /* y */
- { 0x02, 0x07, 0x56 }, /* 102nd */
- { 0x02, 0x08, 0x1a }, /* [ */
- { 0x02, 0x09, 0x42 }, /* F8 */
+ 0x0200001d, /* lctrl */
+ 0x0201000f, /* tab */
+ 0x0202003d, /* F3 */
+ 0x02030014, /* t */
+ 0x02040040, /* F6 */
+ 0x0205001b, /* ] */
+ 0x02060015, /* y */
+ 0x02070056, /* 102nd */
+ 0x0208001a, /* [ */
+ 0x02090042, /* F8 */
- { 0x03, 0x01, 0x29 }, /* grave */
- { 0x03, 0x02, 0x3c }, /* F2 */
- { 0x03, 0x03, 0x06 }, /* 5 */
- { 0x03, 0x04, 0x3f }, /* F5 */
- { 0x03, 0x06, 0x07 }, /* 6 */
- { 0x03, 0x08, 0x0c }, /* - */
- { 0x03, 0x0b, 0x2b }, /* \ */
+ 0x03010029, /* grave */
+ 0x0302003c, /* F2 */
+ 0x03030006, /* 5 */
+ 0x0304003f, /* F5 */
+ 0x03060007, /* 6 */
+ 0x0308000c, /* - */
+ 0x030b002b, /* \ */
- { 0x04, 0x00, 0x61 }, /* rctrl */
- { 0x04, 0x01, 0x1e }, /* a */
- { 0x04, 0x02, 0x20 }, /* d */
- { 0x04, 0x03, 0x21 }, /* f */
- { 0x04, 0x04, 0x1f }, /* s */
- { 0x04, 0x05, 0x25 }, /* k */
- { 0x04, 0x06, 0x24 }, /* j */
- { 0x04, 0x08, 0x27 }, /* ; */
- { 0x04, 0x09, 0x26 }, /* l */
- { 0x04, 0x0a, 0x2b }, /* \ */
- { 0x04, 0x0b, 0x1c }, /* enter */
+ 0x04000061, /* rctrl */
+ 0x0401001e, /* a */
+ 0x04020020, /* d */
+ 0x04030021, /* f */
+ 0x0404001f, /* s */
+ 0x04050025, /* k */
+ 0x04060024, /* j */
+ 0x04080027, /* ; */
+ 0x04090026, /* l */
+ 0x040a002b, /* \ */
+ 0x040b001c, /* enter */
- { 0x05, 0x01, 0x2c }, /* z */
- { 0x05, 0x02, 0x2e }, /* c */
- { 0x05, 0x03, 0x2f }, /* v */
- { 0x05, 0x04, 0x2d }, /* x */
- { 0x05, 0x05, 0x33 }, /* , */
- { 0x05, 0x06, 0x32 }, /* m */
- { 0x05, 0x07, 0x2a }, /* lsh */
- { 0x05, 0x08, 0x35 }, /* / */
- { 0x05, 0x09, 0x34 }, /* . */
- { 0x05, 0x0B, 0x39 }, /* space */
+ 0x0501002c, /* z */
+ 0x0502002e, /* c */
+ 0x0503002f, /* v */
+ 0x0504002d, /* x */
+ 0x05050033, /* , */
+ 0x05060032, /* m */
+ 0x0507002a, /* lsh */
+ 0x05080035, /* / */
+ 0x05090034, /* . */
+ 0x050B0039, /* space */
- { 0x06, 0x01, 0x02 }, /* 1 */
- { 0x06, 0x02, 0x04 }, /* 3 */
- { 0x06, 0x03, 0x05 }, /* 4 */
- { 0x06, 0x04, 0x03 }, /* 2 */
- { 0x06, 0x05, 0x09 }, /* 8 */
- { 0x06, 0x06, 0x08 }, /* 7 */
- { 0x06, 0x08, 0x0b }, /* 0 */
- { 0x06, 0x09, 0x0a }, /* 9 */
- { 0x06, 0x0a, 0x38 }, /* lalt */
- { 0x06, 0x0b, 0x64 }, /* down */
- { 0x06, 0x0c, 0x62 }, /* right */
+ 0x06010002, /* 1 */
+ 0x06020004, /* 3 */
+ 0x06030005, /* 4 */
+ 0x06040003, /* 2 */
+ 0x06050009, /* 8 */
+ 0x06060008, /* 7 */
+ 0x0608000b, /* 0 */
+ 0x0609000a, /* 9 */
+ 0x060a0038, /* lalt */
+ 0x060b0064, /* down */
+ 0x060c0062, /* right */
- { 0x07, 0x01, 0x10 }, /* q */
- { 0x07, 0x02, 0x12 }, /* e */
- { 0x07, 0x03, 0x13 }, /* r */
- { 0x07, 0x04, 0x11 }, /* w */
- { 0x07, 0x05, 0x17 }, /* i */
- { 0x07, 0x06, 0x16 }, /* u */
- { 0x07, 0x07, 0x36 }, /* rsh */
- { 0x07, 0x08, 0x19 }, /* p */
- { 0x07, 0x09, 0x18 }, /* o */
- { 0x07, 0x0b, 0x5F }, /* up */
- { 0x07, 0x0c, 0x61 }, /* left */
+ 0x07010010, /* q */
+ 0x07020012, /* e */
+ 0x07030013, /* r */
+ 0x07040011, /* w */
+ 0x07050017, /* i */
+ 0x07060016, /* u */
+ 0x07070036, /* rsh */
+ 0x07080019, /* p */
+ 0x07090018, /* o */
+ 0x070b005F, /* up */
+ 0x070c0061, /* left */
};
OpenPOWER on IntegriCloud