]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/samsung/exynos/chrome_kb.c
MFC 263910, 263913, 263914, 263933, 263934, 263935, 263936, 263981, 263982,
[FreeBSD/stable/10.git] / sys / arm / samsung / exynos / chrome_kb.c
1 /*-
2  * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Samsung Chromebook Keyboard
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/rman.h>
41 #include <sys/proc.h>
42 #include <sys/sched.h>
43 #include <sys/kdb.h>
44 #include <sys/timeet.h>
45 #include <sys/timetc.h>
46 #include <sys/mutex.h>
47 #include <sys/gpio.h>
48
49 #include <dev/fdt/fdt_common.h>
50 #include <dev/ofw/openfirm.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
53
54 #include <sys/ioccom.h>
55 #include <sys/filio.h>
56 #include <sys/tty.h>
57 #include <sys/kbio.h>
58
59 #include <machine/bus.h>
60 #include <machine/fdt.h>
61 #include <machine/cpu.h>
62 #include <machine/intr.h>
63
64 #include "gpio_if.h"
65
66 #include <arm/samsung/exynos/chrome_ec.h>
67 #include <arm/samsung/exynos/chrome_kb.h>
68
69 #include <arm/samsung/exynos/exynos5_combiner.h>
70 #include <arm/samsung/exynos/exynos5_pad.h>
71
72 #define CKB_LOCK()      mtx_lock(&Giant)
73 #define CKB_UNLOCK()    mtx_unlock(&Giant)
74
75 #ifdef  INVARIANTS
76 /*
77  * Assert that the lock is held in all contexts
78  * where the code can be executed.
79  */
80 #define CKB_LOCK_ASSERT()       mtx_assert(&Giant, MA_OWNED)
81 /*
82  * Assert that the lock is held in the contexts
83  * where it really has to be so.
84  */
85 #define CKB_CTX_LOCK_ASSERT()                           \
86         do {                                            \
87                 if (!kdb_active && panicstr == NULL)    \
88                         mtx_assert(&Giant, MA_OWNED);   \
89         } while (0)
90 #else
91 #define CKB_LOCK_ASSERT()       (void)0
92 #define CKB_CTX_LOCK_ASSERT()   (void)0
93 #endif
94
95 /*
96  * Define a stub keyboard driver in case one hasn't been
97  * compiled into the kernel
98  */
99 #include <sys/kbio.h>
100 #include <dev/kbd/kbdreg.h>
101 #include <dev/kbd/kbdtables.h>
102
103 #define CKB_NFKEY               12
104 #define CKB_FLAG_COMPOSE        0x1
105 #define CKB_FLAG_POLLING        0x2
106 #define KBD_DRIVER_NAME         "ckbd"
107
108 /* TODO: take interrupt from DTS */
109 #define KB_GPIO_INT             146
110
111 struct ckb_softc {
112         keyboard_t sc_kbd;
113         keymap_t sc_keymap;
114         accentmap_t sc_accmap;
115         fkeytab_t sc_fkeymap[CKB_NFKEY];
116
117         struct resource*        sc_mem_res;
118         struct resource*        sc_irq_res;
119         void*                   sc_intr_hl;
120
121         int     sc_mode;        /* input mode (K_XLATE,K_RAW,K_CODE) */
122         int     sc_state;       /* shift/lock key state */
123         int     sc_accents;     /* accent key index (> 0) */
124         int     sc_flags;       /* flags */
125
126         struct callout          sc_repeat_callout;
127         int                     sc_repeat_key;
128         int                     sc_repeating;
129
130         int                     flag;
131         int                     rows;
132         int                     cols;
133         device_t                dev;
134         struct thread           *sc_poll_thread;
135
136         uint8_t                 *scan_local;
137         uint8_t                 *scan;
138 };
139
140 /* prototypes */
141 static void     ckb_set_leds(struct ckb_softc *, uint8_t);
142 static int      ckb_set_typematic(keyboard_t *, int);
143 static uint32_t ckb_read_char(keyboard_t *, int);
144 static void     ckb_clear_state(keyboard_t *);
145 static int      ckb_ioctl(keyboard_t *, u_long, caddr_t);
146 static int      ckb_enable(keyboard_t *);
147 static int      ckb_disable(keyboard_t *);
148
149 static void
150 ckb_repeat(void *arg)
151 {
152         struct ckb_softc *sc;
153
154         sc = arg;
155
156         if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
157                 if (sc->sc_repeat_key != -1) {
158                         sc->sc_repeating = 1;
159                         sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
160                             KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
161                 }
162         }
163 }
164
165 /* detect a keyboard, not used */
166 static int
167 ckb__probe(int unit, void *arg, int flags)
168 {
169
170         return (ENXIO);
171 }
172
173 /* reset and initialize the device, not used */
174 static int
175 ckb_init(int unit, keyboard_t **kbdp, void *arg, int flags)
176 {
177
178         return (ENXIO);
179 }
180
181 /* test the interface to the device, not used */
182 static int
183 ckb_test_if(keyboard_t *kbd)
184 {
185
186         return (0);
187 }
188
189 /* finish using this keyboard, not used */
190 static int
191 ckb_term(keyboard_t *kbd)
192 {
193
194         return (ENXIO);
195 }
196
197 /* keyboard interrupt routine, not used */
198 static int
199 ckb_intr(keyboard_t *kbd, void *arg)
200 {
201
202         return (0);
203 }
204
205 /* lock the access to the keyboard, not used */
206 static int
207 ckb_lock(keyboard_t *kbd, int lock)
208 {
209
210         return (1);
211 }
212
213 /* clear the internal state of the keyboard */
214 static void
215 ckb_clear_state(keyboard_t *kbd)
216 {
217         struct ckb_softc *sc;
218
219         sc = kbd->kb_data;
220
221         CKB_CTX_LOCK_ASSERT();
222
223         sc->sc_flags &= ~(CKB_FLAG_COMPOSE | CKB_FLAG_POLLING);
224         sc->sc_state &= LOCK_MASK; /* preserve locking key state */
225         sc->sc_accents = 0;
226 }
227
228 /* save the internal state, not used */
229 static int
230 ckb_get_state(keyboard_t *kbd, void *buf, size_t len)
231 {
232
233         return (len == 0) ? 1 : -1;
234 }
235
236 /* set the internal state, not used */
237 static int
238 ckb_set_state(keyboard_t *kbd, void *buf, size_t len)
239 {
240
241         return (EINVAL);
242 }
243
244
245 /* check if data is waiting */
246 static int
247 ckb_check(keyboard_t *kbd)
248 {
249         struct ckb_softc *sc;
250         int i;
251
252         sc = kbd->kb_data;
253
254         CKB_CTX_LOCK_ASSERT();
255
256         if (!KBD_IS_ACTIVE(kbd))
257                 return (0);
258
259         if (sc->sc_flags & CKB_FLAG_POLLING) {
260                 return (1);
261         };
262
263         for (i = 0; i < sc->cols; i++)
264                 if (sc->scan_local[i] != sc->scan[i]) {
265                         return (1);
266                 };
267
268         if (sc->sc_repeating)
269                 return (1);
270
271         return (0);
272 }
273
274 /* check if char is waiting */
275 static int
276 ckb_check_char_locked(keyboard_t *kbd)
277 {
278         CKB_CTX_LOCK_ASSERT();
279
280         if (!KBD_IS_ACTIVE(kbd))
281                 return (0);
282
283         return (ckb_check(kbd));
284 }
285
286 static int
287 ckb_check_char(keyboard_t *kbd)
288 {
289         int result;
290
291         CKB_LOCK();
292         result = ckb_check_char_locked(kbd);
293         CKB_UNLOCK();
294
295         return (result);
296 }
297
298 /* read one byte from the keyboard if it's allowed */
299 /* Currently unused. */
300 static int
301 ckb_read(keyboard_t *kbd, int wait)
302 {
303         CKB_CTX_LOCK_ASSERT();
304
305         if (!KBD_IS_ACTIVE(kbd))
306                 return (-1);
307
308         printf("Implement ME: %s\n", __func__);
309         return (0);
310 }
311
312 int scantokey(int i, int j);
313
314 int
315 scantokey(int i, int j)
316 {
317         int k;
318
319         for (k = 0; k < KEYMAP_LEN; k++)
320                 if ((keymap[k].col == i) && (keymap[k].row == j))
321                         return (keymap[k].key);
322
323         return (0);
324 }
325
326 /* read char from the keyboard */
327 static uint32_t
328 ckb_read_char_locked(keyboard_t *kbd, int wait)
329 {
330         struct ckb_softc *sc;
331         int i,j;
332         uint16_t key;
333         int oldbit;
334         int newbit;
335
336         sc = kbd->kb_data;
337
338         CKB_CTX_LOCK_ASSERT();
339
340         if (!KBD_IS_ACTIVE(kbd))
341                 return (NOKEY);
342
343         if (sc->sc_repeating) {
344                 sc->sc_repeating = 0;
345                 callout_reset(&sc->sc_repeat_callout, hz / 10,
346                     ckb_repeat, sc);
347                 return (sc->sc_repeat_key);
348         };
349
350         if (sc->sc_flags & CKB_FLAG_POLLING) {
351                 /* TODO */
352         };
353
354         for (i = 0; i < sc->cols; i++) {
355                 for (j = 0; j < sc->rows; j++) {
356                         oldbit = (sc->scan_local[i] & (1 << j));
357                         newbit = (sc->scan[i] & (1 << j));
358
359                         if (oldbit == newbit)
360                                 continue;
361
362                         key = scantokey(i,j);
363                         if (key == 0) {
364                                 continue;
365                         };
366
367                         if (newbit > 0) {
368                                 /* key pressed */
369                                 sc->scan_local[i] |= (1 << j);
370
371                                 /* setup repeating */
372                                 sc->sc_repeat_key = key;
373                                 callout_reset(&sc->sc_repeat_callout,
374                                     hz / 2, ckb_repeat, sc);
375
376                         } else {
377                                 /* key released */
378                                 sc->scan_local[i] &= ~(1 << j);
379
380                                 /* release flag */
381                                 key |= 0x80;
382
383                                 /* unsetup repeating */
384                                 sc->sc_repeat_key = -1;
385                                 callout_stop(&sc->sc_repeat_callout);
386                         }
387
388                         return (key);
389                 }
390         }
391
392         return (NOKEY);
393 }
394
395 /* Currently wait is always false. */
396 static uint32_t
397 ckb_read_char(keyboard_t *kbd, int wait)
398 {
399         uint32_t keycode;
400
401         CKB_LOCK();
402         keycode = ckb_read_char_locked(kbd, wait);
403         CKB_UNLOCK();
404
405         return (keycode);
406 }
407
408
409 /* some useful control functions */
410 static int
411 ckb_ioctl_locked(keyboard_t *kbd, u_long cmd, caddr_t arg)
412 {
413         struct ckb_softc *sc;
414         int i;
415
416         sc = kbd->kb_data;
417
418         CKB_LOCK_ASSERT();
419
420         switch (cmd) {
421         case KDGKBMODE:         /* get keyboard mode */
422                 *(int *)arg = sc->sc_mode;
423                 break;
424
425         case KDSKBMODE:         /* set keyboard mode */
426                 switch (*(int *)arg) {
427                 case K_XLATE:
428                         if (sc->sc_mode != K_XLATE) {
429                                 /* make lock key state and LED state match */
430                                 sc->sc_state &= ~LOCK_MASK;
431                                 sc->sc_state |= KBD_LED_VAL(kbd);
432                         }
433                         /* FALLTHROUGH */
434                 case K_RAW:
435                 case K_CODE:
436                         if (sc->sc_mode != *(int *)arg) {
437                                 if ((sc->sc_flags & CKB_FLAG_POLLING) == 0)
438                                         ckb_clear_state(kbd);
439                                 sc->sc_mode = *(int *)arg;
440                         }
441                         break;
442                 default:
443                         return (EINVAL);
444                 }
445                 break;
446
447         case KDGETLED:                  /* get keyboard LED */
448                 *(int *)arg = KBD_LED_VAL(kbd);
449                 break;
450
451         case KDSETLED:                  /* set keyboard LED */
452                 /* NOTE: lock key state in "sc_state" won't be changed */
453                 if (*(int *)arg & ~LOCK_MASK)
454                         return (EINVAL);
455
456                 i = *(int *)arg;
457
458                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
459                 if (sc->sc_mode == K_XLATE &&
460                     kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
461                         if (i & ALKED)
462                                 i |= CLKED;
463                         else
464                                 i &= ~CLKED;
465                 }
466                 if (KBD_HAS_DEVICE(kbd)) {
467                         /* Configure LED */
468                 }
469
470                 KBD_LED_VAL(kbd) = *(int *)arg;
471                 break;
472         case KDGKBSTATE:                /* get lock key state */
473                 *(int *)arg = sc->sc_state & LOCK_MASK;
474                 break;
475
476         case KDSKBSTATE:                /* set lock key state */
477                 if (*(int *)arg & ~LOCK_MASK) {
478                         return (EINVAL);
479                 }
480                 sc->sc_state &= ~LOCK_MASK;
481                 sc->sc_state |= *(int *)arg;
482
483                 /* set LEDs and quit */
484                 return (ckb_ioctl(kbd, KDSETLED, arg));
485
486         case KDSETREPEAT:               /* set keyboard repeat rate (new
487                                          * interface) */
488
489                 if (!KBD_HAS_DEVICE(kbd)) {
490                         return (0);
491                 }
492                 if (((int *)arg)[1] < 0) {
493                         return (EINVAL);
494                 }
495                 if (((int *)arg)[0] < 0) {
496                         return (EINVAL);
497                 }
498                 if (((int *)arg)[0] < 200)      /* fastest possible value */
499                         kbd->kb_delay1 = 200;
500                 else
501                         kbd->kb_delay1 = ((int *)arg)[0];
502                 kbd->kb_delay2 = ((int *)arg)[1];
503                 return (0);
504
505         case KDSETRAD:                  /* set keyboard repeat rate (old
506                                          * interface) */
507                 return (ckb_set_typematic(kbd, *(int *)arg));
508
509         case PIO_KEYMAP:                /* set keyboard translation table */
510         case OPIO_KEYMAP:               /* set keyboard translation table
511                                          * (compat) */
512         case PIO_KEYMAPENT:             /* set keyboard translation table
513                                          * entry */
514         case PIO_DEADKEYMAP:            /* set accent key translation table */
515                 sc->sc_accents = 0;
516                 /* FALLTHROUGH */
517         default:
518                 return (genkbd_commonioctl(kbd, cmd, arg));
519         }
520
521         return (0);
522 }
523
524 static int
525 ckb_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
526 {
527         int result;
528
529         /*
530          * XXX KDGKBSTATE, KDSKBSTATE and KDSETLED can be called from any
531          * context where printf(9) can be called, which among other things
532          * includes interrupt filters and threads with any kinds of locks
533          * already held.  For this reason it would be dangerous to acquire
534          * the Giant here unconditionally.  On the other hand we have to
535          * have it to handle the ioctl.
536          * So we make our best effort to auto-detect whether we can grab
537          * the Giant or not.  Blame syscons(4) for this.
538          */
539         switch (cmd) {
540         case KDGKBSTATE:
541         case KDSKBSTATE:
542         case KDSETLED:
543                 if (!mtx_owned(&Giant) && !SCHEDULER_STOPPED())
544                         return (EDEADLK);       /* best I could come up with */
545                 /* FALLTHROUGH */
546         default:
547                 CKB_LOCK();
548                 result = ckb_ioctl_locked(kbd, cmd, arg);
549                 CKB_UNLOCK();
550                 return (result);
551         }
552 }
553
554
555 /*
556  * Enable the access to the device; until this function is called,
557  * the client cannot read from the keyboard.
558  */
559 static int
560 ckb_enable(keyboard_t *kbd)
561 {
562
563         CKB_LOCK();
564         KBD_ACTIVATE(kbd);
565         CKB_UNLOCK();
566
567         return (0);
568 }
569
570 /* disallow the access to the device */
571 static int
572 ckb_disable(keyboard_t *kbd)
573 {
574
575         CKB_LOCK();
576         KBD_DEACTIVATE(kbd);
577         CKB_UNLOCK();
578
579         return (0);
580 }
581
582 /* local functions */
583
584 static int
585 ckb_set_typematic(keyboard_t *kbd, int code)
586 {
587         static const int delays[] = {250, 500, 750, 1000};
588         static const int rates[] = {34, 38, 42, 46, 50, 55, 59, 63,
589                 68, 76, 84, 92, 100, 110, 118, 126,
590                 136, 152, 168, 184, 200, 220, 236, 252,
591         272, 304, 336, 368, 400, 440, 472, 504};
592
593         if (code & ~0x7f) {
594                 return (EINVAL);
595         }
596         kbd->kb_delay1 = delays[(code >> 5) & 3];
597         kbd->kb_delay2 = rates[code & 0x1f];
598         return (0);
599 }
600
601 static int
602 ckb_poll(keyboard_t *kbd, int on)
603 {
604         struct ckb_softc *sc;
605
606         sc = kbd->kb_data;
607
608         CKB_LOCK();
609         if (on) {
610                 sc->sc_flags |= CKB_FLAG_POLLING;
611                 sc->sc_poll_thread = curthread;
612         } else {
613                 sc->sc_flags &= ~CKB_FLAG_POLLING;
614         }
615         CKB_UNLOCK();
616
617         return (0);
618 }
619
620 /* local functions */
621
622 static int dummy_kbd_configure(int flags);
623
624 keyboard_switch_t ckbdsw = {
625         .probe = &ckb__probe,
626         .init = &ckb_init,
627         .term = &ckb_term,
628         .intr = &ckb_intr,
629         .test_if = &ckb_test_if,
630         .enable = &ckb_enable,
631         .disable = &ckb_disable,
632         .read = &ckb_read,
633         .check = &ckb_check,
634         .read_char = &ckb_read_char,
635         .check_char = &ckb_check_char,
636         .ioctl = &ckb_ioctl,
637         .lock = &ckb_lock,
638         .clear_state = &ckb_clear_state,
639         .get_state = &ckb_get_state,
640         .set_state = &ckb_set_state,
641         .get_fkeystr = &genkbd_get_fkeystr,
642         .poll = &ckb_poll,
643         .diag = &genkbd_diag,
644 };
645
646 static int
647 dummy_kbd_configure(int flags)
648 {
649
650         return (0);
651 }
652
653 KEYBOARD_DRIVER(ckbd, ckbdsw, dummy_kbd_configure);
654
655 static int
656 parse_dts(struct ckb_softc *sc)
657 {
658         phandle_t node;
659         pcell_t dts_value;
660         int len;
661
662         if ((node = ofw_bus_get_node(sc->dev)) == -1)
663                 return (ENXIO);
664
665         if ((len = OF_getproplen(node, "keypad,num-rows")) <= 0)
666                 return (ENXIO);
667         OF_getprop(node, "keypad,num-rows", &dts_value, len);
668         sc->rows = fdt32_to_cpu(dts_value);
669
670         if ((len = OF_getproplen(node, "keypad,num-columns")) <= 0)
671                 return (ENXIO);
672         OF_getprop(node, "keypad,num-columns", &dts_value, len);
673         sc->cols = fdt32_to_cpu(dts_value);
674
675         if ((sc->rows == 0) || (sc->cols == 0))
676                 return (ENXIO);
677
678         return (0);
679 }
680
681 void
682 ckb_ec_intr(void *arg)
683 {
684         struct ckb_softc *sc;
685
686         sc = arg;
687
688         if (sc->sc_flags & CKB_FLAG_POLLING)
689                 return;
690
691         ec_command(EC_CMD_MKBP_STATE, sc->scan, sc->cols,
692             sc->scan, sc->cols);
693
694         (sc->sc_kbd.kb_callback.kc_func) (&sc->sc_kbd, KBDIO_KEYINPUT,
695             sc->sc_kbd.kb_callback.kc_arg);
696 };
697
698 static int
699 chrome_kb_attach(device_t dev)
700 {
701         struct ckb_softc *sc;
702         keyboard_t *kbd;
703         int error;
704         int rid;
705         int i;
706
707         sc = device_get_softc(dev);
708
709         sc->dev = dev;
710
711         if ((error = parse_dts(sc)) != 0)
712                 return error;
713
714 #if 0
715         device_printf(sc->dev, "Keyboard matrix [%dx%d]\n",
716             sc->cols, sc->rows);
717 #endif
718
719         /* TODO: take interrupt from DTS */
720         pad_setup_intr(KB_GPIO_INT, ckb_ec_intr, sc);
721
722         kbd = &sc->sc_kbd;
723         rid = 0;
724
725         sc->scan_local = malloc(sc->cols, M_DEVBUF, M_NOWAIT);
726         sc->scan = malloc(sc->cols, M_DEVBUF, M_NOWAIT);
727
728         for (i = 0; i < sc->cols; i++) {
729                 sc->scan_local[i] = 0;
730                 sc->scan[i] = 0;
731         };
732
733         kbd_init_struct(kbd, KBD_DRIVER_NAME, KB_OTHER,
734             device_get_unit(dev), 0, 0, 0);
735         kbd->kb_data = (void *)sc;
736
737         sc->sc_keymap = key_map;
738         sc->sc_accmap = accent_map;
739         for (i = 0; i < CKB_NFKEY; i++) {
740                 sc->sc_fkeymap[i] = fkey_tab[i];
741         }
742
743         kbd_set_maps(kbd, &sc->sc_keymap, &sc->sc_accmap,
744             sc->sc_fkeymap, CKB_NFKEY);
745
746         KBD_FOUND_DEVICE(kbd);
747         ckb_clear_state(kbd);
748         KBD_PROBE_DONE(kbd);
749
750         callout_init(&sc->sc_repeat_callout, 0);
751
752         KBD_INIT_DONE(kbd);
753
754         if (kbd_register(kbd) < 0) {
755                 return (ENXIO);
756         };
757         KBD_CONFIG_DONE(kbd);
758
759         return (0);
760 }
761
762 static int
763 chrome_kb_probe(device_t dev)
764 {
765
766         if (!ofw_bus_status_okay(dev))
767                 return (ENXIO);
768
769         if (ofw_bus_is_compatible(dev, "google,cros-ec-keyb")) {
770                 device_set_desc(dev, "Chrome EC Keyboard");
771                 return (BUS_PROBE_DEFAULT);
772         }
773
774         return (ENXIO);
775 }
776
777 static device_method_t chrome_kb_methods[] = {
778         DEVMETHOD(device_probe,         chrome_kb_probe),
779         DEVMETHOD(device_attach,        chrome_kb_attach),
780         { 0, 0 }
781 };
782
783 static driver_t chrome_kb_driver = {
784         "chrome_kb",
785         chrome_kb_methods,
786         sizeof(struct ckb_softc),
787 };
788
789 static devclass_t chrome_kb_devclass;
790
791 DRIVER_MODULE(chrome_kb, simplebus, chrome_kb_driver,
792     chrome_kb_devclass, 0, 0);