arm_coreboot: Support keyboard for vexpress.
This commit is contained in:
parent
216950a4ee
commit
848bed9d92
4 changed files with 194 additions and 0 deletions
|
@ -240,6 +240,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if COND_arm_coreboot
|
if COND_arm_coreboot
|
||||||
|
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
|
||||||
|
|
|
@ -160,6 +160,9 @@ kernel = {
|
||||||
arm_coreboot = kern/arm/coreboot/coreboot.S;
|
arm_coreboot = kern/arm/coreboot/coreboot.S;
|
||||||
arm_coreboot = lib/fdt.c;
|
arm_coreboot = lib/fdt.c;
|
||||||
arm_coreboot = bus/fdt.c;
|
arm_coreboot = bus/fdt.c;
|
||||||
|
arm_coreboot = term/ps2.c;
|
||||||
|
arm_coreboot = term/arm/pl050.c;
|
||||||
|
arm_coreboot = commands/keylayouts.c;
|
||||||
|
|
||||||
terminfoinkernel = term/terminfo.c;
|
terminfoinkernel = term/terminfo.c;
|
||||||
terminfoinkernel = term/tparm.c;
|
terminfoinkernel = term/tparm.c;
|
||||||
|
|
|
@ -133,6 +133,7 @@ grub_machine_init (void)
|
||||||
grub_fdtbus_init (dtb, dtb_size);
|
grub_fdtbus_init (dtb, dtb_size);
|
||||||
|
|
||||||
grub_machine_timer_init ();
|
grub_machine_timer_init ();
|
||||||
|
grub_pl050_init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
189
grub-core/term/arm/pl050.c
Normal file
189
grub-core/term/arm/pl050.c
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GRUB is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/ps2.h>
|
||||||
|
#include <grub/fdtbus.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/machine/kernel.h>
|
||||||
|
#include <grub/at_keyboard.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/term.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
#include <grub/ps2.h>
|
||||||
|
#include <grub/fdtbus.h>
|
||||||
|
|
||||||
|
static volatile grub_uint32_t *pl050_regs;
|
||||||
|
|
||||||
|
struct grub_ps2_state ps2_state;
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_controller_wait_until_ready (void)
|
||||||
|
{
|
||||||
|
while (! (pl050_regs[1] & 0x40));
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_uint8_t
|
||||||
|
wait_ack (void)
|
||||||
|
{
|
||||||
|
grub_uint64_t endtime;
|
||||||
|
grub_uint8_t ack;
|
||||||
|
|
||||||
|
endtime = grub_get_time_ms () + 20;
|
||||||
|
do
|
||||||
|
ack = pl050_regs[2];
|
||||||
|
while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
|
||||||
|
&& grub_get_time_ms () < endtime);
|
||||||
|
return ack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_mode (int mode)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < GRUB_AT_TRIES; i++)
|
||||||
|
{
|
||||||
|
grub_uint8_t ack;
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
pl050_regs[2] = 0xf0;
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
pl050_regs[2] = mode;
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
ack = wait_ack ();
|
||||||
|
if (ack == GRUB_AT_NACK)
|
||||||
|
continue;
|
||||||
|
if (ack == GRUB_AT_ACK)
|
||||||
|
break;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (i != GRUB_AT_TRIES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
query_mode (void)
|
||||||
|
{
|
||||||
|
grub_uint8_t ret;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
e = write_mode (0);
|
||||||
|
if (!e)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
|
||||||
|
do
|
||||||
|
ret = pl050_regs[2];
|
||||||
|
while (ret == GRUB_AT_ACK);
|
||||||
|
|
||||||
|
/* QEMU translates the set even in no-translate mode. */
|
||||||
|
if (ret == 0x43 || ret == 1)
|
||||||
|
return 1;
|
||||||
|
if (ret == 0x41 || ret == 2)
|
||||||
|
return 2;
|
||||||
|
if (ret == 0x3f || ret == 3)
|
||||||
|
return 3;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_scancodes (void)
|
||||||
|
{
|
||||||
|
write_mode (2);
|
||||||
|
ps2_state.current_set = query_mode ();
|
||||||
|
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
|
||||||
|
if (ps2_state.current_set == 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
write_mode (1);
|
||||||
|
ps2_state.current_set = query_mode ();
|
||||||
|
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
|
||||||
|
if (ps2_state.current_set == 1)
|
||||||
|
return;
|
||||||
|
grub_dprintf ("atkeyb", "no supported scancode set found\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_controller_led (grub_uint8_t leds)
|
||||||
|
{
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
pl050_regs[2] = 0xed;
|
||||||
|
keyboard_controller_wait_until_ready ();
|
||||||
|
pl050_regs[2] = leds & 0x7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is a character pending, return it;
|
||||||
|
otherwise return GRUB_TERM_NO_KEY. */
|
||||||
|
static int
|
||||||
|
grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
grub_uint8_t at_key;
|
||||||
|
int ret;
|
||||||
|
grub_uint8_t old_led;
|
||||||
|
|
||||||
|
if (!(pl050_regs[1] & 0x10))
|
||||||
|
return -1;
|
||||||
|
at_key = pl050_regs[2];
|
||||||
|
old_led = ps2_state.led_status;
|
||||||
|
|
||||||
|
ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
|
||||||
|
if (old_led != ps2_state.led_status)
|
||||||
|
keyboard_controller_led (ps2_state.led_status);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_term_input grub_pl050_keyboard_term =
|
||||||
|
{
|
||||||
|
.name = "pl050_keyboard",
|
||||||
|
.getkey = grub_pl050_keyboard_getkey
|
||||||
|
};
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
pl050_attach(const struct grub_fdtbus_dev *dev)
|
||||||
|
{
|
||||||
|
const grub_uint32_t *reg;
|
||||||
|
reg = grub_fdtbus_get_prop (dev, "reg", 0);
|
||||||
|
|
||||||
|
/* Mouse. Nothing to do. */
|
||||||
|
if (grub_be_to_cpu32 (*reg) == 0x7000)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
|
||||||
|
|
||||||
|
if (!grub_fdtbus_is_mapping_valid (pl050_regs))
|
||||||
|
return grub_error (GRUB_ERR_IO, "could not map pl050");
|
||||||
|
|
||||||
|
ps2_state.at_keyboard_status = 0;
|
||||||
|
set_scancodes ();
|
||||||
|
keyboard_controller_led (ps2_state.led_status);
|
||||||
|
|
||||||
|
grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct grub_fdtbus_driver pl050 =
|
||||||
|
{
|
||||||
|
.compatible = "arm,pl050",
|
||||||
|
.attach = pl050_attach
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_pl050_init (void)
|
||||||
|
{
|
||||||
|
grub_fdtbus_register (&pl050);
|
||||||
|
}
|
Loading…
Reference in a new issue