summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/fsl_sata.c1
-rw-r--r--drivers/core/device-remove.c22
-rw-r--r--drivers/core/root.c8
-rw-r--r--drivers/fpga/ACEX1K.c1
-rw-r--r--drivers/fpga/virtex2.c1
-rw-r--r--drivers/fpga/zynqpl.c1
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/adi_i2c.c1
-rw-r--r--drivers/input/Kconfig19
-rw-r--r--drivers/input/Makefile4
-rw-r--r--drivers/input/cros_ec_keyb.c147
-rw-r--r--drivers/input/i8042.c647
-rw-r--r--drivers/input/input.c252
-rw-r--r--drivers/input/keyboard-uclass.c91
-rw-r--r--drivers/input/keyboard.c289
-rw-r--r--drivers/input/tegra-kbc.c242
-rw-r--r--drivers/misc/cbmem_console.c2
-rw-r--r--drivers/misc/cros_ec.c14
-rw-r--r--drivers/misc/cros_ec_sandbox.c1
-rw-r--r--drivers/mmc/zynq_sdhci.c2
-rw-r--r--drivers/mtd/cfi_flash.c1
-rw-r--r--drivers/mtd/nand/bfin_nand.c1
-rw-r--r--drivers/mtd/spi/Makefile1
-rw-r--r--drivers/mtd/spi/eeprom_m95xxx.c111
-rw-r--r--drivers/mtd/spi/sf-uclass.c23
-rw-r--r--drivers/mtd/spi/sf_internal.h1
-rw-r--r--drivers/mtd/spi/sf_ops.c14
-rw-r--r--drivers/mtd/spi/sf_probe.c12
-rw-r--r--drivers/net/e1000_spi.c1
-rw-r--r--drivers/net/keystone_net.c1
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/phy.c4
-rw-r--r--drivers/net/phy/ti.c200
-rw-r--r--drivers/net/vsc7385.c1
-rw-r--r--drivers/net/zynq_gem.c143
-rw-r--r--drivers/pci/pci_common.c2
-rw-r--r--drivers/power/Kconfig5
-rw-r--r--drivers/power/battery/bat_trats.c1
-rw-r--r--drivers/serial/Kconfig26
-rw-r--r--drivers/serial/Makefile7
-rw-r--r--drivers/serial/ns16550.c45
-rw-r--r--drivers/serial/serial_dw.c39
-rw-r--r--drivers/serial/serial_keystone.c48
-rw-r--r--drivers/serial/serial_omap.c54
-rw-r--r--drivers/serial/serial_ppc.c40
-rw-r--r--drivers/serial/serial_rockchip.c43
-rw-r--r--drivers/serial/serial_tegra.c54
-rw-r--r--drivers/serial/serial_x86.c44
-rw-r--r--drivers/spi/bfin_spi.c1
-rw-r--r--drivers/spi/bfin_spi6xx.c1
-rw-r--r--drivers/spi/sh_qspi.c1
-rw-r--r--drivers/spi/sh_spi.c1
-rw-r--r--drivers/spi/spi-uclass.c20
-rw-r--r--drivers/spi/ti_qspi.c2
-rw-r--r--drivers/timer/Kconfig7
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/sandbox_timer.c53
-rw-r--r--drivers/usb/emul/Makefile1
-rw-r--r--drivers/usb/emul/sandbox_flash.c48
-rw-r--r--drivers/usb/emul/sandbox_hub.c2
-rw-r--r--drivers/usb/emul/sandbox_keyb.c241
-rw-r--r--drivers/usb/emul/usb-emul-uclass.c29
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/gadget/f_mass_storage.c1
-rw-r--r--drivers/usb/gadget/f_thor.c1
-rw-r--r--drivers/usb/host/r8a66597-hcd.c1
-rw-r--r--drivers/usb/host/usb-sandbox.c19
-rw-r--r--drivers/usb/host/usb-uclass.c54
-rw-r--r--drivers/usb/musb-new/musb_uboot.c1
-rw-r--r--drivers/usb/musb-new/sunxi.c12
-rw-r--r--drivers/video/cfb_console.c82
71 files changed, 1641 insertions, 1609 deletions
diff --git a/drivers/block/fsl_sata.c b/drivers/block/fsl_sata.c
index 735708a..208a0ae 100644
--- a/drivers/block/fsl_sata.c
+++ b/drivers/block/fsl_sata.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <command.h>
+#include <console.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/fsl_serdes.h>
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index bd6d406..e1714b2 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -18,7 +18,16 @@
#include <dm/uclass-internal.h>
#include <dm/util.h>
-int device_unbind_children(struct udevice *dev)
+/**
+ * device_chld_unbind() - Unbind all device's children from the device
+ *
+ * On error, the function continues to unbind all children, and reports the
+ * first error.
+ *
+ * @dev: The device that is to be stripped of its children
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_unbind(struct udevice *dev)
{
struct udevice *pos, *n;
int ret, saved_ret = 0;
@@ -34,7 +43,12 @@ int device_unbind_children(struct udevice *dev)
return saved_ret;
}
-int device_remove_children(struct udevice *dev)
+/**
+ * device_chld_remove() - Stop all device's children
+ * @dev: The device whose children are to be removed
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_remove(struct udevice *dev)
{
struct udevice *pos, *n;
int ret;
@@ -73,7 +87,7 @@ int device_unbind(struct udevice *dev)
return ret;
}
- ret = device_unbind_children(dev);
+ ret = device_chld_unbind(dev);
if (ret)
return ret;
@@ -153,7 +167,7 @@ int device_remove(struct udevice *dev)
if (ret)
return ret;
- ret = device_remove_children(dev);
+ ret = device_chld_remove(dev);
if (ret)
goto err;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index bdb394a..e7b1f24 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -59,6 +59,8 @@ void fix_drivers(void)
entry->unbind += gd->reloc_off;
if (entry->ofdata_to_platdata)
entry->ofdata_to_platdata += gd->reloc_off;
+ if (entry->child_post_bind)
+ entry->child_post_bind += gd->reloc_off;
if (entry->child_pre_probe)
entry->child_pre_probe += gd->reloc_off;
if (entry->child_post_remove)
@@ -81,10 +83,16 @@ void fix_uclass(void)
entry->post_bind += gd->reloc_off;
if (entry->pre_unbind)
entry->pre_unbind += gd->reloc_off;
+ if (entry->pre_probe)
+ entry->pre_probe += gd->reloc_off;
if (entry->post_probe)
entry->post_probe += gd->reloc_off;
if (entry->pre_remove)
entry->pre_remove += gd->reloc_off;
+ if (entry->child_post_bind)
+ entry->child_post_bind += gd->reloc_off;
+ if (entry->child_pre_probe)
+ entry->child_pre_probe += gd->reloc_off;
if (entry->init)
entry->init += gd->reloc_off;
if (entry->destroy)
diff --git a/drivers/fpga/ACEX1K.c b/drivers/fpga/ACEX1K.c
index 06b8837..1627f0e 100644
--- a/drivers/fpga/ACEX1K.c
+++ b/drivers/fpga/ACEX1K.c
@@ -9,6 +9,7 @@
*/
#include <common.h> /* core U-Boot definitions */
+#include <console.h>
#include <ACEX1K.h> /* ACEX device family */
/* Define FPGA_DEBUG to get debug printf's */
diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c
index 0d2d9a4..f7cf02a 100644
--- a/drivers/fpga/virtex2.c
+++ b/drivers/fpga/virtex2.c
@@ -12,6 +12,7 @@
*/
#include <common.h>
+#include <console.h>
#include <virtex2.h>
#if 0
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index 6a74f89..ef889ea 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
+#include <console.h>
#include <asm/io.h>
#include <fs.h>
#include <zynqpl.h>
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 32198bd..811ad9b 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -40,4 +40,4 @@ obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
-obj-y += muxes/
+obj-$(CONFIG_I2C_MUX) += muxes/
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
index c58f14a..f0c0841 100644
--- a/drivers/i2c/adi_i2c.c
+++ b/drivers/i2c/adi_i2c.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <console.h>
#include <i2c.h>
#include <asm/clock.h>
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index bb00de7..d560328 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -1,6 +1,25 @@
+config DM_KEYBOARD
+ bool "Enable driver model keyboard support"
+ depends on DM
+ help
+ This adds a uclass for keyboards and implements keyboard support
+ using driver model. The API is implemented by keyboard.h and
+ includes methods to start/stop the device, check for available
+ input and update LEDs if the keyboard has them.
+
config CROS_EC_KEYB
bool "Enable Chrome OS EC keyboard support"
help
Most ARM Chromebooks use an EC to provide access to the keyboard.
Messages are used to request key scans from the EC and these are
then decoded into keys by this driver.
+
+config I8042_KEYB
+ bool "Enable Intel i8042 keyboard support"
+ depends on DM_KEYBOARD
+ help
+ This adds a driver for the i8042 keyboard controller, allowing the
+ keyboard to be used on devices which support this controller. The
+ driver handles English and German keyboards - set the environment
+ variable 'keymap' to "de" to select German. Keyboard repeat is
+ handled by the keyboard itself.
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index b1161c5..5f15265 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -5,7 +5,9 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-$(CONFIG_I8042_KBD) += i8042.o
+obj-$(CONFIG_DM_KEYBOARD) += keyboard-uclass.o
+
+obj-$(CONFIG_I8042_KEYB) += i8042.o
obj-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o
obj-$(CONFIG_TWL4030_INPUT) += twl4030.o
obj-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o
diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c
index dd150ee..9bc4555 100644
--- a/drivers/input/cros_ec_keyb.c
+++ b/drivers/input/cros_ec_keyb.c
@@ -8,9 +8,11 @@
#include <common.h>
#include <cros_ec.h>
+#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <input.h>
+#include <keyboard.h>
#include <key_matrix.h>
#include <stdio_dev.h>
@@ -22,31 +24,29 @@ enum {
KBC_REPEAT_DELAY_MS = 240,
};
-static struct keyb {
- struct cros_ec_dev *dev; /* The CROS_EC device */
- struct input_config input; /* The input layer */
+struct cros_ec_keyb_priv {
+ struct input_config *input; /* The input layer */
struct key_matrix matrix; /* The key matrix layer */
int key_rows; /* Number of keyboard rows */
int key_cols; /* Number of keyboard columns */
int ghost_filter; /* 1 to enable ghost filter, else 0 */
- int inited; /* 1 if keyboard is ready */
-} config;
+};
/**
* Check the keyboard controller and return a list of key matrix positions
* for which a key is pressed
*
- * @param config Keyboard config
+ * @param dev Keyboard device
* @param keys List of keys that we have detected
* @param max_count Maximum number of keys to return
* @param samep Set to true if this scan repeats the last, else false
* @return number of pressed keys, 0 for none, -EIO on error
*/
-static int check_for_keys(struct keyb *config,
- struct key_matrix_key *keys, int max_count,
- bool *samep)
+static int check_for_keys(struct udevice *dev, struct key_matrix_key *keys,
+ int max_count, bool *samep)
{
+ struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
struct key_matrix_key *key;
static struct mbkp_keyscan last_scan;
static bool last_scan_valid;
@@ -54,7 +54,7 @@ static int check_for_keys(struct keyb *config,
unsigned int row, col, bit, data;
int num_keys;
- if (cros_ec_scan_keyboard(config->dev, &scan)) {
+ if (cros_ec_scan_keyboard(dev->parent, &scan)) {
debug("%s: keyboard scan failed\n", __func__);
return -EIO;
}
@@ -69,9 +69,9 @@ static int check_for_keys(struct keyb *config,
last_scan_valid = true;
memcpy(&last_scan, &scan, sizeof(last_scan));
- for (col = num_keys = bit = 0; col < config->matrix.num_cols;
+ for (col = num_keys = bit = 0; col < priv->matrix.num_cols;
col++) {
- for (row = 0; row < config->matrix.num_rows; row++) {
+ for (row = 0; row < priv->matrix.num_rows; row++) {
unsigned int mask = 1 << (bit & 7);
data = scan.data[bit / 8];
@@ -89,28 +89,6 @@ static int check_for_keys(struct keyb *config,
}
/**
- * Test if keys are available to be read
- *
- * @return 0 if no keys available, 1 if keys are available
- */
-static int kbd_tstc(struct stdio_dev *dev)
-{
- /* Just get input to do this for us */
- return config.inited ? input_tstc(&config.input) : 0;
-}
-
-/**
- * Read a key
- *
- * @return ASCII key code, or 0 if no key, or -1 if error
- */
-static int kbd_getc(struct stdio_dev *dev)
-{
- /* Just get input to do this for us */
- return config.inited ? input_getc(&config.input) : 0;
-}
-
-/**
* Check the keyboard, and send any keys that are pressed.
*
* This is called by input_tstc() and input_getc() when they need more
@@ -121,6 +99,8 @@ static int kbd_getc(struct stdio_dev *dev)
*/
int cros_ec_kbc_check(struct input_config *input)
{
+ struct udevice *dev = input->dev;
+ struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
static struct key_matrix_key last_keys[KBC_MAX_KEYS];
static int last_num_keys;
struct key_matrix_key keys[KBC_MAX_KEYS];
@@ -139,9 +119,9 @@ int cros_ec_kbc_check(struct input_config *input)
* may return 0 before all keys have been read from the EC.
*/
do {
- irq_pending = cros_ec_interrupt_pending(config.dev);
+ irq_pending = cros_ec_interrupt_pending(dev->parent);
if (irq_pending) {
- num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS,
+ num_keys = check_for_keys(dev, keys, KBC_MAX_KEYS,
&same);
if (num_keys < 0)
return 0;
@@ -158,7 +138,7 @@ int cros_ec_kbc_check(struct input_config *input)
if (num_keys < 0)
return -1;
- num_keycodes = key_matrix_decode(&config.matrix, keys,
+ num_keycodes = key_matrix_decode(&priv->matrix, keys,
num_keys, keycodes, KBC_MAX_KEYS);
sent = input_send_keycodes(input, keycodes, num_keycodes);
@@ -182,7 +162,7 @@ int cros_ec_kbc_check(struct input_config *input)
* @return 0 if ok, -1 on error
*/
static int cros_ec_keyb_decode_fdt(const void *blob, int node,
- struct keyb *config)
+ struct cros_ec_keyb_priv *config)
{
/*
* Get keyboard rows and columns - at present we are limited to
@@ -202,67 +182,56 @@ static int cros_ec_keyb_decode_fdt(const void *blob, int node,
return 0;
}
-/**
- * Set up the keyboard. This is called by the stdio device handler.
- *
- * We want to do this init when the keyboard is actually used rather than
- * at start-up, since keyboard input may not currently be selected.
- *
- * @return 0 if ok, -1 on error
- */
-static int cros_ec_init_keyboard(struct stdio_dev *dev)
+static int cros_ec_kbd_probe(struct udevice *dev)
{
+ struct cros_ec_keyb_priv *priv = dev_get_priv(dev);
+ struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct stdio_dev *sdev = &uc_priv->sdev;
+ struct input_config *input = &uc_priv->input;
const void *blob = gd->fdt_blob;
- int node;
+ int node = dev->of_offset;
+ int ret;
- config.dev = board_get_cros_ec_dev();
- if (!config.dev) {
- debug("%s: no cros_ec device: cannot init keyboard\n",
- __func__);
+ if (cros_ec_keyb_decode_fdt(blob, node, priv))
return -1;
- }
- node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
- if (node < 0) {
- debug("%s: Node not found\n", __func__);
- return -1;
- }
- if (cros_ec_keyb_decode_fdt(blob, node, &config))
- return -1;
- input_set_delays(&config.input, KBC_REPEAT_DELAY_MS,
- KBC_REPEAT_RATE_MS);
- if (key_matrix_init(&config.matrix, config.key_rows,
- config.key_cols, config.ghost_filter)) {
+ input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
+ ret = key_matrix_init(&priv->matrix, priv->key_rows, priv->key_cols,
+ priv->ghost_filter);
+ if (ret) {
debug("%s: cannot init key matrix\n", __func__);
- return -1;
+ return ret;
}
- if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
+ ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
+ if (ret) {
debug("%s: Could not decode key matrix from fdt\n", __func__);
- return -1;
+ return ret;
}
- config.inited = 1;
- debug("%s: Matrix keyboard %dx%d ready\n", __func__, config.key_rows,
- config.key_cols);
+ debug("%s: Matrix keyboard %dx%d ready\n", __func__, priv->key_rows,
+ priv->key_cols);
- return 0;
-}
+ priv->input = input;
+ input->dev = dev;
+ input_add_tables(input, false);
+ input->read_keys = cros_ec_kbc_check;
+ strcpy(sdev->name, "cros-ec-keyb");
-int drv_keyboard_init(void)
-{
- struct stdio_dev dev;
+ /* Register the device. cros_ec_init_keyboard() will be called soon */
+ return input_stdio_register(sdev);
+}
- if (input_init(&config.input, 0)) {
- debug("%s: Cannot set up input\n", __func__);
- return -1;
- }
- config.input.read_keys = cros_ec_kbc_check;
+static const struct keyboard_ops cros_ec_kbd_ops = {
+};
- memset(&dev, '\0', sizeof(dev));
- strcpy(dev.name, "cros-ec-keyb");
- dev.flags = DEV_FLAGS_INPUT;
- dev.getc = kbd_getc;
- dev.tstc = kbd_tstc;
- dev.start = cros_ec_init_keyboard;
+static const struct udevice_id cros_ec_kbd_ids[] = {
+ { .compatible = "google,cros-ec-keyb" },
+ { }
+};
- /* Register the device. cros_ec_init_keyboard() will be called soon */
- return input_stdio_register(&dev);
-}
+U_BOOT_DRIVER(cros_ec_kbd) = {
+ .name = "cros_ec_kbd",
+ .id = UCLASS_KEYBOARD,
+ .of_match = cros_ec_kbd_ids,
+ .probe = cros_ec_kbd_probe,
+ .ops = &cros_ec_kbd_ops,
+ .priv_auto_alloc_size = sizeof(struct cros_ec_keyb_priv),
+};
diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c
index 9b5fa32..661d7fd 100644
--- a/drivers/input/i8042.c
+++ b/drivers/input/i8042.c
@@ -7,257 +7,29 @@
/* i8042.c - Intel 8042 keyboard driver routines */
-/* includes */
-
#include <common.h>
-#include <asm/io.h>
+#include <dm.h>
+#include <errno.h>
#include <i8042.h>
+#include <input.h>
+#include <keyboard.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
/* defines */
#define in8(p) inb(p)
#define out8(p, v) outb(v, p)
-#ifdef CONFIG_CONSOLE_CURSOR
-extern void console_cursor(int state);
-static int blink_count = CONFIG_SYS_CONSOLE_BLINK_COUNT;
-static int cursor_state;
-#endif
+enum {
+ QUIRK_DUP_POR = 1 << 0,
+};
/* locals */
-
-static int kbd_input = -1; /* no input yet */
-static int kbd_mapping = KBD_US; /* default US keyboard */
-static int kbd_flags = NORMAL; /* after reset */
-static int kbd_state; /* unshift code */
-
-static unsigned char kbd_fct_map[144] = {
- /* kbd_fct_map table for scan code */
- 0, AS, AS, AS, AS, AS, AS, AS, /* scan 00-07 */
- AS, AS, AS, AS, AS, AS, AS, AS, /* scan 08-0F */
- AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */
- AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */
- AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */
- AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */
- AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */
- AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */
- ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */
- ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */
- 0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */
- AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */
- AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */
- };
-
-static unsigned char kbd_key_map[2][5][144] = {
- { /* US keyboard */
- { /* unshift code */
- 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */
- '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 08-0F */
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
- 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
- '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
- 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
- '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
- '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* shift code */
- 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 00-07 */
- '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 08-0F */
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */
- 'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */
- '"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */
- 'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
- '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
- '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* control code */
- 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */
- 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 08-0F */
- 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
- 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
- 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
- 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
- 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
- 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
- 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
- },
- { /* non numeric code */
- 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */
- '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 08-0F */
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */
- 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */
- '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */
- 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
- 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
- 'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* right alt mode - not used in US keyboard */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 08-0F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10-17 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18-1F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20-27 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28-2F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30-37 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40-47 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
- }
- },
- { /* German keyboard */
- { /* unshift code */
- 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */
- '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 08-0F */
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
- 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
- 0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */
- 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
- '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
- '2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* shift code */
- 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 00-07 */
- '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 08-0F */
- 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */
- 'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */
- 0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */
- 'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */
- '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
- '2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* control code */
- 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */
- 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 08-0F */
- 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */
- 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */
- 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */
- 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */
- 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */
- 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
- 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
- },
- { /* non numeric code */
- 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */
- '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 08-0F */
- 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
- 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
- 0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */
- 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */
- ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */
- 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */
- 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */
- 'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */
- '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */
- 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */
- },
- { /* right alt mode - is used in German keyboard */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */
- '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 08-0F */
- '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10-17 */
- 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18-1F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20-27 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28-2F */
- 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30-37 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40-47 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50-57 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */
- }
- }
- };
+struct i8042_kbd_priv {
+ bool extended; /* true if an extended keycode is expected next */
+ int quirks; /* quirks that we support */
+};
static unsigned char ext_key_map[] = {
0x1c, /* keypad enter */
@@ -299,209 +71,92 @@ static int kbd_output_full(void)
return kbd_timeout != -1;
}
-static void kbd_led_set(void)
+/**
+ * check_leds() - Check the keyboard LEDs and update them it needed
+ *
+ * @ret: Value to return
+ * @return value of @ret
+ */
+static int i8042_kbd_update_leds(struct udevice *dev, int leds)
{
kbd_input_empty();
out8(I8042_DATA_REG, CMD_SET_KBD_LED);
kbd_input_empty();
- out8(I8042_DATA_REG, (kbd_flags & 0x7));
-}
-
-static void kbd_normal(unsigned char scan_code)
-{
- unsigned char chr;
+ out8(I8042_DATA_REG, leds & 0x7);
- if ((kbd_flags & BRK) == NORMAL) {
- chr = kbd_key_map[kbd_mapping][kbd_state][scan_code];
- if ((chr == 0xff) || (chr == 0x00))
- return;
-
- /* if caps lock convert upper to lower */
- if (((kbd_flags & CAPS) == CAPS) &&
- (chr >= 'a' && chr <= 'z')) {
- chr -= 'a' - 'A';
- }
- kbd_input = chr;
- }
+ return 0;
}
-static void kbd_shift(unsigned char scan_code)
+static int kbd_write(int reg, int value)
{
- if ((kbd_flags & BRK) == BRK) {
- kbd_state = AS;
- kbd_flags &= (~SHIFT);
- } else {
- kbd_state = SH;
- kbd_flags |= SHIFT;
- }
-}
+ if (!kbd_input_empty())
+ return -1;
+ out8(reg, value);
-static void kbd_ctrl(unsigned char scan_code)
-{
- if ((kbd_flags & BRK) == BRK) {
- kbd_state = AS;
- kbd_flags &= (~CTRL);
- } else {
- kbd_state = CN;
- kbd_flags |= CTRL;
- }
+ return 0;
}
-static void kbd_num(unsigned char scan_code)
+static int kbd_read(int reg)
{
- if ((kbd_flags & BRK) == NORMAL) {
- kbd_flags ^= NUM;
- kbd_state = (kbd_flags & NUM) ? AS : NM;
- kbd_led_set();
- }
-}
+ if (!kbd_output_full())
+ return -1;
-static void kbd_alt(unsigned char scan_code)
-{
- if ((kbd_flags & BRK) == BRK) {
- kbd_state = AS;
- kbd_flags &= (~ALT);
- } else {
- kbd_state = AK;
- kbd_flags &= ALT;
- }
+ return in8(reg);
}
-static void kbd_caps(unsigned char scan_code)
+static int kbd_cmd_read(int cmd)
{
- if ((kbd_flags & BRK) == NORMAL) {
- kbd_flags ^= CAPS;
- kbd_led_set();
- }
-}
+ if (kbd_write(I8042_CMD_REG, cmd))
+ return -1;
-static void kbd_scroll(unsigned char scan_code)
-{
- if ((kbd_flags & BRK) == NORMAL) {
- kbd_flags ^= STP;
- kbd_led_set();
- if (kbd_flags & STP)
- kbd_input = 0x13;
- else
- kbd_input = 0x11;
- }
+ return kbd_read(I8042_DATA_REG);
}
-static void kbd_conv_char(unsigned char scan_code)
+static int kbd_cmd_write(int cmd, int data)
{
- if (scan_code == 0xe0) {
- kbd_flags |= EXT;
- return;
- }
-
- /* if high bit of scan_code, set break flag */
- if (scan_code & 0x80)
- kbd_flags |= BRK;
- else
- kbd_flags &= ~BRK;
-
- if ((scan_code == 0xe1) || (kbd_flags & E1)) {
- if (scan_code == 0xe1) {
- kbd_flags ^= BRK; /* reset the break flag */
- kbd_flags ^= E1; /* bitwise EXOR with E1 flag */
- }
- return;
- }
-
- scan_code &= 0x7f;
-
- if (kbd_flags & EXT) {
- int i;
-
- kbd_flags ^= EXT;
- for (i = 0; ext_key_map[i]; i++) {
- if (ext_key_map[i] == scan_code) {
- scan_code = 0x80 + i;
- break;
- }
- }
- /* not found ? */
- if (!ext_key_map[i])
- return;
- }
-
- switch (kbd_fct_map[scan_code]) {
- case AS:
- kbd_normal(scan_code);
- break;
- case SH:
- kbd_shift(scan_code);
- break;
- case CN:
- kbd_ctrl(scan_code);
- break;
- case NM:
- kbd_num(scan_code);
- break;
- case AK:
- kbd_alt(scan_code);
- break;
- case CP:
- kbd_caps(scan_code);
- break;
- case ST:
- kbd_scroll(scan_code);
- break;
- }
+ if (kbd_write(I8042_CMD_REG, cmd))
+ return -1;
- return;
+ return kbd_write(I8042_DATA_REG, data);
}
-static int kbd_reset(void)
+static int kbd_reset(int quirk)
{
- u8 config;
+ int config;
/* controller self test */
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_CMD_REG, CMD_SELF_TEST);
- if (kbd_output_full() == 0)
- return -1;
- if (in8(I8042_DATA_REG) != KBC_TEST_OK)
- return -1;
+ if (kbd_cmd_read(CMD_SELF_TEST) != KBC_TEST_OK)
+ goto err;
/* keyboard reset */
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_DATA_REG, CMD_RESET_KBD);
- if (kbd_output_full() == 0)
- return -1;
- if (in8(I8042_DATA_REG) != KBD_ACK)
- return -1;
- if (kbd_output_full() == 0)
- return -1;
- if (in8(I8042_DATA_REG) != KBD_POR)
- return -1;
+ if (kbd_write(I8042_DATA_REG, CMD_RESET_KBD) ||
+ kbd_read(I8042_DATA_REG) != KBD_ACK ||
+ kbd_read(I8042_DATA_REG) != KBD_POR)
+ goto err;
/* set AT translation and disable irq */
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_CMD_REG, CMD_RD_CONFIG);
- if (kbd_output_full() == 0)
- return -1;
- config = in8(I8042_DATA_REG);
+ config = kbd_cmd_read(CMD_RD_CONFIG);
+ if (config == -1)
+ goto err;
+
+ /* Sometimes get a second byte */
+ else if ((quirk & QUIRK_DUP_POR) && config == KBD_POR)
+ config = kbd_cmd_read(CMD_RD_CONFIG);
+
config |= CONFIG_AT_TRANS;
config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN);
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_CMD_REG, CMD_WR_CONFIG);
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_DATA_REG, config);
+ if (kbd_cmd_write(CMD_WR_CONFIG, config))
+ goto err;
/* enable keyboard */
- if (kbd_input_empty() == 0)
- return -1;
- out8(I8042_CMD_REG, CMD_KBD_EN);
- if (kbd_input_empty() == 0)
- return -1;
+ if (kbd_write(I8042_CMD_REG, CMD_KBD_EN) ||
+ !kbd_input_empty())
+ goto err;
return 0;
+err:
+ debug("%s: Keyboard failure\n", __func__);
+ return -1;
}
static int kbd_controller_present(void)
@@ -512,6 +167,8 @@ static int kbd_controller_present(void)
/*
* Implement a weak default function for boards that optionally
* need to skip the i8042 initialization.
+ *
+ * TODO(sjg@chromium.org): Use device tree for this?
*/
int __weak board_i8042_skip(void)
{
@@ -556,15 +213,59 @@ int i8042_disable(void)
return 0;
}
+static int i8042_kbd_check(struct input_config *input)
+{
+ struct i8042_kbd_priv *priv = dev_get_priv(input->dev);
+
+ if ((in8(I8042_STS_REG) & STATUS_OBF) == 0) {
+ return 0;
+ } else {
+ bool release = false;
+ int scan_code;
+ int i;
+
+ scan_code = in8(I8042_DATA_REG);
+ if (scan_code == 0xfa) {
+ return 0;
+ } else if (scan_code == 0xe0) {
+ priv->extended = true;
+ return 0;
+ }
+ if (scan_code & 0x80) {
+ scan_code &= 0x7f;
+ release = true;
+ }
+ if (priv->extended) {
+ priv->extended = false;
+ for (i = 0; ext_key_map[i]; i++) {
+ if (ext_key_map[i] == scan_code) {
+ scan_code = 0x60 + i;
+ break;
+ }
+ }
+ /* not found ? */
+ if (!ext_key_map[i])
+ return 0;
+ }
+
+ input_add_keycode(input, scan_code, release);
+ return 1;
+ }
+}
+
/* i8042_kbd_init - reset keyboard and init state flags */
-int i8042_kbd_init(void)
+static int i8042_start(struct udevice *dev)
{
+ struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct i8042_kbd_priv *priv = dev_get_priv(dev);
+ struct input_config *input = &uc_priv->input;
int keymap, try;
char *penv;
+ int ret;
if (!kbd_controller_present() || board_i8042_skip()) {
debug("i8042 keyboard controller is not present\n");
- return -1;
+ return -ENOENT;
}
/* Init keyboard device (default US layout) */
@@ -575,81 +276,75 @@ int i8042_kbd_init(void)
keymap = KBD_GER;
}
- for (try = 0; try < KBD_RESET_TRIES; try++) {
- if (kbd_reset() == 0) {
- kbd_mapping = keymap;
- kbd_flags = NORMAL;
- kbd_state = 0;
- kbd_led_set();
-
- return 0;
- }
+ for (try = 0; kbd_reset(priv->quirks) != 0; try++) {
+ if (try >= KBD_RESET_TRIES)
+ return -1;
}
- return -1;
-}
+ ret = input_add_tables(input, keymap == KBD_GER);
+ if (ret)
+ return ret;
-/*
- * i8042_tstc - test if keyboard input is available
- *
- * option: cursor blinking if called in a loop
- */
-int i8042_tstc(struct stdio_dev *dev)
-{
- unsigned char scan_code = 0;
-
-#ifdef CONFIG_CONSOLE_CURSOR
- if (--blink_count == 0) {
- cursor_state ^= 1;
- console_cursor(cursor_state);
- blink_count = CONFIG_SYS_CONSOLE_BLINK_COUNT;
- udelay(10);
- }
-#endif
-
- if ((in8(I8042_STS_REG) & STATUS_OBF) == 0) {
- return 0;
- } else {
- scan_code = in8(I8042_DATA_REG);
- if (scan_code == 0xfa)
- return 0;
-
- kbd_conv_char(scan_code);
-
- if (kbd_input != -1)
- return 1;
- }
+ i8042_kbd_update_leds(dev, NORMAL);
+ debug("%s: started\n", __func__);
return 0;
}
-/*
- * i8042_getc - wait till keyboard input is available
+/**
+ * Set up the i8042 keyboard. This is called by the stdio device handler
*
- * option: turn on/off cursor while waiting
+ * We want to do this init when the keyboard is actually used rather than
+ * at start-up, since keyboard input may not currently be selected.
+ *
+ * Once the keyboard starts there will be a period during which we must
+ * wait for the keyboard to init. We do this only when a key is first
+ * read - see kbd_wait_for_fifo_init().
+ *
+ * @return 0 if ok, -ve on error
*/
-int i8042_getc(struct stdio_dev *dev)
+static int i8042_kbd_probe(struct udevice *dev)
{
- int ret_chr;
- unsigned char scan_code;
-
- while (kbd_input == -1) {
- while ((in8(I8042_STS_REG) & STATUS_OBF) == 0) {
-#ifdef CONFIG_CONSOLE_CURSOR
- if (--blink_count == 0) {
- cursor_state ^= 1;
- console_cursor(cursor_state);
- blink_count = CONFIG_SYS_CONSOLE_BLINK_COUNT;
- }
- udelay(10);
-#endif
- }
- scan_code = in8(I8042_DATA_REG);
- if (scan_code != 0xfa)
- kbd_conv_char(scan_code);
+ struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct i8042_kbd_priv *priv = dev_get_priv(dev);
+ struct stdio_dev *sdev = &uc_priv->sdev;
+ struct input_config *input = &uc_priv->input;
+ int ret;
+
+ if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "intel,duplicate-por"))
+ priv->quirks |= QUIRK_DUP_POR;
+
+ /* Register the device. i8042_start() will be called soon */
+ input->dev = dev;
+ input->read_keys = i8042_kbd_check;
+ input_allow_repeats(input, true);
+ strcpy(sdev->name, "i8042-kbd");
+ ret = input_stdio_register(sdev);
+ if (ret) {
+ debug("%s: input_stdio_register() failed\n", __func__);
+ return ret;
}
- ret_chr = kbd_input;
- kbd_input = -1;
+ debug("%s: ready\n", __func__);
- return ret_chr;
+ return 0;
}
+
+static const struct keyboard_ops i8042_kbd_ops = {
+ .start = i8042_start,
+ .update_leds = i8042_kbd_update_leds,
+};
+
+static const struct udevice_id i8042_kbd_ids[] = {
+ { .compatible = "intel,i8042-keyboard" },
+ { }
+};
+
+U_BOOT_DRIVER(i8042_kbd) = {
+ .name = "i8042_kbd",
+ .id = UCLASS_KEYBOARD,
+ .of_match = i8042_kbd_ids,
+ .probe = i8042_kbd_probe,
+ .ops = &i8042_kbd_ops,
+ .priv_auto_alloc_size = sizeof(struct i8042_kbd_priv),
+};
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 007b855..011667f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -8,15 +8,21 @@
*/
#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <errno.h>
#include <stdio_dev.h>
#include <input.h>
+#ifdef CONFIG_DM_KEYBOARD
+#include <keyboard.h>
+#endif
#include <linux/input.h>
enum {
/* These correspond to the lights on the keyboard */
- FLAG_NUM_LOCK = 1 << 0,
- FLAG_CAPS_LOCK = 1 << 1,
- FLAG_SCROLL_LOCK = 1 << 2,
+ FLAG_SCROLL_LOCK = 1 << 0,
+ FLAG_NUM_LOCK = 1 << 1,
+ FLAG_CAPS_LOCK = 1 << 2,
/* Special flag ORed with key code to indicate release */
KEY_RELEASE = 1 << 15,
@@ -42,7 +48,7 @@ static const uchar kbd_plain_xlate[] = {
'8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
'2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50 - 0x5F */
- '\r', 0xff, 0xff
+ '\r', 0xff, '/', '*',
};
static unsigned char kbd_shift_xlate[] = {
@@ -58,13 +64,13 @@ static unsigned char kbd_shift_xlate[] = {
'8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
'2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50 - 0x5F */
- '\r', 0xff, 0xff
+ '\r', 0xff, '/', '*',
};
static unsigned char kbd_ctrl_xlate[] = {
0xff, 0x1b, '1', 0x00, '3', '4', '5', 0x1E,
'7', '8', '9', '0', 0x1F, '=', '\b', '\t', /* 0x00 - 0x0f */
- 0x11, 0x17, 0x05, 0x12, 0x14, 0x18, 0x15, 0x09,
+ 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09,
0x0f, 0x10, 0x1b, 0x1d, '\n', 0xff, 0x01, 0x13, /* 0x10 - 0x1f */
0x04, 0x06, 0x08, 0x09, 0x0a, 0x0b, 0x0c, ';',
'\'', '~', 0x00, 0x1c, 0x1a, 0x18, 0x03, 0x16, /* 0x20 - 0x2f */
@@ -74,7 +80,89 @@ static unsigned char kbd_ctrl_xlate[] = {
'8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
'2', '3', '0', '.', 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50 - 0x5F */
- '\r', 0xff, 0xff
+ '\r', 0xff, '/', '*',
+};
+
+static const uchar kbd_plain_xlate_german[] = {
+ 0xff, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */
+ '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 08-0F */
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */
+ 'o', 'p', 0x81, '+', '\r', 0xff, 'a', 's', /* scan 18-1F */
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */
+ 0x84, '^', 0xff, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */
+ 'b', 'n', 'm', ',', '.', '-', 0xff, '*', /* scan 30-37 */
+ ' ', ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', ',', 0xff, 0xff, '<', 0xff, /* scan 50-57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
+ '\r', 0xff, '/', '*',
+};
+
+static unsigned char kbd_shift_xlate_german[] = {
+ 0xff, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 00-07 */
+ '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 08-0F */
+ 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */
+ 'O', 'P', 0x9a, '*', '\r', 0xff, 'A', 'S', /* scan 18-1F */
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */
+ 0x8e, 0xf8, 0xff, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */
+ 'B', 'N', 'M', ';', ':', '_', 0xff, '*', /* scan 30-37 */
+ ' ', ' ', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '7', /* scan 40-47 */
+ '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */
+ '2', '3', '0', ',', 0xff, 0xff, '>', 0xff, /* scan 50-57 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */
+ '\r', 0xff, '/', '*',
+};
+
+static unsigned char kbd_right_alt_xlate_german[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */
+ '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 08-0F */
+ '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10-17 */
+ 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18-1F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20-27 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28-2F */
+ 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30-37 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40-47 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50-57 */
+};
+
+enum kbd_mask {
+ KBD_ENGLISH = 1 << 0,
+ KBD_GERMAN = 1 << 1,
+};
+
+static struct kbd_entry {
+ int kbd_mask; /* Which languages this is for */
+ int left_keycode; /* Left keycode to select this map */
+ int right_keycode; /* Right keycode to select this map */
+ const uchar *xlate; /* Ascii code for each keycode */
+ int num_entries; /* Number of entries in xlate */
+} kbd_entry[] = {
+ { KBD_ENGLISH, -1, -1,
+ kbd_plain_xlate, ARRAY_SIZE(kbd_plain_xlate) },
+ { KBD_GERMAN, -1, -1,
+ kbd_plain_xlate_german, ARRAY_SIZE(kbd_plain_xlate_german) },
+ { KBD_ENGLISH, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
+ kbd_shift_xlate, ARRAY_SIZE(kbd_shift_xlate) },
+ { KBD_GERMAN, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
+ kbd_shift_xlate_german, ARRAY_SIZE(kbd_shift_xlate_german) },
+ { KBD_ENGLISH | KBD_GERMAN, KEY_LEFTCTRL, KEY_RIGHTCTRL,
+ kbd_ctrl_xlate, ARRAY_SIZE(kbd_ctrl_xlate) },
+ { KBD_GERMAN, -1, KEY_RIGHTALT,
+ kbd_right_alt_xlate_german,
+ ARRAY_SIZE(kbd_right_alt_xlate_german) },
+ {},
};
/*
@@ -106,6 +194,7 @@ static int input_queue_ascii(struct input_config *config, int ch)
return -1; /* buffer full */
config->fifo_in++;
}
+ debug(" {%02x} ", ch);
config->fifo[config->fifo_in] = (uchar)ch;
return 0;
@@ -151,8 +240,11 @@ int input_getc(struct input_config *config)
static struct input_key_xlate *process_modifier(struct input_config *config,
int key, int release)
{
+#ifdef CONFIG_DM_KEYBOARD
+ struct udevice *dev = config->dev;
+ struct keyboard_ops *ops = keyboard_get_ops(dev);
+#endif
struct input_key_xlate *table;
- int flip = -1;
int i;
/* Start with the main table, and see what modifiers change it */
@@ -167,6 +259,8 @@ static struct input_key_xlate *process_modifier(struct input_config *config,
/* Handle the lighted keys */
if (!release) {
+ int flip = -1;
+
switch (key) {
case KEY_SCROLLLOCK:
flip = FLAG_SCROLL_LOCK;
@@ -178,19 +272,27 @@ static struct input_key_xlate *process_modifier(struct input_config *config,
flip = FLAG_CAPS_LOCK;
break;
}
- }
- if (flip != -1) {
- int leds = 0;
-
- config->leds ^= flip;
- if (config->flags & FLAG_NUM_LOCK)
- leds |= INPUT_LED_NUM;
- if (config->flags & FLAG_CAPS_LOCK)
- leds |= INPUT_LED_CAPS;
- if (config->flags & FLAG_SCROLL_LOCK)
- leds |= INPUT_LED_SCROLL;
- config->leds = leds;
+ if (flip != -1) {
+ int leds = 0;
+
+ config->flags ^= flip;
+ if (config->flags & FLAG_NUM_LOCK)
+ leds |= INPUT_LED_NUM;
+ if (config->flags & FLAG_CAPS_LOCK)
+ leds |= INPUT_LED_CAPS;
+ if (config->flags & FLAG_SCROLL_LOCK)
+ leds |= INPUT_LED_SCROLL;
+ config->leds = leds;
+ config->leds_changed = flip;
+
+#ifdef CONFIG_DM_KEYBOARD
+ if (ops->update_leds) {
+ if (ops->update_leds(dev, config->leds))
+ debug("Update keyboard's LED failed\n");
+ }
+#endif
+ }
}
return table;
@@ -367,16 +469,25 @@ static int input_keycodes_to_ascii(struct input_config *config,
/* Start conversion by looking for the first new keycode (by same). */
for (i = same; i < num_keycodes; i++) {
int key = keycode[i];
- int ch = (key < table->num_entries) ? table->xlate[key] : 0xff;
+ int ch;
/*
* For a normal key (with an ASCII value), add it; otherwise
* translate special key to escape sequence if possible.
*/
- if (ch != 0xff) {
- if (ch_count < max_chars)
- output_ch[ch_count] = (uchar)ch;
- ch_count++;
+ if (key < table->num_entries) {
+ ch = table->xlate[key];
+ if ((config->flags & FLAG_CAPS_LOCK) &&
+ ch >= 'a' && ch <= 'z')
+ ch -= 'a' - 'A';
+ /* ban digit numbers if 'Num Lock' is not on */
+ if (!(config->flags & FLAG_NUM_LOCK)) {
+ if (key >= KEY_KP7 && key <= KEY_KPDOT &&
+ key != KEY_KPMINUS && key != KEY_KPPLUS)
+ ch = 0xff;
+ }
+ if (ch_count < max_chars && ch != 0xff)
+ output_ch[ch_count++] = (uchar)ch;
} else {
ch_count += input_keycode_to_ansi364(config, key,
output_ch, max_chars);
@@ -393,8 +504,8 @@ static int input_keycodes_to_ascii(struct input_config *config,
return ch_count;
}
-int input_send_keycodes(struct input_config *config,
- int keycode[], int num_keycodes)
+static int _input_send_keycodes(struct input_config *config, int keycode[],
+ int num_keycodes, bool do_send)
{
char ch[num_keycodes * ANSI_CHAR_MAX];
int count, i, same = 0;
@@ -411,16 +522,18 @@ int input_send_keycodes(struct input_config *config,
* insert another character if we later realise that we
* have missed a repeat slot.
*/
- is_repeat = config->repeat_rate_ms &&
- (int)get_timer(config->next_repeat_ms) >= 0;
+ is_repeat = config->allow_repeats || (config->repeat_rate_ms &&
+ (int)get_timer(config->next_repeat_ms) >= 0);
if (!is_repeat)
return 0;
}
count = input_keycodes_to_ascii(config, keycode, num_keycodes,
ch, sizeof(ch), is_repeat ? 0 : same);
- for (i = 0; i < count; i++)
- input_queue_ascii(config, ch[i]);
+ if (do_send) {
+ for (i = 0; i < count; i++)
+ input_queue_ascii(config, ch[i]);
+ }
delay_ms = is_repeat ?
config->repeat_rate_ms :
config->repeat_delay_ms;
@@ -430,6 +543,41 @@ int input_send_keycodes(struct input_config *config,
return count;
}
+int input_send_keycodes(struct input_config *config, int keycode[],
+ int num_keycodes)
+{
+ return _input_send_keycodes(config, keycode, num_keycodes, true);
+}
+
+int input_add_keycode(struct input_config *config, int new_keycode,
+ bool release)
+{
+ int keycode[INPUT_MAX_MODIFIERS + 1];
+ int count, i;
+
+ /* Add the old keycodes which are not removed by this new one */
+ for (i = 0, count = 0; i < config->num_prev_keycodes; i++) {
+ int code = config->prev_keycodes[i];
+
+ if (new_keycode == code) {
+ if (release)
+ continue;
+ new_keycode = -1;
+ }
+ keycode[count++] = code;
+ }
+
+ if (!release && new_keycode != -1)
+ keycode[count++] = new_keycode;
+ debug("\ncodes for %02x/%d: ", new_keycode, release);
+ for (i = 0; i < count; i++)
+ debug("%02x ", keycode[i]);
+ debug("\n");
+
+ /* Don't output any ASCII characters if this is a key release */
+ return _input_send_keycodes(config, keycode, count, !release);
+}
+
int input_add_table(struct input_config *config, int left_keycode,
int right_keycode, const uchar *xlate, int num_entries)
{
@@ -456,19 +604,43 @@ void input_set_delays(struct input_config *config, int repeat_delay_ms,
config->repeat_rate_ms = repeat_rate_ms;
}
+void input_allow_repeats(struct input_config *config, bool allow_repeats)
+{
+ config->allow_repeats = allow_repeats;
+}
+
+int input_leds_changed(struct input_config *config)
+{
+ if (config->leds_changed)
+ return config->leds;
+
+ return -1;
+}
+
+int input_add_tables(struct input_config *config, bool german)
+{
+ struct kbd_entry *entry;
+ int mask;
+ int ret;
+
+ mask = german ? KBD_GERMAN : KBD_ENGLISH;
+ for (entry = kbd_entry; entry->kbd_mask; entry++) {
+ if (!(mask & entry->kbd_mask))
+ continue;
+ ret = input_add_table(config, entry->left_keycode,
+ entry->right_keycode, entry->xlate,
+ entry->num_entries);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int input_init(struct input_config *config, int leds)
{
memset(config, '\0', sizeof(*config));
config->leds = leds;
- if (input_add_table(config, -1, -1,
- kbd_plain_xlate, ARRAY_SIZE(kbd_plain_xlate)) ||
- input_add_table(config, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
- kbd_shift_xlate, ARRAY_SIZE(kbd_shift_xlate)) ||
- input_add_table(config, KEY_LEFTCTRL, KEY_RIGHTCTRL,
- kbd_ctrl_xlate, ARRAY_SIZE(kbd_ctrl_xlate))) {
- debug("%s: Could not add modifier tables\n", __func__);
- return -1;
- }
return 0;
}
diff --git a/drivers/input/keyboard-uclass.c b/drivers/input/keyboard-uclass.c
new file mode 100644
index 0000000..e2ce25c
--- /dev/null
+++ b/drivers/input/keyboard-uclass.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <keyboard.h>
+
+static int keyboard_start(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct keyboard_ops *ops = keyboard_get_ops(dev);
+
+ if (ops->start)
+ return ops->start(dev);
+
+ return 0;
+}
+
+static int keyboard_stop(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct keyboard_ops *ops = keyboard_get_ops(dev);
+
+ if (ops->stop)
+ return ops->stop(dev);
+
+ return 0;
+}
+
+static int keyboard_tstc(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct keyboard_priv *priv = dev_get_uclass_priv(dev);
+ struct keyboard_ops *ops = keyboard_get_ops(dev);
+
+ /* Just get input to do this for us if we can */
+ if (priv->input.dev)
+ return input_tstc(&priv->input);
+ else if (ops->tstc)
+ return ops->tstc(dev);
+
+ return -ENOSYS;
+}
+
+static int keyboard_getc(struct stdio_dev *sdev)
+{
+ struct udevice *dev = sdev->priv;
+ struct keyboard_priv *priv = dev_get_uclass_priv(dev);
+ struct keyboard_ops *ops = keyboard_get_ops(dev);
+
+ /* Just get input to do this for us if we can */
+ if (priv->input.dev)
+ return input_getc(&priv->input);
+ else if (ops->getc)
+ return ops->getc(dev);
+
+ return -ENOSYS;
+}
+
+static int keyboard_pre_probe(struct udevice *dev)
+{
+ struct keyboard_priv *priv = dev_get_uclass_priv(dev);
+ struct stdio_dev *sdev = &priv->sdev;
+ int ret;
+
+ strlcpy(sdev->name, dev->name, sizeof(sdev->name));
+ sdev->flags = DEV_FLAGS_INPUT;
+ sdev->getc = keyboard_getc;
+ sdev->tstc = keyboard_tstc;
+ sdev->start = keyboard_start;
+ sdev->stop = keyboard_stop;
+ sdev->priv = dev;
+ ret = input_init(&priv->input, 0);
+ if (ret) {
+ debug("%s: Cannot set up input, ret=%d - please add DEBUG to drivers/input/input.c to figure out the cause\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+UCLASS_DRIVER(keyboard) = {
+ .id = UCLASS_KEYBOARD,
+ .name = "keyboard",
+ .pre_probe = keyboard_pre_probe,
+ .per_device_auto_alloc_size = sizeof(struct keyboard_priv),
+};
diff --git a/drivers/input/keyboard.c b/drivers/input/keyboard.c
index ca3886a..48255bd 100644
--- a/drivers/input/keyboard.c
+++ b/drivers/input/keyboard.c
@@ -9,290 +9,79 @@
***********************************************************************/
#include <common.h>
+#include <console.h>
+#include <input.h>
#include <stdio_dev.h>
#include <keyboard.h>
+#include <stdio_dev.h>
-#undef KBG_DEBUG
-
-#ifdef KBG_DEBUG
-#define PRINTF(fmt,args...) printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
-
-#define DEVNAME "kbd"
-
-#define LED_SCR 0x01 /* scroll lock led */
-#define LED_CAP 0x04 /* caps lock led */
-#define LED_NUM 0x02 /* num lock led */
-
-#define KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */
+static struct input_config config;
-#if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
-int ps2ser_check(void);
+static int kbd_read_keys(struct input_config *config)
+{
+#if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8540) || \
+ defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
+ /* no ISR is used, so received chars must be polled */
+ ps2ser_check();
#endif
-static volatile char kbd_buffer[KBD_BUFFER_LEN];
-static volatile int in_pointer = 0;
-static volatile int out_pointer = 0;
+ return 1;
+}
-static unsigned char leds = 0;
-static unsigned char num_lock = 0;
-static unsigned char caps_lock = 0;
-static unsigned char scroll_lock = 0;
-static unsigned char shift = 0;
-static unsigned char ctrl = 0;
-static unsigned char alt = 0;
-static unsigned char e0 = 0;
+static int check_leds(int ret)
+{
+ int leds;
-/******************************************************************
- * Queue handling
- ******************************************************************/
+ leds = input_leds_changed(&config);
+ if (leds >= 0)
+ pckbd_leds(leds);
-/* puts character in the queue and sets up the in and out pointer */
-static void kbd_put_queue(char data)
-{
- if((in_pointer+1)==KBD_BUFFER_LEN) {
- if(out_pointer==0) {
- return; /* buffer full */
- } else{
- in_pointer=0;
- }
- } else {
- if((in_pointer+1)==out_pointer)
- return; /* buffer full */
- in_pointer++;
- }
- kbd_buffer[in_pointer]=data;
- return;
+ return ret;
}
/* test if a character is in the queue */
static int kbd_testc(struct stdio_dev *dev)
{
-#if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
- /* no ISR is used, so received chars must be polled */
- ps2ser_check();
-#endif
- if(in_pointer==out_pointer)
- return(0); /* no data */
- else
- return(1);
+ return check_leds(input_tstc(&config));
}
/* gets the character from the queue */
static int kbd_getc(struct stdio_dev *dev)
{
- char c;
- while(in_pointer==out_pointer) {
-#if defined(CONFIG_MPC5xxx) || defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
- /* no ISR is used, so received chars must be polled */
- ps2ser_check();
-#endif
- ;}
- if((out_pointer+1)==KBD_BUFFER_LEN)
- out_pointer=0;
- else
- out_pointer++;
- c=kbd_buffer[out_pointer];
- return (int)c;
-
+ return check_leds(input_getc(&config));
}
-/* Simple translation table for the keys */
-
-static unsigned char kbd_plain_xlate[] = {
- 0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', /* 0x00 - 0x0f */
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's', /* 0x10 - 0x1f */
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */
- 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
- '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
- '\r',0xff,0xff
- };
-
-static unsigned char kbd_shift_xlate[] = {
- 0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', /* 0x00 - 0x0f */
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S', /* 0x10 - 0x1f */
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V', /* 0x20 - 0x2f */
- 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
- '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
- '\r',0xff,0xff
- };
-
-static unsigned char kbd_ctrl_xlate[] = {
- 0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t', /* 0x00 - 0x0f */
- 0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13, /* 0x10 - 0x1f */
- 0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16, /* 0x20 - 0x2f */
- 0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
- '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
- '\r',0xff,0xff
- };
-
-
-void handle_scancode(unsigned char scancode)
+void handle_scancode(unsigned char scan_code)
{
- unsigned char keycode;
+ bool release = false;
- /* Convert scancode to keycode */
- PRINTF("scancode %x\n",scancode);
- if(scancode==0xe0) {
- e0=1; /* special charakters */
- return;
- }
- if(e0==1) {
- e0=0; /* delete flag */
- if(!( ((scancode&0x7F)==0x38)|| /* the right ctrl key */
- ((scancode&0x7F)==0x1D)|| /* the right alt key */
- ((scancode&0x7F)==0x35)|| /* the right '/' key */
- ((scancode&0x7F)==0x1C) )) /* the right enter key */
- /* we swallow unknown e0 codes */
- return;
- }
- /* special cntrl keys */
- switch(scancode) {
- case 0x2A:
- case 0x36: /* shift pressed */
- shift=1;
- return; /* do nothing else */
- case 0xAA:
- case 0xB6: /* shift released */
- shift=0;
- return; /* do nothing else */
- case 0x38: /* alt pressed */
- alt=1;
- return; /* do nothing else */
- case 0xB8: /* alt released */
- alt=0;
- return; /* do nothing else */
- case 0x1d: /* ctrl pressed */
- ctrl=1;
- return; /* do nothing else */
- case 0x9d: /* ctrl released */
- ctrl=0;
- return; /* do nothing else */
- case 0x46: /* scrollock pressed */
- scroll_lock=~scroll_lock;
- if(scroll_lock==0)
- leds&=~LED_SCR; /* switch LED off */
- else
- leds|=LED_SCR; /* switch on LED */
- pckbd_leds(leds);
- return; /* do nothing else */
- case 0x3A: /* capslock pressed */
- caps_lock=~caps_lock;
- if(caps_lock==0)
- leds&=~LED_CAP; /* switch caps_lock off */
- else
- leds|=LED_CAP; /* switch on LED */
- pckbd_leds(leds);
- return;
- case 0x45: /* numlock pressed */
- num_lock=~num_lock;
- if(num_lock==0)
- leds&=~LED_NUM; /* switch LED off */
- else
- leds|=LED_NUM; /* switch on LED */
- pckbd_leds(leds);
- return;
- case 0xC6: /* scroll lock released */
- case 0xC5: /* num lock released */
- case 0xBA: /* caps lock released */
- return; /* just swallow */
- }
-#if 1
- if((scancode&0x80)==0x80) /* key released */
- return;
-#else
- if((scancode&0x80)==0x00) /* key pressed */
- return;
- scancode &= ~0x80;
-#endif
- /* now, decide which table we need */
- if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */
- PRINTF("unkown scancode %X\n",scancode);
- return; /* swallow it */
- }
- /* setup plain code first */
- keycode=kbd_plain_xlate[scancode];
- if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */
- if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
- PRINTF("unkown caps-locked scancode %X\n",scancode);
- return; /* swallow it */
- }
- keycode=kbd_shift_xlate[scancode];
- if(keycode<'A') { /* we only want the alphas capital */
- keycode=kbd_plain_xlate[scancode];
- }
- }
- if(shift==1) { /* shift overwrites caps_lock */
- if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
- PRINTF("unkown shifted scancode %X\n",scancode);
- return; /* swallow it */
- }
- keycode=kbd_shift_xlate[scancode];
- }
- if(ctrl==1) { /* ctrl overwrites caps_lock and shift */
- if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */
- PRINTF("unkown ctrl scancode %X\n",scancode);
- return; /* swallow it */
- }
- keycode=kbd_ctrl_xlate[scancode];
- }
- /* check if valid keycode */
- if(keycode==0xff) {
- PRINTF("unkown scancode %X\n",scancode);
- return; /* swallow unknown codes */
+ /* Compare with i8042_kbd_check() in i8042.c if some logic is missing */
+ if (scan_code & 0x80) {
+ scan_code &= 0x7f;
+ release = true;
}
- kbd_put_queue(keycode);
- PRINTF("%x\n",keycode);
+ input_add_keycode(&config, scan_code, release);
}
-/******************************************************************
- * Init
- ******************************************************************/
-
-#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
-extern int overwrite_console (void);
-#define OVERWRITE_CONSOLE overwrite_console ()
-#else
-#define OVERWRITE_CONSOLE 0
-#endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
-
+/* TODO: convert to driver model */
int kbd_init (void)
{
- int error;
- struct stdio_dev kbddev ;
- char *stdinname = getenv ("stdin");
+ struct stdio_dev kbddev;
+ struct input_config *input = &config;
if(kbd_init_hw()==-1)
return -1;
memset (&kbddev, 0, sizeof(kbddev));
- strcpy(kbddev.name, DEVNAME);
+ strcpy(kbddev.name, "kbd");
kbddev.flags = DEV_FLAGS_INPUT;
- kbddev.getc = kbd_getc ;
- kbddev.tstc = kbd_testc ;
+ kbddev.getc = kbd_getc;
+ kbddev.tstc = kbd_testc;
- error = stdio_register (&kbddev);
- if(error==0) {
- /* check if this is the standard input device */
- if(strcmp(stdinname,DEVNAME)==0) {
- /* reassign the console */
- if(OVERWRITE_CONSOLE) {
- return 1;
- }
- error=console_assign(stdin,DEVNAME);
- if(error==0)
- return 1;
- else
- return error;
- }
- return 1;
- }
- return error;
+ input_init(input, 0);
+ input->read_keys = kbd_read_keys;
+ input_add_tables(input, true);
+
+ return input_stdio_register(&kbddev);
}
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index 6b88db4..951cbb4 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -6,8 +6,10 @@
*/
#include <common.h>
+#include <dm.h>
#include <fdtdec.h>
#include <input.h>
+#include <keyboard.h>
#include <key_matrix.h>
#include <stdio_dev.h>
#include <tegra-kbc.h>
@@ -40,14 +42,13 @@ enum {
};
/* keyboard controller config and state */
-static struct keyb {
- struct input_config input; /* The input layer */
+struct tegra_kbd_priv {
+ struct input_config *input; /* The input layer */
struct key_matrix matrix; /* The key matrix layer */
struct kbc_tegra *kbc; /* tegra keyboard controller */
unsigned char inited; /* 1 if keyboard has been inited */
unsigned char first_scan; /* 1 if this is our first key scan */
- unsigned char created; /* 1 if driver has been created */
/*
* After init we must wait a short time before polling the keyboard.
@@ -58,17 +59,17 @@ static struct keyb {
unsigned int start_time_ms; /* Time that we inited (in ms) */
unsigned int last_poll_ms; /* Time we should last polled */
unsigned int next_repeat_ms; /* Next time we repeat a key */
-} config;
+};
/**
* reads the keyboard fifo for current keypresses
*
- * @param config Keyboard config
+ * @param priv Keyboard private data
* @param fifo Place to put fifo results
* @param max_keycodes Maximum number of key codes to put in the fifo
* @return number of items put into fifo
*/
-static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
+static int tegra_kbc_find_keys(struct tegra_kbd_priv *priv, int *fifo,
int max_keycodes)
{
struct key_matrix_key keys[KBC_MAX_KPENT], *key;
@@ -78,7 +79,7 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
for (key = keys, i = 0; i < KBC_MAX_KPENT; i++, key++) {
/* Get next word */
if (!(i & 3))
- kp_ent = readl(&config->kbc->kp_ent[i / 4]);
+ kp_ent = readl(&priv->kbc->kp_ent[i / 4]);
key->valid = (kp_ent & KBC_KPENT_VALID) != 0;
key->row = (kp_ent >> 3) & 0xf;
@@ -87,7 +88,7 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
/* Shift to get next entry */
kp_ent >>= 8;
}
- return key_matrix_decode(&config->matrix, keys, KBC_MAX_KPENT, fifo,
+ return key_matrix_decode(&priv->matrix, keys, KBC_MAX_KPENT, fifo,
max_keycodes);
}
@@ -106,10 +107,10 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
* Note: if fifo_cnt is 0, we will tell the input layer that no keys are
* pressed.
*
- * @param config Keyboard config
+ * @param priv Keyboard private data
* @param fifo_cnt Number of entries in the keyboard fifo
*/
-static void process_fifo(struct keyb *config, int fifo_cnt)
+static void process_fifo(struct tegra_kbd_priv *priv, int fifo_cnt)
{
int fifo[KBC_MAX_KPENT];
int cnt = 0;
@@ -117,9 +118,9 @@ static void process_fifo(struct keyb *config, int fifo_cnt)
/* Always call input_send_keycodes() at least once */
do {
if (fifo_cnt)
- cnt = tegra_kbc_find_keys(config, fifo, KBC_MAX_KPENT);
+ cnt = tegra_kbc_find_keys(priv, fifo, KBC_MAX_KPENT);
- input_send_keycodes(&config->input, fifo, cnt);
+ input_send_keycodes(priv->input, fifo, cnt);
} while (--fifo_cnt > 0);
}
@@ -127,24 +128,24 @@ static void process_fifo(struct keyb *config, int fifo_cnt)
* Check the keyboard controller and emit ASCII characters for any keys that
* are pressed.
*
- * @param config Keyboard config
+ * @param priv Keyboard private data
*/
-static void check_for_keys(struct keyb *config)
+static void check_for_keys(struct tegra_kbd_priv *priv)
{
int fifo_cnt;
- if (!config->first_scan &&
- get_timer(config->last_poll_ms) < KBC_REPEAT_RATE_MS)
+ if (!priv->first_scan &&
+ get_timer(priv->last_poll_ms) < KBC_REPEAT_RATE_MS)
return;
- config->last_poll_ms = get_timer(0);
- config->first_scan = 0;
+ priv->last_poll_ms = get_timer(0);
+ priv->first_scan = 0;
/*
* Once we get here we know the keyboard has been scanned. So if there
* scan waiting for us, we know that nothing is held down.
*/
- fifo_cnt = (readl(&config->kbc->interrupt) >> 4) & 0xf;
- process_fifo(config, fifo_cnt);
+ fifo_cnt = (readl(&priv->kbc->interrupt) >> 4) & 0xf;
+ process_fifo(priv, fifo_cnt);
}
/**
@@ -153,22 +154,22 @@ static void check_for_keys(struct keyb *config)
* Wkup mode to Continous polling mode and the repoll time. We can
* deduct the time that's already elapsed.
*
- * @param config Keyboard config
+ * @param priv Keyboard private data
*/
-static void kbd_wait_for_fifo_init(struct keyb *config)
+static void kbd_wait_for_fifo_init(struct tegra_kbd_priv *priv)
{
- if (!config->inited) {
+ if (!priv->inited) {
unsigned long elapsed_time;
long delay_ms;
- elapsed_time = get_timer(config->start_time_ms);
- delay_ms = config->init_dly_ms - elapsed_time;
+ elapsed_time = get_timer(priv->start_time_ms);
+ delay_ms = priv->init_dly_ms - elapsed_time;
if (delay_ms > 0) {
udelay(delay_ms * 1000);
debug("%s: delay %ldms\n", __func__, delay_ms);
}
- config->inited = 1;
+ priv->inited = 1;
}
}
@@ -183,38 +184,16 @@ static void kbd_wait_for_fifo_init(struct keyb *config)
*/
static int tegra_kbc_check(struct input_config *input)
{
- kbd_wait_for_fifo_init(&config);
- check_for_keys(&config);
+ struct tegra_kbd_priv *priv = dev_get_priv(input->dev);
- return 1;
-}
+ kbd_wait_for_fifo_init(priv);
+ check_for_keys(priv);
-/**
- * Test if keys are available to be read
- *
- * @return 0 if no keys available, 1 if keys are available
- */
-static int kbd_tstc(struct stdio_dev *dev)
-{
- /* Just get input to do this for us */
- return input_tstc(&config.input);
-}
-
-/**
- * Read a key
- *
- * TODO: U-Boot wants 0 for no key, but Ctrl-@ is a valid key...
- *
- * @return ASCII key code, or 0 if no key, or -1 if error
- */
-static int kbd_getc(struct stdio_dev *dev)
-{
- /* Just get input to do this for us */
- return input_getc(&config.input);
+ return 1;
}
/* configures keyboard GPIO registers to use the rows and columns */
-static void config_kbc_gpio(struct kbc_tegra *kbc)
+static void config_kbc_gpio(struct tegra_kbd_priv *priv, struct kbc_tegra *kbc)
{
int i;
@@ -233,10 +212,10 @@ static void config_kbc_gpio(struct kbc_tegra *kbc)
row_cfg &= ~r_mask;
col_cfg &= ~c_mask;
- if (i < config.matrix.num_rows) {
+ if (i < priv->matrix.num_rows) {
row_cfg |= ((i << 1) | 1) << r_shift;
} else {
- col_cfg |= (((i - config.matrix.num_rows) << 1) | 1)
+ col_cfg |= (((i - priv->matrix.num_rows) << 1) | 1)
<< c_shift;
}
@@ -248,9 +227,9 @@ static void config_kbc_gpio(struct kbc_tegra *kbc)
/**
* Start up the keyboard device
*/
-static void tegra_kbc_open(void)
+static void tegra_kbc_open(struct tegra_kbd_priv *priv)
{
- struct kbc_tegra *kbc = config.kbc;
+ struct kbc_tegra *kbc = priv->kbc;
unsigned int scan_period;
u32 val;
@@ -265,16 +244,32 @@ static void tegra_kbc_open(void)
* Before reading from the keyboard we must wait for the init_dly
* plus the rpt_delay, plus 2ms for the row scan time.
*/
- config.init_dly_ms = scan_period * 2 + 2;
+ priv->init_dly_ms = scan_period * 2 + 2;
val = KBC_DEBOUNCE_COUNT << KBC_DEBOUNCE_CNT_SHIFT;
val |= 1 << KBC_FIFO_TH_CNT_SHIFT; /* fifo interrupt threshold */
val |= KBC_CONTROL_KBC_EN; /* enable */
writel(val, &kbc->control);
- config.start_time_ms = get_timer(0);
- config.last_poll_ms = config.next_repeat_ms = get_timer(0);
- config.first_scan = 1;
+ priv->start_time_ms = get_timer(0);
+ priv->last_poll_ms = get_timer(0);
+ priv->next_repeat_ms = priv->last_poll_ms;
+ priv->first_scan = 1;
+}
+
+static int tegra_kbd_start(struct udevice *dev)
+{
+ struct tegra_kbd_priv *priv = dev_get_priv(dev);
+
+ /* Set up pin mux and enable the clock */
+ funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
+ clock_enable(PERIPH_ID_KBC);
+ config_kbc_gpio(priv, priv->kbc);
+
+ tegra_kbc_open(priv);
+ debug("%s: Tegra keyboard ready\n", __func__);
+
+ return 0;
}
/**
@@ -289,88 +284,73 @@ static void tegra_kbc_open(void)
*
* @return 0 if ok, -ve on error
*/
-static int init_tegra_keyboard(struct stdio_dev *dev)
+static int tegra_kbd_probe(struct udevice *dev)
{
- /* check if already created */
- if (config.created)
- return 0;
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- int node;
-
- node = fdtdec_next_compatible(gd->fdt_blob, 0,
- COMPAT_NVIDIA_TEGRA20_KBC);
- if (node < 0) {
- debug("%s: cannot locate keyboard node\n", __func__);
- return node;
- }
- config.kbc = (struct kbc_tegra *)fdtdec_get_addr(gd->fdt_blob,
- node, "reg");
- if ((fdt_addr_t)config.kbc == FDT_ADDR_T_NONE) {
+ struct tegra_kbd_priv *priv = dev_get_priv(dev);
+ struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct stdio_dev *sdev = &uc_priv->sdev;
+ struct input_config *input = &uc_priv->input;
+ int node = dev->of_offset;
+ int ret;
+
+ priv->kbc = (struct kbc_tegra *)dev_get_addr(dev);
+ if ((fdt_addr_t)priv->kbc == FDT_ADDR_T_NONE) {
debug("%s: No keyboard register found\n", __func__);
- return -1;
+ return -EINVAL;
}
- input_set_delays(&config.input, KBC_REPEAT_DELAY_MS,
- KBC_REPEAT_RATE_MS);
+ input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
/* Decode the keyboard matrix information (16 rows, 8 columns) */
- if (key_matrix_init(&config.matrix, 16, 8, 1)) {
- debug("%s: Could not init key matrix\n", __func__);
- return -1;
+ ret = key_matrix_init(&priv->matrix, 16, 8, 1);
+ if (ret) {
+ debug("%s: Could not init key matrix: %d\n", __func__, ret);
+ return ret;
}
- if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
- debug("%s: Could not decode key matrix from fdt\n", __func__);
- return -1;
+ ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
+ if (ret) {
+ debug("%s: Could not decode key matrix from fdt: %d\n",
+ __func__, ret);
+ return ret;
}
- if (config.matrix.fn_keycode) {
- if (input_add_table(&config.input, KEY_FN, -1,
- config.matrix.fn_keycode,
- config.matrix.key_count))
- return -1;
+ if (priv->matrix.fn_keycode) {
+ ret = input_add_table(input, KEY_FN, -1,
+ priv->matrix.fn_keycode,
+ priv->matrix.key_count);
+ if (ret) {
+ debug("%s: input_add_table() failed\n", __func__);
+ return ret;
+ }
}
-#else
-#error "Tegra keyboard driver requires FDT definitions"
-#endif
- /* Set up pin mux and enable the clock */
- funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
- clock_enable(PERIPH_ID_KBC);
- config_kbc_gpio(config.kbc);
-
- tegra_kbc_open();
- config.created = 1;
- debug("%s: Tegra keyboard ready\n", __func__);
+ /* Register the device. init_tegra_keyboard() will be called soon */
+ priv->input = input;
+ input->dev = dev;
+ input->read_keys = tegra_kbc_check;
+ input_add_tables(input, false);
+ strcpy(sdev->name, "tegra-kbc");
+ ret = input_stdio_register(sdev);
+ if (ret) {
+ debug("%s: input_stdio_register() failed\n", __func__);
+ return ret;
+ }
return 0;
}
-int drv_keyboard_init(void)
-{
- struct stdio_dev dev;
- char *stdinname = getenv("stdin");
- int error;
-
- if (input_init(&config.input, 0)) {
- debug("%s: Cannot set up input\n", __func__);
- return -1;
- }
- config.input.read_keys = tegra_kbc_check;
+static const struct keyboard_ops tegra_kbd_ops = {
+ .start = tegra_kbd_start,
+};
- memset(&dev, '\0', sizeof(dev));
- strcpy(dev.name, "tegra-kbc");
- dev.flags = DEV_FLAGS_INPUT;
- dev.getc = kbd_getc;
- dev.tstc = kbd_tstc;
- dev.start = init_tegra_keyboard;
+static const struct udevice_id tegra_kbd_ids[] = {
+ { .compatible = "nvidia,tegra20-kbc" },
+ { }
+};
- /* Register the device. init_tegra_keyboard() will be called soon */
- error = input_stdio_register(&dev);
- if (error)
- return error;
-#ifdef CONFIG_CONSOLE_MUX
- error = iomux_doenv(stdin, stdinname);
- if (error)
- return error;
-#endif
- return 0;
-}
+U_BOOT_DRIVER(tegra_kbd) = {
+ .name = "tegra_kbd",
+ .id = UCLASS_KEYBOARD,
+ .of_match = tegra_kbd_ids,
+ .probe = tegra_kbd_probe,
+ .ops = &tegra_kbd_ops,
+ .priv_auto_alloc_size = sizeof(struct tegra_kbd_priv),
+};
diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c
index 5f85ccf..127121e 100644
--- a/drivers/misc/cbmem_console.c
+++ b/drivers/misc/cbmem_console.c
@@ -16,7 +16,7 @@
*/
#include <common.h>
-
+#include <console.h>
#ifndef CONFIG_SYS_COREBOOT
#error This driver requires coreboot
#endif
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index ba36795..e3229ef 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -358,9 +358,11 @@ static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
return len;
}
-int cros_ec_scan_keyboard(struct cros_ec_dev *dev, struct mbkp_keyscan *scan)
+int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan)
{
- if (ec_command(dev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
+ struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
+
+ if (ec_command(cdev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
sizeof(scan->data)) != sizeof(scan->data))
return -1;
@@ -549,13 +551,15 @@ int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
return 0;
}
-int cros_ec_interrupt_pending(struct cros_ec_dev *dev)
+int cros_ec_interrupt_pending(struct udevice *dev)
{
+ struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
+
/* no interrupt support : always poll */
- if (!dm_gpio_is_valid(&dev->ec_int))
+ if (!dm_gpio_is_valid(&cdev->ec_int))
return -ENOENT;
- return dm_gpio_get_value(&dev->ec_int);
+ return dm_gpio_get_value(&cdev->ec_int);
}
int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info)
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 7509612..98f19a6 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -460,6 +460,7 @@ static int process_cmd(struct ec_state *ec,
len = cros_ec_keyscan(ec, resp_data);
break;
case EC_CMD_ENTERING_MODE:
+ len = 0;
break;
default:
printf(" ** Unknown EC command %#02x\n", req_hdr->command);
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index c69f5d4..e169b77 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -29,7 +29,7 @@ int zynq_sdhci_init(phys_addr_t regbase)
SDHCI_QUIRK_BROKEN_R1B;
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- add_sdhci(host, 52000000, 52000000 >> 9);
+ add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 52000000 >> 9);
return 0;
}
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index e3cb598..39932f4 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -18,6 +18,7 @@
/* #define DEBUG */
#include <common.h>
+#include <console.h>
#include <dm.h>
#include <errno.h>
#include <fdt_support.h>
diff --git a/drivers/mtd/nand/bfin_nand.c b/drivers/mtd/nand/bfin_nand.c
index 7e755e8..7c11868 100644
--- a/drivers/mtd/nand/bfin_nand.c
+++ b/drivers/mtd/nand/bfin_nand.c
@@ -15,6 +15,7 @@
*/
#include <common.h>
+#include <console.h>
#include <asm/io.h>
#ifdef DEBUG
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index ff48b25..cf4e7e1 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -20,4 +20,3 @@ obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
-obj-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
diff --git a/drivers/mtd/spi/eeprom_m95xxx.c b/drivers/mtd/spi/eeprom_m95xxx.c
deleted file mode 100644
index a019939..0000000
--- a/drivers/mtd/spi/eeprom_m95xxx.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2009
- * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <spi.h>
-
-#define SPI_EEPROM_WREN 0x06
-#define SPI_EEPROM_RDSR 0x05
-#define SPI_EEPROM_READ 0x03
-#define SPI_EEPROM_WRITE 0x02
-
-#ifndef CONFIG_DEFAULT_SPI_BUS
-#define CONFIG_DEFAULT_SPI_BUS 0
-#endif
-
-#ifndef CONFIG_DEFAULT_SPI_MODE
-#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0
-#endif
-
-#ifndef CONFIG_SYS_SPI_WRITE_TOUT
-#define CONFIG_SYS_SPI_WRITE_TOUT (5 * CONFIG_SYS_HZ)
-#endif
-
-ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
-{
- struct spi_slave *slave;
- u8 cmd = SPI_EEPROM_READ;
-
- slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
- CONFIG_DEFAULT_SPI_MODE);
- if (!slave)
- return 0;
-
- spi_claim_bus(slave);
-
- /* command */
- if (spi_xfer(slave, 8, &cmd, NULL, SPI_XFER_BEGIN))
- return -1;
-
- /*
- * if alen == 3, addr[0] is the block number, we never use it here.
- * All we need are the lower 16 bits.
- */
- if (alen == 3)
- addr++;
-
- /* address, and data */
- if (spi_xfer(slave, 16, addr, NULL, 0))
- return -1;
- if (spi_xfer(slave, 8 * len, NULL, buffer, SPI_XFER_END))
- return -1;
-
- spi_release_bus(slave);
- spi_free_slave(slave);
- return len;
-}
-
-ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
-{
- struct spi_slave *slave;
- char buf[3];
- ulong start;
-
- slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
- CONFIG_DEFAULT_SPI_MODE);
- if (!slave)
- return 0;
-
- spi_claim_bus(slave);
-
- buf[0] = SPI_EEPROM_WREN;
- if (spi_xfer(slave, 8, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END))
- return -1;
-
- buf[0] = SPI_EEPROM_WRITE;
-
- /* As for reading, drop addr[0] if alen is 3 */
- if (alen == 3) {
- alen--;
- addr++;
- }
-
- memcpy(buf + 1, addr, alen);
- /* command + addr, then data */
- if (spi_xfer(slave, 24, buf, NULL, SPI_XFER_BEGIN))
- return -1;
- if (spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END))
- return -1;
-
- start = get_timer(0);
- do {
- buf[0] = SPI_EEPROM_RDSR;
- buf[1] = 0;
- spi_xfer(slave, 16, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END);
-
- if (!(buf[1] & 1))
- break;
-
- } while (get_timer(start) < CONFIG_SYS_SPI_WRITE_TOUT);
-
- if (buf[1] & 1)
- printf("*** spi_write: Timeout while writing!\n");
-
- spi_release_bus(slave);
- spi_free_slave(slave);
- return len;
-}
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 350e21a..72e0f6b 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -11,6 +11,8 @@
#include <dm/device-internal.h>
#include "sf_internal.h"
+DECLARE_GLOBAL_DATA_PTR;
+
int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf)
{
return sf_get_ops(dev)->read(dev, offset, len, buf);
@@ -72,8 +74,29 @@ int spi_flash_remove(struct udevice *dev)
return device_remove(dev);
}
+static int spi_flash_post_bind(struct udevice *dev)
+{
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ struct dm_spi_flash_ops *ops = sf_get_ops(dev);
+ static int reloc_done;
+
+ if (!reloc_done) {
+ if (ops->read)
+ ops->read += gd->reloc_off;
+ if (ops->write)
+ ops->write += gd->reloc_off;
+ if (ops->erase)
+ ops->erase += gd->reloc_off;
+
+ reloc_done++;
+ }
+#endif
+ return 0;
+}
+
UCLASS_DRIVER(spi_flash) = {
.id = UCLASS_SPI_FLASH,
.name = "spi_flash",
+ .post_bind = spi_flash_post_bind,
.per_device_auto_alloc_size = sizeof(struct spi_flash),
};
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 8793f18..85c8a89 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -64,6 +64,7 @@ enum spi_nor_option_flags {
#define SPI_FLASH_CFI_MFR_SPANSION 0x01
#define SPI_FLASH_CFI_MFR_STMICRO 0x20
#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2
+#define SPI_FLASH_CFI_MFR_SST 0xbf
#define SPI_FLASH_CFI_MFR_WINBOND 0xef
/* Erase commands */
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 384224d..3a56d7f 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -583,7 +583,7 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
}
#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO
+#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs,
u32 *len)
{
@@ -663,8 +663,11 @@ int stm_lock(struct spi_flash *flash, u32 ofs, size_t len)
u8 status_old, status_new;
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
u8 shift = ffs(mask) - 1, pow, val;
+ int ret;
- spi_flash_cmd_read_status(flash, &status_old);
+ ret = spi_flash_cmd_read_status(flash, &status_old);
+ if (ret < 0)
+ return ret;
/* SPI NOR always locks to the end */
if (ofs + len != flash->size) {
@@ -714,8 +717,11 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
uint8_t status_old, status_new;
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
u8 shift = ffs(mask) - 1, pow, val;
+ int ret;
- spi_flash_cmd_read_status(flash, &status_old);
+ ret = spi_flash_cmd_read_status(flash, &status_old);
+ if (ret < 0)
+ return ret;
/* Cannot unlock; would unlock larger region than requested */
if (stm_is_locked_sr(flash, status_old, ofs - flash->erase_size,
@@ -750,4 +756,4 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len)
return 0;
}
-#endif /* CONFIG_SPI_FLASH_STMICRO */
+#endif
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index bc05d30..a619182 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -164,14 +164,15 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
flash->memory_map = spi->memory_map;
flash->dual_flash = flash->spi->option;
+ /* Assign spi flash flags */
+ if (params->flags & SST_WR)
+ flash->flags |= SNOR_F_SST_WR;
+
/* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
flash->write = spi_flash_cmd_write_ops;
#if defined(CONFIG_SPI_FLASH_SST)
- if (params->flags & SST_WR)
- flash->flags |= SNOR_F_SST_WR;
-
- if (params->flags & SNOR_F_SST_WR) {
+ if (flash->flags & SNOR_F_SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
flash->write = sst_write_bp;
else
@@ -184,8 +185,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
/* lock hooks are flash specific - assign them based on idcode0 */
switch (idcode[0]) {
-#ifdef CONFIG_SPI_FLASH_STMICRO
+#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
case SPI_FLASH_CFI_MFR_STMICRO:
+ case SPI_FLASH_CFI_MFR_SST:
flash->flash_lock = stm_lock;
flash->flash_unlock = stm_unlock;
flash->flash_is_locked = stm_is_locked;
diff --git a/drivers/net/e1000_spi.c b/drivers/net/e1000_spi.c
index e7f6826..df72375 100644
--- a/drivers/net/e1000_spi.c
+++ b/drivers/net/e1000_spi.c
@@ -1,4 +1,5 @@
#include <common.h>
+#include <console.h>
#include "e1000.h"
#include <linux/compiler.h>
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index 5ed29ae..24ca52e 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
#include <command.h>
+#include <console.h>
#include <net.h>
#include <phy.h>
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index d096db8..9e4d492 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -24,4 +24,5 @@ obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
obj-$(CONFIG_PHY_REALTEK) += realtek.o
obj-$(CONFIG_PHY_SMSC) += smsc.o
obj-$(CONFIG_PHY_TERANETICS) += teranetics.o
+obj-$(CONFIG_PHY_TI) += ti.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d7364ff..51b5746 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -11,6 +11,7 @@
#include <config.h>
#include <common.h>
+#include <console.h>
#include <dm.h>
#include <malloc.h>
#include <net.h>
@@ -484,6 +485,9 @@ int phy_init(void)
#ifdef CONFIG_PHY_TERANETICS
phy_teranetics_init();
#endif
+#ifdef CONFIG_PHY_TI
+ phy_ti_init();
+#endif
#ifdef CONFIG_PHY_VITESSE
phy_vitesse_init();
#endif
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
new file mode 100644
index 0000000..541a57f
--- /dev/null
+++ b/drivers/net/phy/ti.c
@@ -0,0 +1,200 @@
+/*
+ * TI PHY drivers
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ */
+#include <common.h>
+#include <phy.h>
+
+/* TI DP83867 */
+#define DP83867_DEVADDR 0x1f
+
+#define MII_DP83867_PHYCTRL 0x10
+#define MII_DP83867_MICR 0x12
+#define DP83867_CTRL 0x1f
+
+/* Extended Registers */
+#define DP83867_RGMIICTL 0x0032
+#define DP83867_RGMIIDCTL 0x0086
+
+#define DP83867_SW_RESET BIT(15)
+#define DP83867_SW_RESTART BIT(14)
+
+/* MICR Interrupt bits */
+#define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15)
+#define MII_DP83867_MICR_SPEED_CHNG_INT_EN BIT(14)
+#define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN BIT(13)
+#define MII_DP83867_MICR_PAGE_RXD_INT_EN BIT(12)
+#define MII_DP83867_MICR_AUTONEG_COMP_INT_EN BIT(11)
+#define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN BIT(10)
+#define MII_DP83867_MICR_FALSE_CARRIER_INT_EN BIT(8)
+#define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4)
+#define MII_DP83867_MICR_WOL_INT_EN BIT(3)
+#define MII_DP83867_MICR_XGMII_ERR_INT_EN BIT(2)
+#define MII_DP83867_MICR_POL_CHNG_INT_EN BIT(1)
+#define MII_DP83867_MICR_JABBER_INT_EN BIT(0)
+
+/* RGMIICTL bits */
+#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
+#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
+
+/* PHY CTRL bits */
+#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
+
+/* RGMIIDCTL bits */
+#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
+
+#define MII_MMD_CTRL 0x0d /* MMD Access Control Register */
+#define MII_MMD_DATA 0x0e /* MMD Access Data Register */
+
+/* MMD Access Control register fields */
+#define MII_MMD_CTRL_DEVAD_MASK 0x1f /* Mask MMD DEVAD*/
+#define MII_MMD_CTRL_ADDR 0x0000 /* Address */
+#define MII_MMD_CTRL_NOINCR 0x4000 /* no post increment */
+#define MII_MMD_CTRL_INCR_RDWT 0x8000 /* post increment on reads & writes */
+#define MII_MMD_CTRL_INCR_ON_WT 0xC000 /* post increment on writes only */
+
+/**
+ * phy_read_mmd_indirect - reads data from the MMD registers
+ * @phydev: The PHY device bus
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ *
+ * Description: it reads data from the MMD registers (clause 22 to access to
+ * clause 45) of the specified phy address.
+ * To read these registers we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Read reg 14 // Read MMD data
+ */
+int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
+ int devad, int addr)
+{
+ int value = -1;
+
+ /* Write the desired MMD Devad */
+ phy_write(phydev, addr, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ phy_write(phydev, addr, MII_MMD_DATA, prtad);
+
+ /* Select the Function : DATA with no post increment */
+ phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
+
+ /* Read the content of the MMD's selected register */
+ value = phy_read(phydev, addr, MII_MMD_DATA);
+ return value;
+}
+
+/**
+ * phy_write_mmd_indirect - writes data to the MMD registers
+ * @phydev: The PHY device
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @addr: PHY address on the MII bus
+ * @data: data to write in the MMD register
+ *
+ * Description: Write data from the MMD registers of the specified
+ * phy address.
+ * To write these registers we have:
+ * 1) Write reg 13 // DEVAD
+ * 2) Write reg 14 // MMD Address
+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
+ * 3) Write reg 14 // Write MMD data
+ */
+void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
+ int devad, int addr, u32 data)
+{
+ /* Write the desired MMD Devad */
+ phy_write(phydev, addr, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ phy_write(phydev, addr, MII_MMD_DATA, prtad);
+
+ /* Select the Function : DATA with no post increment */
+ phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
+
+ /* Write the data into MMD's selected register */
+ phy_write(phydev, addr, MII_MMD_DATA, data);
+}
+
+/**
+ * phy_interface_is_rgmii - Convenience function for testing if a PHY interface
+ * is RGMII (all variants)
+ * @phydev: the phy_device struct
+ */
+static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
+{
+ return phydev->interface >= PHY_INTERFACE_MODE_RGMII &&
+ phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID;
+}
+
+/* User setting - can be taken from DTS */
+#define RX_ID_DELAY 8
+#define TX_ID_DELAY 0xa
+#define FIFO_DEPTH 1
+
+static int dp83867_config(struct phy_device *phydev)
+{
+ unsigned int val, delay;
+ int ret;
+
+ /* Restart the PHY. */
+ val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL);
+ phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
+ val | DP83867_SW_RESTART);
+
+ if (phy_interface_is_rgmii(phydev)) {
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
+ (FIFO_DEPTH << DP83867_PHYCR_FIFO_DEPTH_SHIFT));
+ if (ret)
+ return ret;
+ }
+
+ if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) &&
+ (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) {
+ val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
+ DP83867_DEVADDR, phydev->addr);
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
+ DP83867_RGMII_RX_CLK_DELAY_EN);
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+ val |= DP83867_RGMII_TX_CLK_DELAY_EN;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+ val |= DP83867_RGMII_RX_CLK_DELAY_EN;
+
+ phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
+ DP83867_DEVADDR, phydev->addr, val);
+
+ delay = (RX_ID_DELAY |
+ (TX_ID_DELAY << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
+
+ phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
+ DP83867_DEVADDR, phydev->addr, delay);
+ }
+
+ genphy_config_aneg(phydev);
+ return 0;
+}
+
+static struct phy_driver DP83867_driver = {
+ .name = "TI DP83867",
+ .uid = 0x2000a231,
+ .mask = 0xfffffff0,
+ .features = PHY_GBIT_FEATURES,
+ .config = &dp83867_config,
+ .startup = &genphy_startup,
+ .shutdown = &genphy_shutdown,
+};
+
+int phy_ti_init(void)
+{
+ phy_register(&DP83867_driver);
+ return 0;
+}
diff --git a/drivers/net/vsc7385.c b/drivers/net/vsc7385.c
index a5110e5..c6d6dce 100644
--- a/drivers/net/vsc7385.c
+++ b/drivers/net/vsc7385.c
@@ -14,6 +14,7 @@
#include <config.h>
#include <common.h>
+#include <console.h>
#include <asm/io.h>
#include <asm/errno.h>
#include "vsc7385.h"
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 5637a0d..858093f 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -23,6 +23,7 @@
#include <asm/system.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
+#include <asm-generic/errno.h>
#if !defined(CONFIG_PHYLIB)
# error XILINX_GEM_ETHERNET requires PHYLIB
@@ -46,6 +47,7 @@
/* Wrap bit, last descriptor */
#define ZYNQ_GEM_TXBUF_WRAP_MASK 0x40000000
#define ZYNQ_GEM_TXBUF_LAST_MASK 0x00008000 /* Last buffer */
+#define ZYNQ_GEM_TXBUF_USED_MASK 0x80000000 /* Used by Hw */
#define ZYNQ_GEM_NWCTRL_TXEN_MASK 0x00000008 /* Enable transmit */
#define ZYNQ_GEM_NWCTRL_RXEN_MASK 0x00000004 /* Enable receive */
@@ -56,8 +58,7 @@
#define ZYNQ_GEM_NWCFG_SPEED1000 0x000000400 /* 1Gbps operation */
#define ZYNQ_GEM_NWCFG_FDEN 0x000000002 /* Full Duplex mode */
#define ZYNQ_GEM_NWCFG_FSREM 0x000020000 /* FCS removal */
-#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x000080000 /* Div pclk by 32, 80MHz */
-#define ZYNQ_GEM_NWCFG_MDCCLKDIV2 0x0000c0000 /* Div pclk by 48, 120MHz */
+#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x0000c0000 /* Div pclk by 48, max 120MHz */
#ifdef CONFIG_ARM64
# define ZYNQ_GEM_DBUS_WIDTH (1 << 21) /* 64 bit bus */
@@ -85,6 +86,8 @@
ZYNQ_GEM_DMACR_TXSIZE | \
ZYNQ_GEM_DMACR_RXBUF)
+#define ZYNQ_GEM_TSR_DONE 0x00000020 /* Tx done mask */
+
/* Use MII register 1 (MII status register) to detect PHY */
#define PHY_DETECT_REG 1
@@ -108,28 +111,33 @@
/* Device registers */
struct zynq_gem_regs {
- u32 nwctrl; /* Network Control reg */
- u32 nwcfg; /* Network Config reg */
- u32 nwsr; /* Network Status reg */
+ u32 nwctrl; /* 0x0 - Network Control reg */
+ u32 nwcfg; /* 0x4 - Network Config reg */
+ u32 nwsr; /* 0x8 - Network Status reg */
u32 reserved1;
- u32 dmacr; /* DMA Control reg */
- u32 txsr; /* TX Status reg */
- u32 rxqbase; /* RX Q Base address reg */
- u32 txqbase; /* TX Q Base address reg */
- u32 rxsr; /* RX Status reg */
+ u32 dmacr; /* 0x10 - DMA Control reg */
+ u32 txsr; /* 0x14 - TX Status reg */
+ u32 rxqbase; /* 0x18 - RX Q Base address reg */
+ u32 txqbase; /* 0x1c - TX Q Base address reg */
+ u32 rxsr; /* 0x20 - RX Status reg */
u32 reserved2[2];
- u32 idr; /* Interrupt Disable reg */
+ u32 idr; /* 0x2c - Interrupt Disable reg */
u32 reserved3;
- u32 phymntnc; /* Phy Maintaince reg */
+ u32 phymntnc; /* 0x34 - Phy Maintaince reg */
u32 reserved4[18];
- u32 hashl; /* Hash Low address reg */
- u32 hashh; /* Hash High address reg */
+ u32 hashl; /* 0x80 - Hash Low address reg */
+ u32 hashh; /* 0x84 - Hash High address reg */
#define LADDR_LOW 0
#define LADDR_HIGH 1
- u32 laddr[4][LADDR_HIGH + 1]; /* Specific1 addr low/high reg */
- u32 match[4]; /* Type ID1 Match reg */
+ u32 laddr[4][LADDR_HIGH + 1]; /* 0x8c - Specific1 addr low/high reg */
+ u32 match[4]; /* 0xa8 - Type ID1 Match reg */
u32 reserved6[18];
- u32 stat[44]; /* Octects transmitted Low reg - stat start */
+#define STAT_SIZE 44
+ u32 stat[STAT_SIZE]; /* 0x100 - Octects transmitted Low reg */
+ u32 reserved7[164];
+ u32 transmit_q1_ptr; /* 0x440 - Transmit priority queue 1 */
+ u32 reserved8[15];
+ u32 receive_q1_ptr; /* 0x480 - Receive priority queue 1 */
};
/* BD descriptors */
@@ -144,7 +152,10 @@ struct emac_bd {
*/
#define BD_SPACE 0x100000
/* BD separation space */
-#define BD_SEPRN_SPACE 64
+#define BD_SEPRN_SPACE (RX_BUF * sizeof(struct emac_bd))
+
+/* Setup the first free TX descriptor */
+#define TX_FREE_DESC 2
/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
struct zynq_gem_priv {
@@ -156,6 +167,7 @@ struct zynq_gem_priv {
int phyaddr;
u32 emio;
int init;
+ phy_interface_t interface;
struct phy_device *phydev;
struct mii_dev *bus;
};
@@ -208,12 +220,23 @@ static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum,
static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val)
{
- return phy_setup_op(dev, phy_addr, regnum,
+ u32 ret;
+
+ ret = phy_setup_op(dev, phy_addr, regnum,
ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);
+
+ if (!ret)
+ debug("%s: phy_addr %d, regnum 0x%x, val 0x%x\n", __func__,
+ phy_addr, regnum, *val);
+
+ return ret;
}
static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)
{
+ debug("%s: phy_addr %d, regnum 0x%x, data 0x%x\n", __func__, phy_addr,
+ regnum, data);
+
return phy_setup_op(dev, phy_addr, regnum,
ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);
}
@@ -289,10 +312,10 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
u32 i;
unsigned long clk_rate = 0;
struct phy_device *phydev;
- const u32 stat_size = (sizeof(struct zynq_gem_regs) -
- offsetof(struct zynq_gem_regs, stat)) / 4;
struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
struct zynq_gem_priv *priv = dev->priv;
+ struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
+ struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2];
const u32 supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
@@ -318,7 +341,7 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
writel(0x0, &regs->hashh);
/* Clear all counters */
- for (i = 0; i <= stat_size; i++)
+ for (i = 0; i < STAT_SIZE; i++)
readl(&regs->stat[i]);
/* Setup RxBD space */
@@ -341,6 +364,23 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
/* Setup for Network Control register, MDIO, Rx and Tx enable */
setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);
+ /* Disable the second priority queue */
+ dummy_tx_bd->addr = 0;
+ dummy_tx_bd->status = ZYNQ_GEM_TXBUF_WRAP_MASK |
+ ZYNQ_GEM_TXBUF_LAST_MASK|
+ ZYNQ_GEM_TXBUF_USED_MASK;
+
+ dummy_rx_bd->addr = ZYNQ_GEM_RXBUF_WRAP_MASK |
+ ZYNQ_GEM_RXBUF_NEW_MASK;
+ dummy_rx_bd->status = 0;
+ flush_dcache_range((ulong)&dummy_tx_bd, (ulong)&dummy_tx_bd +
+ sizeof(dummy_tx_bd));
+ flush_dcache_range((ulong)&dummy_rx_bd, (ulong)&dummy_rx_bd +
+ sizeof(dummy_rx_bd));
+
+ writel((ulong)dummy_tx_bd, &regs->transmit_q1_ptr);
+ writel((ulong)dummy_rx_bd, &regs->receive_q1_ptr);
+
priv->init++;
}
@@ -348,7 +388,7 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
/* interface - look at tsec */
phydev = phy_connect(priv->bus, priv->phyaddr, dev,
- PHY_INTERFACE_MODE_MII);
+ priv->interface);
phydev->supported = supported | ADVERTISED_Pause |
ADVERTISED_Asym_Pause;
@@ -369,8 +409,8 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
clk_rate = ZYNQ_GEM_FREQUENCY_1000;
break;
case SPEED_100:
- clrsetbits_le32(&regs->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000,
- ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100);
+ writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100,
+ &regs->nwcfg);
clk_rate = ZYNQ_GEM_FREQUENCY_100;
break;
case SPEED_10:
@@ -389,22 +429,54 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
return 0;
}
+static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
+ bool set, unsigned int timeout)
+{
+ u32 val;
+ unsigned long start = get_timer(0);
+
+ while (1) {
+ val = readl(reg);
+
+ if (!set)
+ val = ~val;
+
+ if ((val & mask) == mask)
+ return 0;
+
+ if (get_timer(start) > timeout)
+ break;
+
+ udelay(1);
+ }
+
+ debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n",
+ func, reg, mask, set);
+
+ return -ETIMEDOUT;
+}
+
static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)
{
u32 addr, size;
struct zynq_gem_priv *priv = dev->priv;
struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
-
- /* setup BD */
- writel((ulong)priv->tx_bd, &regs->txqbase);
+ struct emac_bd *current_bd = &priv->tx_bd[1];
/* Setup Tx BD */
memset(priv->tx_bd, 0, sizeof(struct emac_bd));
priv->tx_bd->addr = (ulong)ptr;
priv->tx_bd->status = (len & ZYNQ_GEM_TXBUF_FRMLEN_MASK) |
- ZYNQ_GEM_TXBUF_LAST_MASK |
- ZYNQ_GEM_TXBUF_WRAP_MASK;
+ ZYNQ_GEM_TXBUF_LAST_MASK;
+ /* Dummy descriptor to mark it as the last in descriptor chain */
+ current_bd->addr = 0x0;
+ current_bd->status = ZYNQ_GEM_TXBUF_WRAP_MASK |
+ ZYNQ_GEM_TXBUF_LAST_MASK|
+ ZYNQ_GEM_TXBUF_USED_MASK;
+
+ /* setup BD */
+ writel((ulong)priv->tx_bd, &regs->txqbase);
addr = (ulong) ptr;
addr &= ~(ARCH_DMA_MINALIGN - 1);
@@ -421,12 +493,11 @@ static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)
setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK);
/* Read TX BD status */
- if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_UNDERRUN)
- printf("TX underrun\n");
if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
printf("TX buffers exhausted in mid frame\n");
- return 0;
+ return wait_for_bit(__func__, &regs->txsr, ZYNQ_GEM_TSR_DONE,
+ true, 20000);
}
/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
@@ -535,6 +606,12 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr,
priv->phyaddr = phy_addr;
priv->emio = emio;
+#ifndef CONFIG_ZYNQ_GEM_INTERFACE
+ priv->interface = PHY_INTERFACE_MODE_MII;
+#else
+ priv->interface = CONFIG_ZYNQ_GEM_INTERFACE;
+#endif
+
sprintf(dev->name, "Gem.%lx", base_addr);
dev->iobase = base_addr;
diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c
index a64792f..2a14902 100644
--- a/drivers/pci/pci_common.c
+++ b/drivers/pci/pci_common.c
@@ -268,7 +268,7 @@ int __pci_hose_phys_to_bus(struct pci_controller *hose,
bus_addr = phys_addr - res->phys_start + res->bus_start;
if (bus_addr >= res->bus_start &&
- bus_addr < res->bus_start + res->size) {
+ (bus_addr - res->bus_start) < res->size) {
*ba = bus_addr;
return 0;
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 809f8f1..1936e5f 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -8,7 +8,8 @@ choice
prompt "Select Sunxi PMIC Variant"
depends on ARCH_SUNXI
default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
- default AXP221_POWER if MACH_SUN6I || MACH_SUN8I
+ default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
+ default SUNXI_NO_PMIC if MACH_SUN8I_H3
config SUNXI_NO_PMIC
boolean "board without a pmic"
@@ -31,7 +32,7 @@ config AXP209_POWER
config AXP221_POWER
boolean "axp221 / axp223 pmic support"
- depends on MACH_SUN6I || MACH_SUN8I
+ depends on MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33
---help---
Select this to enable support for the axp221/axp223 pmic found on most
A23 and A31 boards.
diff --git a/drivers/power/battery/bat_trats.c b/drivers/power/battery/bat_trats.c
index bfde692..089e789 100644
--- a/drivers/power/battery/bat_trats.c
+++ b/drivers/power/battery/bat_trats.c
@@ -6,6 +6,7 @@
*/
#include <common.h>
+#include <console.h>
#include <power/pmic.h>
#include <power/battery.h>
#include <power/max8997_pmic.h>
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index eba96f4..82ad90d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -53,6 +53,7 @@ config DEBUG_UART
choice
prompt "Select which UART will provide the debug UART"
depends on DEBUG_UART
+ default DEBUG_UART_NS16550
config DEBUG_UART_ALTERA_JTAGUART
bool "Altera JTAG UART"
@@ -185,14 +186,15 @@ config ALTERA_UART
Select this to enable an UART for Altera devices. Please find
details on the "Embedded Peripherals IP User Guide" of Altera.
-config ROCKCHIP_SERIAL
- bool "Rockchip on-chip UART support"
- depends on ARCH_ROCKCHIP && DM_SERIAL
+config SYS_NS16550
+ bool "NS16550 UART or compatible"
help
- Select this to enable a debug UART for Rockchip devices. This uses
- the ns16550 driver. You will need to #define CONFIG_SYS_NS16550 in
- your board config header. The clock input is automatically set to
- use the oscillator (24MHz).
+ Support NS16550 UART or compatible. This can be enabled in the
+ device tree with the correct input clock frequency. If the input
+ clock frequency is not defined in the device tree, the macro
+ CONFIG_SYS_NS16550_CLK defined in a legacy board header file will
+ be used. It can be a constant or a function to get clock, eg,
+ get_serial_clock().
config SANDBOX_SERIAL
bool "Sandbox UART support"
@@ -221,14 +223,4 @@ config UNIPHIER_SERIAL
If you have a UniPhier based board and want to use the on-chip
serial ports, say Y to this option. If unsure, say N.
-config X86_SERIAL
- bool "Support for 16550 serial port on x86 machines"
- depends on X86
- default y
- help
- Most x86 machines have a ns16550 UART or compatible. This can be
- enabled in the device tree with the correct input clock frequency
- provided (default 1843200). Enable this to obtain serial console
- output.
-
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 1818c7c..dd87147 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -8,7 +8,6 @@
ifdef CONFIG_DM_SERIAL
obj-y += serial-uclass.o
obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
-obj-$(CONFIG_PPC) += serial_ppc.o
else
obj-y += serial.o
obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
@@ -20,12 +19,10 @@ obj-$(CONFIG_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
obj-$(CONFIG_ARM_DCC) += arm_dcc.o
obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
-obj-$(CONFIG_DW_SERIAL) += serial_dw.o
obj-$(CONFIG_EFI_APP) += serial_efi.o
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
obj-$(CONFIG_MCFUART) += mcfuart.o
obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o
-obj-$(CONFIG_KEYSTONE_SERIAL) += serial_keystone.o
obj-$(CONFIG_SYS_NS16550) += ns16550.o
obj-$(CONFIG_S5P) += serial_s5p.o
obj-$(CONFIG_IMX_SERIAL) += serial_imx.o
@@ -41,12 +38,8 @@ obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o
obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
obj-$(CONFIG_MXS_AUART) += mxs_auart.o
-obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
-obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
-obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
-obj-$(CONFIG_X86_SERIAL) += serial_x86.o
obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
ifndef CONFIG_SPL_BUILD
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 6433844..d5bcbc3 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -8,7 +8,6 @@
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
-#include <mapmem.h>
#include <ns16550.h>
#include <serial.h>
#include <watchdog.h>
@@ -57,6 +56,10 @@ DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_DM_SERIAL
+#ifndef CONFIG_SYS_NS16550_CLK
+#define CONFIG_SYS_NS16550_CLK 0
+#endif
+
static inline void serial_out_shift(void *addr, int shift, int value)
{
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
@@ -97,7 +100,7 @@ static void ns16550_writeb(NS16550_t port, int offset, int value)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
- addr = map_sysmem(plat->base, 0) + offset;
+ addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset;
/*
* As far as we know it doesn't make sense to support selection of
* these options at run-time, so use the existing CONFIG options.
@@ -111,7 +114,7 @@ static int ns16550_readb(NS16550_t port, int offset)
unsigned char *addr;
offset *= 1 << plat->reg_shift;
- addr = map_sysmem(plat->base, 0) + offset;
+ addr = map_physmem(plat->base, 0, MAP_NOCACHE) + offset;
return serial_in_shift(addr, plat->reg_shift);
}
@@ -401,6 +404,13 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
plat->base = addr;
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"reg-shift", 1);
+ plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "clock-frequency",
+ CONFIG_SYS_NS16550_CLK);
+ if (!plat->clock) {
+ debug("ns16550 clock not defined\n");
+ return -EINVAL;
+ }
return 0;
}
@@ -412,4 +422,33 @@ const struct dm_serial_ops ns16550_serial_ops = {
.getc = ns16550_serial_getc,
.setbrg = ns16550_serial_setbrg,
};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id ns16550_serial_ids[] = {
+ { .compatible = "ns16550" },
+ { .compatible = "ns16550a" },
+ { .compatible = "nvidia,tegra20-uart" },
+ { .compatible = "snps,dw-apb-uart" },
+ { .compatible = "ti,omap2-uart" },
+ { .compatible = "ti,omap3-uart" },
+ { .compatible = "ti,omap4-uart" },
+ { .compatible = "ti,am3352-uart" },
+ { .compatible = "ti,am4372-uart" },
+ { .compatible = "ti,dra742-uart" },
+ {}
+};
+#endif
+
+U_BOOT_DRIVER(ns16550_serial) = {
+ .name = "ns16550_serial",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ .of_match = ns16550_serial_ids,
+ .ofdata_to_platdata = ns16550_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+#endif
+ .priv_auto_alloc_size = sizeof(struct NS16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
#endif /* CONFIG_DM_SERIAL */
diff --git a/drivers/serial/serial_dw.c b/drivers/serial/serial_dw.c
deleted file mode 100644
index a348f29..0000000
--- a/drivers/serial/serial_dw.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ns16550.h>
-#include <serial.h>
-
-static const struct udevice_id dw_serial_ids[] = {
- { .compatible = "snps,dw-apb-uart" },
- { }
-};
-
-static int dw_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
- plat->clock = CONFIG_SYS_NS16550_CLK;
-
- return 0;
-}
-
-U_BOOT_DRIVER(serial_ns16550) = {
- .name = "serial_dw",
- .id = UCLASS_SERIAL,
- .of_match = dw_serial_ids,
- .ofdata_to_platdata = dw_serial_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
-};
diff --git a/drivers/serial/serial_keystone.c b/drivers/serial/serial_keystone.c
deleted file mode 100644
index 7b5ab6c..0000000
--- a/drivers/serial/serial_keystone.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2015 Texas Instruments, <www.ti.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <fdtdec.h>
-#include <ns16550.h>
-#include <serial.h>
-#include <asm/arch/clock.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct udevice_id keystone_serial_ids[] = {
- { .compatible = "ti,keystone-uart" },
- { .compatible = "ns16550a" },
- { }
-};
-
-static int keystone_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
- plat->clock = CONFIG_SYS_NS16550_CLK;
- return 0;
-}
-#endif
-
-U_BOOT_DRIVER(serial_keystone_ns16550) = {
- .name = "serial_keystone",
- .id = UCLASS_SERIAL,
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- .of_match = of_match_ptr(keystone_serial_ids),
- .ofdata_to_platdata = of_match_ptr(keystone_serial_ofdata_to_platdata),
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
-#endif
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
deleted file mode 100644
index 891cd7b..0000000
--- a/drivers/serial/serial_omap.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <fdtdec.h>
-#include <ns16550.h>
-#include <serial.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz */
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct udevice_id omap_serial_ids[] = {
- { .compatible = "ti,omap2-uart" },
- { .compatible = "ti,omap3-uart" },
- { .compatible = "ti,omap4-uart" },
- { .compatible = "ti,am3352-uart" },
- { .compatible = "ti,am4372-uart" },
- { .compatible = "ti,dra742-uart" },
- { }
-};
-
-static int omap_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
- plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "clock-frequency", DEFAULT_CLK_SPEED);
- plat->reg_shift = 2;
-
- return 0;
-}
-#endif
-
-U_BOOT_DRIVER(serial_omap_ns16550) = {
- .name = "serial_omap",
- .id = UCLASS_SERIAL,
- .of_match = of_match_ptr(omap_serial_ids),
- .ofdata_to_platdata = of_match_ptr(omap_serial_ofdata_to_platdata),
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/serial/serial_ppc.c b/drivers/serial/serial_ppc.c
deleted file mode 100644
index 47141c6..0000000
--- a/drivers/serial/serial_ppc.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ns16550.h>
-#include <serial.h>
-
-static const struct udevice_id ppc_serial_ids[] = {
- { .compatible = "ns16550" },
- { }
-};
-
-static int ppc_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
- plat->clock = get_serial_clock();
-
- return 0;
-}
-
-U_BOOT_DRIVER(serial_ns16550) = {
- .name = "serial_ppc",
- .id = UCLASS_SERIAL,
- .of_match = ppc_serial_ids,
- .ofdata_to_platdata = ppc_serial_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/serial/serial_rockchip.c b/drivers/serial/serial_rockchip.c
deleted file mode 100644
index 0e7bbfc..0000000
--- a/drivers/serial/serial_rockchip.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2015 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ns16550.h>
-#include <serial.h>
-#include <asm/arch/clock.h>
-
-static const struct udevice_id rockchip_serial_ids[] = {
- { .compatible = "rockchip,rk3288-uart" },
- { }
-};
-
-static int rockchip_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
-
- /* Do all Rockchip parts use 24MHz? */
- plat->clock = 24 * 1000000;
-
- return 0;
-}
-
-U_BOOT_DRIVER(serial_ns16550) = {
- .name = "serial_rockchip",
- .id = UCLASS_SERIAL,
- .of_match = rockchip_serial_ids,
- .ofdata_to_platdata = rockchip_serial_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/serial/serial_tegra.c b/drivers/serial/serial_tegra.c
deleted file mode 100644
index 0c84f0b..0000000
--- a/drivers/serial/serial_tegra.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <ns16550.h>
-#include <serial.h>
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-static const struct udevice_id tegra_serial_ids[] = {
- { .compatible = "nvidia,tegra20-uart" },
- { }
-};
-
-static int tegra_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
- plat->clock = V_NS16550_CLK;
-
- return 0;
-}
-#else
-struct ns16550_platdata tegra_serial = {
- .base = CONFIG_SYS_NS16550_COM1,
- .reg_shift = 2,
- .clock = V_NS16550_CLK,
-};
-
-U_BOOT_DEVICE(ns16550_serial) = {
- "serial_tegra20", &tegra_serial
-};
-#endif
-
-U_BOOT_DRIVER(serial_ns16550) = {
- .name = "serial_tegra20",
- .id = UCLASS_SERIAL,
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- .of_match = tegra_serial_ids,
- .ofdata_to_platdata = tegra_serial_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
-#endif
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
- .flags = DM_FLAG_PRE_RELOC,
-};
diff --git a/drivers/serial/serial_x86.c b/drivers/serial/serial_x86.c
deleted file mode 100644
index 4bf6062..0000000
--- a/drivers/serial/serial_x86.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014 Google, Inc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <dm.h>
-#include <fdtdec.h>
-#include <ns16550.h>
-#include <serial.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static const struct udevice_id x86_serial_ids[] = {
- { .compatible = "x86-uart" },
- { }
-};
-
-static int x86_serial_ofdata_to_platdata(struct udevice *dev)
-{
- struct ns16550_platdata *plat = dev_get_platdata(dev);
- int ret;
-
- ret = ns16550_serial_ofdata_to_platdata(dev);
- if (ret)
- return ret;
-
- plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "clock-frequency", 1843200);
-
- return 0;
-}
-
-U_BOOT_DRIVER(serial_ns16550) = {
- .name = "serial_x86",
- .id = UCLASS_SERIAL,
- .of_match = x86_serial_ids,
- .ofdata_to_platdata = x86_serial_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
- .priv_auto_alloc_size = sizeof(struct NS16550),
- .probe = ns16550_serial_probe,
- .ops = &ns16550_serial_ops,
-};
diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c
index 71a31d0..9a6fc78 100644
--- a/drivers/spi/bfin_spi.c
+++ b/drivers/spi/bfin_spi.c
@@ -9,6 +9,7 @@
/*#define DEBUG*/
#include <common.h>
+#include <console.h>
#include <malloc.h>
#include <spi.h>
diff --git a/drivers/spi/bfin_spi6xx.c b/drivers/spi/bfin_spi6xx.c
index 8359d76..9a27b78 100644
--- a/drivers/spi/bfin_spi6xx.c
+++ b/drivers/spi/bfin_spi6xx.c
@@ -18,6 +18,7 @@
*/
#include <common.h>
+#include <console.h>
#include <malloc.h>
#include <spi.h>
diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index 7209e1d..75999c8 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
+#include <console.h>
#include <malloc.h>
#include <spi.h>
#include <asm/arch/rmobile.h>
diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c
index 7ca5e36..1384385 100644
--- a/drivers/spi/sh_spi.c
+++ b/drivers/spi/sh_spi.c
@@ -19,6 +19,7 @@
*/
#include <common.h>
+#include <console.h>
#include <malloc.h>
#include <spi.h>
#include <asm/io.h>
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 58388ef..3c7d64a 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -118,6 +118,26 @@ static int spi_post_probe(struct udevice *bus)
spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
"spi-max-frequency", 0);
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ struct dm_spi_ops *ops = spi_get_ops(bus);
+
+
+ if (ops->claim_bus)
+ ops->claim_bus += gd->reloc_off;
+ if (ops->release_bus)
+ ops->release_bus += gd->reloc_off;
+ if (ops->set_wordlen)
+ ops->set_wordlen += gd->reloc_off;
+ if (ops->xfer)
+ ops->xfer += gd->reloc_off;
+ if (ops->set_speed)
+ ops->set_speed += gd->reloc_off;
+ if (ops->set_mode)
+ ops->set_mode += gd->reloc_off;
+ if (ops->cs_info)
+ ops->cs_info += gd->reloc_off;
+#endif
+
return 0;
}
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index ecd9d78..646dd89 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -170,6 +170,8 @@ void spi_cs_deactivate(struct spi_slave *slave)
debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
writel(qslave->cmd | QSPI_INVAL, &qslave->base->cmd);
+ /* dummy readl to ensure bus sync */
+ readl(&qslave->base->cmd);
}
void spi_init(void)
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index 97c4128..601e493 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -16,4 +16,11 @@ config ALTERA_TIMER
Select this to enable an timer for Altera devices. Please find
details on the "Embedded Peripherals IP User Guide" of Altera.
+config SANDBOX_TIMER
+ bool "Sandbox Timer support"
+ depends on SANDBOX && TIMER
+ help
+ Select this to enable an emulated timer for sandbox. It gets
+ time from host os.
+
endmenu
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index ae66c07..300946e 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_TIMER) += timer-uclass.o
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
+obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
diff --git a/drivers/timer/sandbox_timer.c b/drivers/timer/sandbox_timer.c
new file mode 100644
index 0000000..38de763
--- /dev/null
+++ b/drivers/timer/sandbox_timer.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <os.h>
+
+/* system timer offset in ms */
+static unsigned long sandbox_timer_offset;
+
+void sandbox_timer_add_offset(unsigned long offset)
+{
+ sandbox_timer_offset += offset;
+}
+
+static int sandbox_timer_get_count(struct udevice *dev, unsigned long *count)
+{
+ *count = os_get_nsec() / 1000 + sandbox_timer_offset * 1000;
+
+ return 0;
+}
+
+static int sandbox_timer_probe(struct udevice *dev)
+{
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ uc_priv->clock_rate = 1000000;
+
+ return 0;
+}
+
+static const struct timer_ops sandbox_timer_ops = {
+ .get_count = sandbox_timer_get_count,
+};
+
+static const struct udevice_id sandbox_timer_ids[] = {
+ { .compatible = "sandbox,timer" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_timer) = {
+ .name = "sandbox_timer",
+ .id = UCLASS_TIMER,
+ .of_match = sandbox_timer_ids,
+ .probe = sandbox_timer_probe,
+ .ops = &sandbox_timer_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/usb/emul/Makefile b/drivers/usb/emul/Makefile
index 8fd83d5..b64ac6d 100644
--- a/drivers/usb/emul/Makefile
+++ b/drivers/usb/emul/Makefile
@@ -7,4 +7,5 @@
obj-$(CONFIG_USB_EMUL) += sandbox_flash.o
obj-$(CONFIG_USB_EMUL) += sandbox_hub.o
+obj-$(CONFIG_USB_EMUL) += sandbox_keyb.o
obj-$(CONFIG_USB_EMUL) += usb-emul-uclass.o
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 6e0808d..0965ad0 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -31,6 +31,14 @@ enum cmd_phase {
PHASE_STATUS,
};
+enum {
+ STRINGID_MANUFACTURER = 1,
+ STRINGID_PRODUCT,
+ STRINGID_SERIAL,
+
+ STRINGID_COUNT,
+};
+
/**
* struct sandbox_flash_priv - private state for this driver
*
@@ -61,6 +69,7 @@ struct sandbox_flash_priv {
struct sandbox_flash_plat {
const char *pathname;
+ struct usb_string flash_strings[STRINGID_COUNT];
};
struct scsi_inquiry_resp {
@@ -89,21 +98,6 @@ struct __packed scsi_read10_req {
u8 spare2[3];
};
-enum {
- STRINGID_MANUFACTURER = 1,
- STRINGID_PRODUCT,
- STRINGID_SERIAL,
-
- STRINGID_COUNT,
-};
-
-static struct usb_string flash_strings[] = {
- {STRINGID_MANUFACTURER, "sandbox"},
- {STRINGID_PRODUCT, "flash"},
- {STRINGID_SERIAL, "2345"},
- {},
-};
-
static struct usb_device_descriptor flash_device_desc = {
.bLength = sizeof(flash_device_desc),
.bDescriptorType = USB_DT_DEVICE,
@@ -246,7 +240,8 @@ static void handle_read(struct sandbox_flash_priv *priv, ulong lba,
}
}
-static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
+static int handle_ufi_command(struct sandbox_flash_plat *plat,
+ struct sandbox_flash_priv *priv, const void *buff,
int len)
{
const struct SCSI_cmd_block *req = buff;
@@ -260,9 +255,10 @@ static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
resp->data_format = 1;
resp->additional_len = 0x1f;
strncpy(resp->vendor,
- flash_strings[STRINGID_MANUFACTURER - 1].s,
+ plat->flash_strings[STRINGID_MANUFACTURER - 1].s,
sizeof(resp->vendor));
- strncpy(resp->product, flash_strings[STRINGID_PRODUCT - 1].s,
+ strncpy(resp->product,
+ plat->flash_strings[STRINGID_PRODUCT - 1].s,
sizeof(resp->product));
strncpy(resp->revision, "1.0", sizeof(resp->revision));
setup_response(priv, resp, sizeof(*resp));
@@ -303,6 +299,7 @@ static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
unsigned long pipe, void *buff, int len)
{
+ struct sandbox_flash_plat *plat = dev_get_platdata(dev);
struct sandbox_flash_priv *priv = dev_get_priv(dev);
int ep = usb_pipeendpoint(pipe);
struct umass_bbb_cbw *cbw = buff;
@@ -325,7 +322,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
goto err;
priv->transfer_len = cbw->dCBWDataTransferLength;
priv->tag = cbw->dCBWTag;
- return handle_ufi_command(priv, cbw->CBWCDB,
+ return handle_ufi_command(plat, priv, cbw->CBWCDB,
cbw->bCDBLength);
case PHASE_DATA:
debug("data out\n");
@@ -384,7 +381,18 @@ static int sandbox_flash_ofdata_to_platdata(struct udevice *dev)
static int sandbox_flash_bind(struct udevice *dev)
{
- return usb_emul_setup_device(dev, PACKET_SIZE_64, flash_strings,
+ struct sandbox_flash_plat *plat = dev_get_platdata(dev);
+ struct usb_string *fs;
+
+ fs = plat->flash_strings;
+ fs[0].id = STRINGID_MANUFACTURER;
+ fs[0].s = "sandbox";
+ fs[1].id = STRINGID_PRODUCT;
+ fs[1].s = "flash";
+ fs[2].id = STRINGID_SERIAL;
+ fs[2].s = dev->name;
+
+ return usb_emul_setup_device(dev, PACKET_SIZE_64, plat->flash_strings,
flash_desc_list);
}
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index baf8bdc..624fbde 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -13,7 +13,7 @@
DECLARE_GLOBAL_DATA_PTR;
/* We only support up to 8 */
-#define SANDBOX_NUM_PORTS 2
+#define SANDBOX_NUM_PORTS 4
struct sandbox_hub_platdata {
struct usb_dev_platdata plat;
diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c
new file mode 100644
index 0000000..2735985
--- /dev/null
+++ b/drivers/usb/emul/sandbox_keyb.c
@@ -0,0 +1,241 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <os.h>
+#include <scsi.h>
+#include <usb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This driver emulates a USB keyboard using the USB HID specification (boot
+ * protocol)
+ */
+
+enum {
+ SANDBOX_KEYB_EP_IN = 1, /* endpoints */
+};
+
+enum cmd_phase {
+ PHASE_START,
+ PHASE_DATA,
+ PHASE_STATUS,
+};
+
+enum {
+ STRINGID_MANUFACTURER = 1,
+ STRINGID_PRODUCT,
+ STRINGID_SERIAL,
+
+ STRINGID_COUNT,
+};
+
+/**
+ * struct sandbox_keyb_priv - private state for this driver
+ *
+ */
+struct sandbox_keyb_priv {
+ struct membuff in;
+};
+
+struct sandbox_keyb_plat {
+ struct usb_string keyb_strings[STRINGID_COUNT];
+};
+
+static struct usb_device_descriptor keyb_device_desc = {
+ .bLength = sizeof(keyb_device_desc),
+ .bDescriptorType = USB_DT_DEVICE,
+
+ .bcdUSB = __constant_cpu_to_le16(0x0100),
+
+ .bDeviceClass = 0,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+
+ .idVendor = __constant_cpu_to_le16(0x1234),
+ .idProduct = __constant_cpu_to_le16(0x5679),
+ .iManufacturer = STRINGID_MANUFACTURER,
+ .iProduct = STRINGID_PRODUCT,
+ .iSerialNumber = STRINGID_SERIAL,
+ .bNumConfigurations = 1,
+};
+
+static struct usb_config_descriptor keyb_config0 = {
+ .bLength = sizeof(keyb_config0),
+ .bDescriptorType = USB_DT_CONFIG,
+
+ /* wTotalLength is set up by usb-emul-uclass */
+ .bNumInterfaces = 2,
+ .bConfigurationValue = 0,
+ .iConfiguration = 0,
+ .bmAttributes = 1 << 7 | 1 << 5,
+ .bMaxPower = 50,
+};
+
+static struct usb_interface_descriptor keyb_interface0 = {
+ .bLength = sizeof(keyb_interface0),
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = USB_SUB_HID_BOOT,
+ .bInterfaceProtocol = USB_PROT_HID_KEYBOARD,
+ .iInterface = 0,
+};
+
+static struct usb_class_hid_descriptor keyb_report0 = {
+ .bLength = sizeof(keyb_report0),
+ .bDescriptorType = USB_DT_HID,
+ .bcdCDC = 0x101,
+ .bCountryCode = 0,
+ .bNumDescriptors = 1,
+ .bDescriptorType0 = USB_DT_HID_REPORT,
+ .wDescriptorLength0 = 0x3f,
+};
+
+static struct usb_endpoint_descriptor keyb_endpoint0_in = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = SANDBOX_KEYB_EP_IN | USB_ENDPOINT_DIR_MASK,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK |
+ USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = __constant_cpu_to_le16(8),
+ .bInterval = 0xa,
+};
+
+static struct usb_interface_descriptor keyb_interface1 = {
+ .bLength = sizeof(keyb_interface1),
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = USB_SUB_HID_BOOT,
+ .bInterfaceProtocol = USB_PROT_HID_MOUSE,
+ .iInterface = 0,
+};
+
+static struct usb_class_hid_descriptor keyb_report1 = {
+ .bLength = sizeof(struct usb_class_hid_descriptor),
+ .bDescriptorType = USB_DT_HID,
+ .bcdCDC = 0x101,
+ .bCountryCode = 0,
+ .bNumDescriptors = 1,
+ .bDescriptorType0 = USB_DT_HID_REPORT,
+ .wDescriptorLength0 = 0x32,
+};
+
+static struct usb_endpoint_descriptor keyb_endpoint1_in = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = SANDBOX_KEYB_EP_IN | USB_ENDPOINT_DIR_MASK,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK |
+ USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = __constant_cpu_to_le16(8),
+ .bInterval = 0xa,
+};
+
+static void *keyb_desc_list[] = {
+ &keyb_device_desc,
+ &keyb_config0,
+ &keyb_interface0,
+ &keyb_report0,
+ &keyb_endpoint0_in,
+ &keyb_interface1,
+ &keyb_report1,
+ &keyb_endpoint1_in,
+ NULL,
+};
+
+int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str)
+{
+ struct sandbox_keyb_priv *priv = dev_get_priv(dev);
+ int len, ret;
+
+ len = strlen(str);
+ ret = membuff_put(&priv->in, str, len);
+ if (ret != len)
+ return -ENOSPC;
+
+ return 0;
+}
+
+static int sandbox_keyb_control(struct udevice *dev, struct usb_device *udev,
+ unsigned long pipe, void *buff, int len,
+ struct devrequest *setup)
+{
+ debug("pipe=%lx\n", pipe);
+
+ return -EIO;
+}
+
+static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length, int interval)
+{
+ struct sandbox_keyb_priv *priv = dev_get_priv(dev);
+ uint8_t *data = buffer;
+ int ch;
+
+ memset(data, '\0', length);
+ ch = membuff_getbyte(&priv->in);
+ if (ch != -1)
+ data[2] = 4 + ch - 'a';
+
+ return 0;
+}
+
+static int sandbox_keyb_bind(struct udevice *dev)
+{
+ struct sandbox_keyb_plat *plat = dev_get_platdata(dev);
+ struct usb_string *fs;
+
+ fs = plat->keyb_strings;
+ fs[0].id = STRINGID_MANUFACTURER;
+ fs[0].s = "sandbox";
+ fs[1].id = STRINGID_PRODUCT;
+ fs[1].s = "keyboard";
+ fs[2].id = STRINGID_SERIAL;
+ fs[2].s = dev->name;
+
+ return usb_emul_setup_device(dev, PACKET_SIZE_8, plat->keyb_strings,
+ keyb_desc_list);
+}
+
+static int sandbox_keyb_probe(struct udevice *dev)
+{
+ struct sandbox_keyb_priv *priv = dev_get_priv(dev);
+
+ return membuff_new(&priv->in, 256);
+}
+
+static const struct dm_usb_ops sandbox_usb_keyb_ops = {
+ .control = sandbox_keyb_control,
+ .interrupt = sandbox_keyb_interrupt,
+};
+
+static const struct udevice_id sandbox_usb_keyb_ids[] = {
+ { .compatible = "sandbox,usb-keyb" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_sandbox_keyb) = {
+ .name = "usb_sandbox_keyb",
+ .id = UCLASS_USB_EMUL,
+ .of_match = sandbox_usb_keyb_ids,
+ .bind = sandbox_keyb_bind,
+ .probe = sandbox_keyb_probe,
+ .ops = &sandbox_usb_keyb_ops,
+ .priv_auto_alloc_size = sizeof(struct sandbox_keyb_priv),
+ .platdata_auto_alloc_size = sizeof(struct sandbox_keyb_plat),
+};
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c
index 205f2c5..ee7ea5a 100644
--- a/drivers/usb/emul/usb-emul-uclass.c
+++ b/drivers/usb/emul/usb-emul-uclass.c
@@ -108,9 +108,8 @@ static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value,
return upto ? upto : length ? -EIO : 0;
}
-int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp)
+static int usb_emul_find_devnum(int devnum, struct udevice **emulp)
{
- int devnum = usb_pipedevice(pipe);
struct udevice *dev;
struct uclass *uc;
int ret;
@@ -134,6 +133,20 @@ int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp)
return -ENOENT;
}
+int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp)
+{
+ int devnum = usb_pipedevice(pipe);
+
+ return usb_emul_find_devnum(devnum, emulp);
+}
+
+int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp)
+{
+ struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
+
+ return usb_emul_find_devnum(udev->devnum, emulp);
+}
+
int usb_emul_control(struct udevice *emul, struct usb_device *udev,
unsigned long pipe, void *buffer, int length,
struct devrequest *setup)
@@ -205,6 +218,18 @@ int usb_emul_bulk(struct udevice *emul, struct usb_device *udev,
return ops->bulk(emul, udev, pipe, buffer, length);
}
+int usb_emul_int(struct udevice *emul, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length, int interval)
+{
+ struct dm_usb_ops *ops = usb_get_emul_ops(emul);
+
+ if (!ops->interrupt)
+ return -ENOSYS;
+ debug("%s: dev=%s\n", __func__, emul->name);
+
+ return ops->interrupt(emul, udev, pipe, buffer, length, interval);
+}
+
int usb_emul_setup_device(struct udevice *dev, int maxpacketsize,
struct usb_string *strings, void **desc_list)
{
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index c5e35ee..cfe9a24 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -9,6 +9,7 @@
*/
#include <common.h>
+#include <console.h>
#include <asm/errno.h>
#include <linux/netdevice.h>
#include <linux/usb/ch9.h>
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index abe9391..ec1f23a 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -243,6 +243,7 @@
#include <config.h>
#include <malloc.h>
#include <common.h>
+#include <console.h>
#include <g_dnl.h>
#include <linux/err.h>
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 9ed0ce3..a60e948 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -17,6 +17,7 @@
#include <errno.h>
#include <common.h>
+#include <console.h>
#include <malloc.h>
#include <memalign.h>
#include <version.h>
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 373e04c..6ef5190 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <console.h>
#include <usb.h>
#include <asm/io.h>
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
index c5f9822..5e3d96c 100644
--- a/drivers/usb/host/usb-sandbox.c
+++ b/drivers/usb/host/usb-sandbox.c
@@ -87,6 +87,24 @@ static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev,
return ret;
}
+static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev,
+ unsigned long pipe, void *buffer, int length,
+ int interval)
+{
+ struct udevice *emul;
+ int ret;
+
+ /* Just use child of dev as emulator? */
+ debug("%s: bus=%s\n", __func__, bus->name);
+ ret = usb_emul_find(bus, pipe, &emul);
+ usbmon_trace(bus, pipe, NULL, emul);
+ if (ret)
+ return ret;
+ ret = usb_emul_int(emul, udev, pipe, buffer, length, interval);
+
+ return ret;
+}
+
static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
{
return 0;
@@ -100,6 +118,7 @@ static int sandbox_usb_probe(struct udevice *dev)
static const struct dm_usb_ops sandbox_usb_ops = {
.control = sandbox_submit_control,
.bulk = sandbox_submit_bulk,
+ .interrupt = sandbox_submit_int,
.alloc_device = sandbox_alloc_device,
};
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 7f6a9a6..50538e0 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -158,9 +158,6 @@ int usb_stop(void)
ret = device_remove(bus);
if (ret && !err)
err = ret;
- ret = device_unbind_children(bus);
- if (ret && !err)
- err = ret;
}
#ifdef CONFIG_SANDBOX
@@ -205,6 +202,20 @@ static void usb_scan_bus(struct udevice *bus, bool recurse)
printf("%d USB Device(s) found\n", priv->next_addr);
}
+static void remove_inactive_children(struct uclass *uc, struct udevice *bus)
+{
+ uclass_foreach_dev(bus, uc) {
+ struct udevice *dev, *next;
+
+ if (!device_active(bus))
+ continue;
+ device_foreach_child_safe(dev, next, bus) {
+ if (!device_active(dev))
+ device_unbind(dev);
+ }
+ }
+}
+
int usb_init(void)
{
int controllers_initialized = 0;
@@ -273,6 +284,15 @@ int usb_init(void)
}
debug("scan end\n");
+
+ /* Remove any devices that were not found on this scan */
+ remove_inactive_children(uc, bus);
+
+ ret = uclass_get(UCLASS_USB_HUB, &uc);
+ if (ret)
+ return ret;
+ remove_inactive_children(uc, bus);
+
/* if we were not able to find at least one working bus, bail out */
if (!count)
printf("No controllers found\n");
@@ -282,6 +302,14 @@ int usb_init(void)
return usb_started ? 0 : -1;
}
+/*
+ * TODO(sjg@chromium.org): Remove this legacy function. At present it is needed
+ * to support boards which use driver model for USB but not Ethernet, and want
+ * to use USB Ethernet.
+ *
+ * The #if clause is here to ensure that remains the only case.
+ */
+#if !defined(CONFIG_DM_ETH) && defined(CONFIG_USB_HOST_ETHER)
static struct usb_device *find_child_devnum(struct udevice *parent, int devnum)
{
struct usb_device *udev;
@@ -315,6 +343,7 @@ struct usb_device *usb_get_dev_index(struct udevice *bus, int index)
return find_child_devnum(dev, devnum);
}
+#endif
int usb_post_bind(struct udevice *dev)
{
@@ -494,14 +523,15 @@ error:
}
/**
- * usb_find_emul_child() - Find an existing device for emulated devices
+ * usb_find_child() - Find an existing device which matches our needs
+ *
+ *
*/
-static int usb_find_emul_child(struct udevice *parent,
- struct usb_device_descriptor *desc,
- struct usb_interface_descriptor *iface,
- struct udevice **devp)
+static int usb_find_child(struct udevice *parent,
+ struct usb_device_descriptor *desc,
+ struct usb_interface_descriptor *iface,
+ struct udevice **devp)
{
-#ifdef CONFIG_SANDBOX
struct udevice *dev;
*devp = NULL;
@@ -520,7 +550,7 @@ static int usb_find_emul_child(struct udevice *parent,
return 0;
}
}
-#endif
+
return -ENOENT;
}
@@ -580,8 +610,8 @@ int usb_scan_device(struct udevice *parent, int port,
debug("read_descriptor for '%s': ret=%d\n", parent->name, ret);
if (ret)
return ret;
- ret = usb_find_emul_child(parent, &udev->descriptor, iface, &dev);
- debug("** usb_find_emul_child returns %d\n", ret);
+ ret = usb_find_child(parent, &udev->descriptor, iface, &dev);
+ debug("** usb_find_child returns %d\n", ret);
if (ret) {
if (ret != -ENOENT)
return ret;
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
index 10f6b5d..233a0e4 100644
--- a/drivers/usb/musb-new/musb_uboot.c
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -1,4 +1,5 @@
#include <common.h>
+#include <console.h>
#include <watchdog.h>
#ifdef CONFIG_ARCH_SUNXI
#include <asm/arch/usb_phy.h>
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index a146c08..5eb8d19 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -166,6 +166,17 @@ static void USBC_ConfigFIFO_Base(void)
}
/******************************************************************************
+ * Needed for the DFU polling magic
+ ******************************************************************************/
+
+static u8 last_int_usb;
+
+bool dfu_usb_get_reset(void)
+{
+ return !!(last_int_usb & MUSB_INTR_RESET);
+}
+
+/******************************************************************************
* MUSB Glue code
******************************************************************************/
@@ -176,6 +187,7 @@ static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
/* read and flush interrupts */
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ last_int_usb = musb->int_usb;
if (musb->int_usb)
musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 556a55f..f15c964 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -15,8 +15,10 @@
* logo can be placed in the upper left corner and additional board
* information strings (that normally goes to serial port) can be drawn.
*
- * The console driver can use the standard PC keyboard interface (i8042)
- * for character input. Character output goes to a memory mapped video
+ * The console driver can use a keyboard interface for character input
+ * but this is deprecated. Only rk51 uses it.
+ *
+ * Character output goes to a memory-mapped video
* framebuffer with little or big-endian organisation.
* With environment setting 'console=serial' the console i/o can be
* forced to serial port.
@@ -38,18 +40,10 @@
* VIDEO_DATA_FORMAT - graphical data format GDF
* VIDEO_FB_ADRS - start of video memory
*
- * CONFIG_I8042_KBD - AT Keyboard driver for i8042
* VIDEO_KBD_INIT_FCT - init function for keyboard
* VIDEO_TSTC_FCT - keyboard_tstc function
* VIDEO_GETC_FCT - keyboard_getc function
*
- * CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with
- * delay loop in VIDEO_TSTC_FCT (i8042)
- *
- * CONFIG_SYS_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
- * CONFIG_CONSOLE_TIME - display time/date in upper right
- * corner, needs CONFIG_CMD_DATE and
- * CONFIG_CONSOLE_CURSOR
* CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner.
* Use CONFIG_SPLASH_SCREEN_ALIGN with
* environment variable "splashpos" to place
@@ -165,19 +159,6 @@
#define VIDEO_FB_ADRS (pGD->frameAdrs)
/*
- * Console device defines with i8042 keyboard controller
- * Any other keyboard controller must change this section
- */
-
-#ifdef CONFIG_I8042_KBD
-#include <i8042.h>
-
-#define VIDEO_KBD_INIT_FCT i8042_kbd_init()
-#define VIDEO_TSTC_FCT i8042_tstc
-#define VIDEO_GETC_FCT i8042_getc
-#endif
-
-/*
* Console device
*/
@@ -198,9 +179,6 @@
/*
* Cursor definition:
- * CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c)
- * to let the cursor blink. Uses the macros
- * CURSOR_OFF and CURSOR_ON.
* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No
* blinking is provided. Uses the macros CURSOR_SET
* and CURSOR_OFF.
@@ -210,42 +188,29 @@
* must disable the hardware register of the graphic
* chip. Otherwise a blinking field is displayed
*/
-#if !defined(CONFIG_CONSOLE_CURSOR) && \
- !defined(CONFIG_VIDEO_SW_CURSOR) && \
- !defined(CONFIG_VIDEO_HW_CURSOR)
+#if !defined(CONFIG_VIDEO_SW_CURSOR) && !defined(CONFIG_VIDEO_HW_CURSOR)
/* no Cursor defined */
#define CURSOR_ON
#define CURSOR_OFF
#define CURSOR_SET
#endif
-#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
-#if defined(CURSOR_ON) || \
- (defined(CONFIG_CONSOLE_CURSOR) && defined(CONFIG_VIDEO_SW_CURSOR))
-#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
- or CONFIG_VIDEO_HW_CURSOR can be defined
+#if defined(CONFIG_VIDEO_SW_CURSOR)
+#if defined(CONFIG_VIDEO_HW_CURSOR)
+#error only one of CONFIG_VIDEO_SW_CURSOR or CONFIG_VIDEO_HW_CURSOR can be \
+ defined
#endif
void console_cursor(int state);
#define CURSOR_ON console_cursor(1)
#define CURSOR_OFF console_cursor(0)
#define CURSOR_SET video_set_cursor()
-#endif /* CONFIG_CONSOLE_CURSOR || CONFIG_VIDEO_SW_CURSOR */
-
-#ifdef CONFIG_CONSOLE_CURSOR
-#ifndef CONFIG_CONSOLE_TIME
-#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
-#endif
-#ifndef CONFIG_I8042_KBD
-#warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
-#endif
-#endif /* CONFIG_CONSOLE_CURSOR */
-
+#endif /* CONFIG_VIDEO_SW_CURSOR */
#ifdef CONFIG_VIDEO_HW_CURSOR
#ifdef CURSOR_ON
-#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
- or CONFIG_VIDEO_HW_CURSOR can be defined
+#error only one of CONFIG_VIDEO_SW_CURSOR or CONFIG_VIDEO_HW_CURSOR can be \
+ defined
#endif
#define CURSOR_ON
#define CURSOR_OFF
@@ -626,7 +591,7 @@ static void video_putchar(int xx, int yy, unsigned char c)
video_drawchars(xx, yy + video_logo_height, &c, 1);
}
-#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
+#if defined(CONFIG_VIDEO_SW_CURSOR)
static void video_set_cursor(void)
{
if (cursor_state)
@@ -651,27 +616,6 @@ static void video_invertchar(int xx, int yy)
void console_cursor(int state)
{
-#ifdef CONFIG_CONSOLE_TIME
- struct rtc_time tm;
- char info[16];
-
- /* time update only if cursor is on (faster scroll) */
- if (state) {
- rtc_get(&tm);
-
- sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
- tm.tm_sec);
- video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
- VIDEO_INFO_Y, (uchar *) info);
-
- sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
- tm.tm_year);
- video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
- VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT,
- (uchar *) info);
- }
-#endif
-
if (cursor_state != state) {
if (cursor_state) {
/* turn off the cursor */