From 1d8a078b29433f35608cd0fbd94d0feed3bfb33d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 26 Aug 2015 06:17:27 -0700 Subject: net: e1000: Fix build warnings for 32-bit commit 6497e37 "net: e1000: Support 64-bit physical address" causes compiler warnings on 32-bit U-Boot build below. drivers/net/e1000.c: In function 'e1000_configure_tx': drivers/net/e1000.c:4982:2: warning: right shift count >= width of type [enabled by default] drivers/net/e1000.c: In function 'e1000_configure_rx': drivers/net/e1000.c:5126:2: warning: right shift count >= width of type [enabled by default] This commit fixes the build warnings. Signed-off-by: Bin Meng Acked-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/e1000.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 6f74d30..7b830ff 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -4978,8 +4978,8 @@ e1000_configure_tx(struct e1000_hw *hw) unsigned long tipg, tarc; uint32_t ipgr1, ipgr2; - E1000_WRITE_REG(hw, TDBAL, (unsigned long)tx_base & 0xffffffff); - E1000_WRITE_REG(hw, TDBAH, (unsigned long)tx_base >> 32); + E1000_WRITE_REG(hw, TDBAL, lower_32_bits((unsigned long)tx_base)); + E1000_WRITE_REG(hw, TDBAH, upper_32_bits((unsigned long)tx_base)); E1000_WRITE_REG(hw, TDLEN, 128); @@ -5103,6 +5103,7 @@ e1000_configure_rx(struct e1000_hw *hw) { unsigned long rctl, ctrl_ext; rx_tail = 0; + /* make sure receives are disabled while setting up the descriptors */ rctl = E1000_READ_REG(hw, RCTL); E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); @@ -5122,8 +5123,8 @@ e1000_configure_rx(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); } /* Setup the Base and Length of the Rx Descriptor Ring */ - E1000_WRITE_REG(hw, RDBAL, (unsigned long)rx_base & 0xffffffff); - E1000_WRITE_REG(hw, RDBAH, (unsigned long)rx_base >> 32); + E1000_WRITE_REG(hw, RDBAL, lower_32_bits((unsigned long)rx_base)); + E1000_WRITE_REG(hw, RDBAH, upper_32_bits((unsigned long)rx_base)); E1000_WRITE_REG(hw, RDLEN, 128); -- cgit v1.1 From 153e1dda2ff62b0ecffa186a950bbfb82f1b474d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 13 Aug 2015 00:29:16 -0700 Subject: video: coreboot: Save VESA mode for future use When booting as a coreboot payload, the framebuffer details are passed from coreboot via configuration tables. We save these information into vesa_mode_info structure for future use. Signed-off-by: Bin Meng --- drivers/pci/pci_rom.c | 2 +- drivers/video/coreboot_fb.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 26db3ca..b9a3990 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -187,7 +187,7 @@ int pci_rom_load(struct pci_rom_header *rom_header, return 0; } -static struct vbe_mode_info mode_info; +struct vbe_mode_info mode_info; int vbe_get_video_info(struct graphic_device *gdev) { diff --git a/drivers/video/coreboot_fb.c b/drivers/video/coreboot_fb.c index 56c35c1..4790ef1 100644 --- a/drivers/video/coreboot_fb.c +++ b/drivers/video/coreboot_fb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "videomodes.h" @@ -17,6 +18,26 @@ */ GraphicDevice ctfb; +static void save_vesa_mode(void) +{ + struct vesa_mode_info *vesa = &mode_info.vesa; + struct cb_framebuffer *fb = lib_sysinfo.framebuffer; + + vesa->x_resolution = fb->x_resolution; + vesa->y_resolution = fb->y_resolution; + vesa->bits_per_pixel = fb->bits_per_pixel; + vesa->bytes_per_scanline = fb->bytes_per_line; + vesa->phys_base_ptr = fb->physical_address; + vesa->red_mask_size = fb->red_mask_size; + vesa->red_mask_pos = fb->red_mask_pos; + vesa->green_mask_size = fb->green_mask_size; + vesa->green_mask_pos = fb->green_mask_pos; + vesa->blue_mask_size = fb->blue_mask_size; + vesa->blue_mask_pos = fb->blue_mask_pos; + vesa->reserved_mask_size = fb->reserved_mask_size; + vesa->reserved_mask_pos = fb->reserved_mask_pos; +} + static int parse_coreboot_table_fb(GraphicDevice *gdev) { struct cb_framebuffer *fb = lib_sysinfo.framebuffer; @@ -81,5 +102,8 @@ void *video_hw_init(void) memset((void *)gdev->pciBase, 0, gdev->winSizeX * gdev->winSizeY * gdev->gdfBytesPP); + /* Initialize vesa_mode_info structure */ + save_vesa_mode(); + return (void *)gdev; } -- cgit v1.1 From 1916ec12672f76b9a9b0c581e41dad8afea2187d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 13 Aug 2015 00:29:17 -0700 Subject: x86: Set up video framebuffer for coreboot before loading kernel Currenlty we only set up video framebuffer when VIDEO_VESA driver is used. With coreboot, VIDEO_COREBOOT driver is used instead. Since we already saved VESA mode in the VIDEO_COREBOOT driver, now we can also set up video framebuffer for coreboot before loading Linux kernel. Signed-off-by: Bin Meng --- drivers/pci/pci_rom.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index b9a3990..d244543 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -232,7 +232,6 @@ int vbe_get_video_info(struct graphic_device *gdev) void setup_video(struct screen_info *screen_info) { -#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE struct vesa_mode_info *vesa = &mode_info.vesa; /* Sanity test on VESA parameters */ @@ -258,7 +257,6 @@ void setup_video(struct screen_info *screen_info) screen_info->blue_pos = vesa->blue_mask_pos; screen_info->rsvd_size = vesa->reserved_mask_size; screen_info->rsvd_pos = vesa->reserved_mask_pos; -#endif } int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method) -- cgit v1.1 From 08fc7b8fac1d27d7e9f964309cbc32de0abd2c0d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 20 Aug 2015 06:40:17 -0700 Subject: dm: pci: Support selected device/driver binding before relocation On some platforms pci devices behind bridge need to be probed (eg: a pci uart on recent x86 chipset) before relocation. But we won't bind all devices found during the enumeration. Only devices whose driver with DM_FLAG_PRE_RELOC set will be bound. Any other generic devices except bridges won't be bound. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/pci/pci-uclass.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 7d41d56..4160274 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -461,6 +461,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, int n_ents; int ret; char name[30], *str; + bool bridge; *devp = NULL; @@ -480,6 +481,17 @@ static int pci_find_and_bind_driver(struct udevice *parent, continue; drv = entry->driver; + + /* + * In the pre-relocation phase, we only bind devices + * whose driver has the DM_FLAG_PRE_RELOC set, to save + * precious memory space as on some platforms as that + * space is pretty limited (ie: using Cache As RAM). + */ + if (!(gd->flags & GD_FLG_RELOC) && + !(drv->flags & DM_FLAG_PRE_RELOC)) + return 0; + /* * We could pass the descriptor to the driver as * platdata (instead of NULL) and allow its bind() @@ -499,14 +511,23 @@ static int pci_find_and_bind_driver(struct udevice *parent, } } + bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI; + /* + * In the pre-relocation phase, we only bind bridge devices to save + * precious memory space as on some platforms as that space is pretty + * limited (ie: using Cache As RAM). + */ + if (!(gd->flags & GD_FLG_RELOC) && !bridge) + return 0; + /* Bind a generic driver so that the device can be used */ sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf), PCI_FUNC(bdf)); str = strdup(name); if (!str) return -ENOMEM; - drv = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI ? "pci_bridge_drv" : - "pci_generic_drv"; + drv = bridge ? "pci_bridge_drv" : "pci_generic_drv"; + ret = device_bind_driver(parent, drv, str, devp); if (ret) { debug("%s: Failed to bind generic driver: %d", __func__, ret); @@ -589,11 +610,13 @@ int pci_bind_bus_devices(struct udevice *bus) return ret; /* Update the platform data */ - pplat = dev_get_parent_platdata(dev); - pplat->devfn = PCI_MASK_BUS(bdf); - pplat->vendor = vendor; - pplat->device = device; - pplat->class = class; + if (dev) { + pplat = dev_get_parent_platdata(dev); + pplat->devfn = PCI_MASK_BUS(bdf); + pplat->vendor = vendor; + pplat->device = device; + pplat->class = class; + } } return 0; @@ -717,10 +740,6 @@ static int pci_uclass_post_probe(struct udevice *bus) { int ret; - /* Don't scan buses before relocation */ - if (!(gd->flags & GD_FLG_RELOC)) - return 0; - debug("%s: probing bus %d\n", __func__, bus->seq); ret = pci_bind_bus_devices(bus); if (ret) -- cgit v1.1 From 348b744b7c6528c0509e2a0b0740be3ce949497f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 20 Aug 2015 06:40:23 -0700 Subject: x86: fsp: Call fsp_init_phase_pci() in pci_uclass_post_probe() Per Intel FSP specification, we should call FSP notify API to inform FSP that PCI enumeration has been done so that FSP will do any necessary initialization as required by the chipset's BIOS Writer's Guide (BWG). Unfortunately we have to put this call here as with driver model, the enumeration is all done on a lazy basis as needed, so until something is touched on PCI it won't happen. Note we only call this after U-Boot is relocated and root bus has finished probing. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/pci/pci-uclass.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 4160274..c90e7ac 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -14,6 +14,9 @@ #include #include #include +#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) +#include +#endif DECLARE_GLOBAL_DATA_PTR; @@ -749,6 +752,24 @@ static int pci_uclass_post_probe(struct udevice *bus) ret = pci_auto_config_devices(bus); #endif +#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) + /* + * Per Intel FSP specification, we should call FSP notify API to + * inform FSP that PCI enumeration has been done so that FSP will + * do any necessary initialization as required by the chipset's + * BIOS Writer's Guide (BWG). + * + * Unfortunately we have to put this call here as with driver model, + * the enumeration is all done on a lazy basis as needed, so until + * something is touched on PCI it won't happen. + * + * Note we only call this 1) after U-Boot is relocated, and 2) + * root bus has finished probing. + */ + if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) + ret = fsp_init_phase_pci(); +#endif + return ret < 0 ? ret : 0; } -- cgit v1.1 From c78dfb4fd2cc8dbcd0baa3d180aeef1a06b1f062 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 21 Aug 2015 00:18:51 -0700 Subject: x86: superio: Add keyboard controller support to smsc_lpc47m driver Add an api to enable and configure the integrated keyboard controller on SMSC LPC47m superio chipset. It also adds several macros to help future extension. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/misc/smsc_lpc47m.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/smsc_lpc47m.c b/drivers/misc/smsc_lpc47m.c index 1e50d5b..fcce3a4 100644 --- a/drivers/misc/smsc_lpc47m.c +++ b/drivers/misc/smsc_lpc47m.c @@ -22,7 +22,7 @@ static void pnp_exit_conf_state(u16 dev) outb(0xaa, port); } -void lpc47m_enable_serial(u16 dev, u16 iobase, u8 irq) +void lpc47m_enable_serial(uint dev, uint iobase, uint irq) { pnp_enter_conf_state(dev); pnp_set_logical_device(dev); @@ -32,3 +32,14 @@ void lpc47m_enable_serial(u16 dev, u16 iobase, u8 irq) pnp_set_enable(dev, 1); pnp_exit_conf_state(dev); } + +void lpc47m_enable_kbc(uint dev, uint irq0, uint irq1) +{ + pnp_enter_conf_state(dev); + pnp_set_logical_device(dev); + pnp_set_enable(dev, 0); + pnp_set_irq(dev, PNP_IDX_IRQ0, irq0); + pnp_set_irq(dev, PNP_IDX_IRQ1, irq1); + pnp_set_enable(dev, 1); + pnp_exit_conf_state(dev); +} -- cgit v1.1 From dce54dd6c70e6af9a1b506ed45c0cfc9a90fcc92 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 20 Aug 2015 06:40:26 -0700 Subject: dm: pci: Save devfn without bus number in pci_uclass_child_post_bind() In pci_uclass_child_post_bind(), bdf is extracted from fdt_pci_addr. Mask bus number before save it to pplat->devfn. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/pci/pci-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index c90e7ac..2d12344 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -794,8 +794,8 @@ static int pci_uclass_child_post_bind(struct udevice *dev) if (ret != -ENOENT) return -EINVAL; } else { - /* extract the bdf from fdt_pci_addr */ - pplat->devfn = addr.phys_hi & 0xffff00; + /* extract the devfn from fdt_pci_addr */ + pplat->devfn = addr.phys_hi & 0xff00; } return 0; -- cgit v1.1 From e7cc0b6f006e547e86b111187d192ea8211c7576 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 22 Aug 2015 15:58:58 -0600 Subject: x86: gpio: Correct calls to _ich6_gpio_set_direction() These calls seem to be incorrect. The function expects an I/O address but the existing callers pass the value at an I/O address. Fix it. Signed-off-by: Simon Glass --- drivers/gpio/intel_ich6_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index cb408a4..fd1f287 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -410,7 +410,7 @@ static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset) { struct ich6_bank_priv *bank = dev_get_priv(dev); - return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0); + return _ich6_gpio_set_direction(bank->io_sel, offset, 0); } static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset, @@ -419,7 +419,7 @@ static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset, int ret; struct ich6_bank_priv *bank = dev_get_priv(dev); - ret = _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1); + ret = _ich6_gpio_set_direction(bank->io_sel, offset, 1); if (ret) return ret; -- cgit v1.1 From df1c9eb505a194e2957356d9e0d730dbe03ed45d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 22 Aug 2015 15:58:59 -0600 Subject: x86: gpio: Tidy up gpio_ich6_get_base() and callers This function can return an error. Correct the detection of this error so that it works even with large 32-bit addresses. The return value is set up for returning an I/O address but the function is also used to return a memory-mapped address. Adjust the return code to make this work. Also add a bit more debugging. Signed-off-by: Simon Glass --- drivers/gpio/intel_ich6_gpio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index fd1f287..67bf0a2 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -75,7 +75,7 @@ static int gpio_ich6_get_base(unsigned long base) /* Is the device present? */ tmpword = x86_pci_read_config16(pci_dev, PCI_VENDOR_ID); if (tmpword != PCI_VENDOR_ID_INTEL) { - debug("%s: wrong VendorID\n", __func__); + debug("%s: wrong VendorID %x\n", __func__, tmpword); return -ENODEV; } @@ -144,7 +144,7 @@ static int gpio_ich6_get_base(unsigned long base) * at the offset that we just read. Bit 0 indicates that it's * an I/O address, not a memory address, so mask that off. */ - return tmplong & 0xfffc; + return tmplong & 1 ? tmplong & ~3 : tmplong & ~15; } static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value) @@ -324,7 +324,7 @@ int gpio_ich6_pinctrl_init(void) debug("%s: io-base offset not present\n", __func__); } else { iobase = gpio_ich6_get_base(iobase_offset); - if (iobase < 0) { + if (IS_ERR_VALUE(iobase)) { debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase); return -EINVAL; -- cgit v1.1 From 5e653b0609cd256572a2e97a8449489ca84de017 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:03 -0700 Subject: x86: i8042: Remove unused codes Remove unused CONFIG_USE_CPCIDVI wrapped codes. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/input/i8042.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 1769c5e..87220ca 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -10,16 +10,6 @@ /* includes */ #include -#include - -#ifdef CONFIG_USE_CPCIDVI -extern u8 gt_cpcidvi_in8(u32 offset); -extern void gt_cpcidvi_out8(u32 offset, u8 data); - -#define in8(a) gt_cpcidvi_in8(a) -#define out8(a, b) gt_cpcidvi_out8(a, b) -#endif - #include /* defines */ @@ -365,13 +355,6 @@ int i8042_kbd_init(void) if (!kbd_controller_present() || board_i8042_skip()) return -1; -#ifdef CONFIG_USE_CPCIDVI - penv = getenv("console"); - if (penv != NULL) { - if (strncmp(penv, "serial", 7) == 0) - return -1; - } -#endif /* Init keyboard device (default US layout) */ keymap = KBD_US; penv = getenv("keymap"); -- cgit v1.1 From 3928d66a5e7f55a860f2dd150231f51c8cc9d5fc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:04 -0700 Subject: x86: i8042: Reorder static functions Reorder those static function so that their declarations can be removed. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/input/i8042.c | 490 +++++++++++++++++++++++--------------------------- 1 file changed, 222 insertions(+), 268 deletions(-) (limited to 'drivers') diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 87220ca..126b222 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -27,18 +27,6 @@ static int kbd_mapping = KBD_US; /* default US keyboard */ static int kbd_flags = NORMAL; /* after reset */ static int kbd_state; /* unshift code */ -static void kbd_conv_char(unsigned char scan_code); -static void kbd_led_set(void); -static void kbd_normal(unsigned char scan_code); -static void kbd_shift(unsigned char scan_code); -static void kbd_ctrl(unsigned char scan_code); -static void kbd_num(unsigned char scan_code); -static void kbd_caps(unsigned char scan_code); -static void kbd_scroll(unsigned char scan_code); -static void kbd_alt(unsigned char scan_code); -static int kbd_input_empty(void); -static int kbd_reset(void); - static unsigned char kbd_fct_map[144] = { /* kbd_fct_map table for scan code */ 0, AS, AS, AS, AS, AS, AS, AS, /* scan 0- 7 */ @@ -288,8 +276,230 @@ static unsigned char ext_key_map[] = { 0x00 /* map end */ }; +static int kbd_input_empty(void) +{ + int kbdTimeout = KBD_TIMEOUT * 1000; + + while ((in8(I8042_STATUS_REG) & I8042_STATUS_IN_DATA) && kbdTimeout--) + udelay(1); + + return kbdTimeout != -1; +} + +static int wait_until_kbd_output_full(void) +{ + int kbdTimeout = KBD_TIMEOUT * 1000; + + while (((in8(I8042_STATUS_REG) & 0x01) == 0) && kbdTimeout--) + udelay(1); + + return kbdTimeout != -1; +} + +static void kbd_led_set(void) +{ + kbd_input_empty(); + out8(I8042_DATA_REG, 0xed); /* SET LED command */ + kbd_input_empty(); + out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ +} + +static void kbd_normal(unsigned char scan_code) +{ + unsigned char chr; + + 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; + } +} + +static void kbd_shift(unsigned char scan_code) +{ + if ((kbd_flags & BRK) == BRK) { + kbd_state = AS; + kbd_flags &= (~SHIFT); + } else { + kbd_state = SH; + kbd_flags |= SHIFT; + } +} + +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; + } +} + +static void kbd_num(unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) { + kbd_flags ^= NUM; + kbd_state = (kbd_flags & NUM) ? AS : NM; + kbd_led_set(); /* update keyboard LED */ + } +} + +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; + } +} + +static void kbd_caps(unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) { + kbd_flags ^= CAPS; + kbd_led_set(); /* update keyboard LED */ + } +} + +static void kbd_scroll(unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) { + kbd_flags ^= STP; + kbd_led_set(); /* update keyboard LED */ + if (kbd_flags & STP) + kbd_input = 0x13; + else + kbd_input = 0x11; + } +} + +static void kbd_conv_char(unsigned char scan_code) +{ + 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; + } + return; +} + /******************************************************************************/ +static int kbd_reset(void) +{ + /* KB Reset */ + if (kbd_input_empty() == 0) + return -1; + + out8(I8042_DATA_REG, 0xff); + + if (wait_until_kbd_output_full() == 0) + return -1; + + if (in8(I8042_DATA_REG) != 0xfa) /* ACK */ + return -1; + + if (wait_until_kbd_output_full() == 0) + return -1; + + if (in8(I8042_DATA_REG) != 0xaa) /* Test Pass*/ + return -1; + + if (kbd_input_empty() == 0) + return -1; + + /* Set KBC mode */ + out8(I8042_COMMAND_REG, 0x60); + + if (kbd_input_empty() == 0) + return -1; + + out8(I8042_DATA_REG, 0x45); + + if (kbd_input_empty() == 0) + return -1; + + /* Enable Keyboard */ + out8(I8042_COMMAND_REG, 0xae); + if (kbd_input_empty() == 0) + return -1; + + out8(I8042_COMMAND_REG, 0x60); + if (kbd_input_empty() == 0) + return -1; + + out8(I8042_DATA_REG, 0xf4); + if (kbd_input_empty() == 0) + return -1; + + return 0; +} + static int kbd_controller_present(void) { return in8(I8042_STATUS_REG) != 0xff; @@ -342,7 +552,6 @@ int i8042_disable(void) return 0; } - /******************************************************************************* * * i8042_kbd_init - reset keyboard and init state flags @@ -439,258 +648,3 @@ int i8042_getc(struct stdio_dev *dev) kbd_input = -1; return ret_chr; } - - -/******************************************************************************/ - -static void kbd_conv_char(unsigned char scan_code) -{ - 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 CP: - kbd_caps(scan_code); - break; - case ST: - kbd_scroll(scan_code); - break; - case AK: - kbd_alt(scan_code); - break; - } - return; -} - - -/******************************************************************************/ - -static void kbd_normal(unsigned char scan_code) -{ - unsigned char chr; - - 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; - } -} - - -/******************************************************************************/ - -static void kbd_shift(unsigned char scan_code) -{ - if ((kbd_flags & BRK) == BRK) { - kbd_state = AS; - kbd_flags &= (~SHIFT); - } else { - kbd_state = SH; - kbd_flags |= SHIFT; - } -} - - -/******************************************************************************/ - -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; - } -} - - -/******************************************************************************/ - -static void kbd_caps(unsigned char scan_code) -{ - if ((kbd_flags & BRK) == NORMAL) { - kbd_flags ^= CAPS; - kbd_led_set(); /* update keyboard LED */ - } -} - - -/******************************************************************************/ - -static void kbd_num(unsigned char scan_code) -{ - if ((kbd_flags & BRK) == NORMAL) { - kbd_flags ^= NUM; - kbd_state = (kbd_flags & NUM) ? AS : NM; - kbd_led_set(); /* update keyboard LED */ - } -} - - -/******************************************************************************/ - -static void kbd_scroll(unsigned char scan_code) -{ - if ((kbd_flags & BRK) == NORMAL) { - kbd_flags ^= STP; - kbd_led_set(); /* update keyboard LED */ - if (kbd_flags & STP) - kbd_input = 0x13; - else - kbd_input = 0x11; - } -} - -/******************************************************************************/ - -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; - } -} - - -/******************************************************************************/ - -static void kbd_led_set(void) -{ - kbd_input_empty(); - out8(I8042_DATA_REG, 0xed); /* SET LED command */ - kbd_input_empty(); - out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ -} - - -/******************************************************************************/ - -static int kbd_input_empty(void) -{ - int kbdTimeout = KBD_TIMEOUT * 1000; - - while ((in8(I8042_STATUS_REG) & I8042_STATUS_IN_DATA) && kbdTimeout--) - udelay(1); - - return kbdTimeout != -1; -} - -/******************************************************************************/ - -static int wait_until_kbd_output_full(void) -{ - int kbdTimeout = KBD_TIMEOUT * 1000; - - while (((in8(I8042_STATUS_REG) & 0x01) == 0) && kbdTimeout--) - udelay(1); - - return kbdTimeout != -1; -} - -/******************************************************************************/ - -static int kbd_reset(void) -{ - /* KB Reset */ - if (kbd_input_empty() == 0) - return -1; - - out8(I8042_DATA_REG, 0xff); - - if (wait_until_kbd_output_full() == 0) - return -1; - - if (in8(I8042_DATA_REG) != 0xfa) /* ACK */ - return -1; - - if (wait_until_kbd_output_full() == 0) - return -1; - - if (in8(I8042_DATA_REG) != 0xaa) /* Test Pass*/ - return -1; - - if (kbd_input_empty() == 0) - return -1; - - /* Set KBC mode */ - out8(I8042_COMMAND_REG, 0x60); - - if (kbd_input_empty() == 0) - return -1; - - out8(I8042_DATA_REG, 0x45); - - if (kbd_input_empty() == 0) - return -1; - - /* Enable Keyboard */ - out8(I8042_COMMAND_REG, 0xae); - if (kbd_input_empty() == 0) - return -1; - - out8(I8042_COMMAND_REG, 0x60); - if (kbd_input_empty() == 0) - return -1; - - out8(I8042_DATA_REG, 0xf4); - if (kbd_input_empty() == 0) - return -1; - - return 0; -} -- cgit v1.1 From 835dd000503591d8eb59a191f7220768898737b3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:05 -0700 Subject: x86: i8042: Clean up the driver per coding convention - Rename CamelCase variables to conform U-Boot coding convention - Rename wait_until_kbd_output_full() to kbd_output_full() - Change to use macros for i8042 command and control register bits Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/input/i8042.c | 230 ++++++++++++++++++++++++++------------------------ 1 file changed, 118 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 126b222..e8f59df 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -10,27 +10,30 @@ /* includes */ #include +#include #include /* 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 blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; +static int blink_count = CONFIG_SYS_CONSOLE_BLINK_COUNT; static int cursor_state; #endif /* 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 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 0- 7 */ - AS, AS, AS, AS, AS, AS, AS, AS, /* scan 8- F */ + 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 */ @@ -52,8 +55,8 @@ static unsigned char kbd_fct_map[144] = { static unsigned char kbd_key_map[2][5][144] = { { /* US keyboard */ { /* unshift code */ - 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ - '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -72,8 +75,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ }, { /* shift code */ - 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 0- 7 */ - '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -92,8 +95,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ }, { /* control code */ - 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ - 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ + 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 */ @@ -112,8 +115,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ }, { /* non numeric code */ - 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ - '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -132,30 +135,30 @@ static unsigned char kbd_key_map[2][5][144] = { 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 0 - 7 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 8 - F */ - 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, /* 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 */ + { /* German keyboard */ { /* unshift code */ - 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ - '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -174,8 +177,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ }, { /* shift code */ - 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 0- 7 */ - '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -194,8 +197,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ }, { /* control code */ - 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ - 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ + 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 */ @@ -214,8 +217,8 @@ static unsigned char kbd_key_map[2][5][144] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ }, { /* non numeric code */ - 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ - '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ + 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 */ @@ -233,23 +236,23 @@ static unsigned char kbd_key_map[2][5][144] = { '\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 0 - 7 */ - '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 8 - F */ - '@', 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 */ + { /* 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 */ } @@ -278,30 +281,30 @@ static unsigned char ext_key_map[] = { static int kbd_input_empty(void) { - int kbdTimeout = KBD_TIMEOUT * 1000; + int kbd_timeout = KBD_TIMEOUT * 1000; - while ((in8(I8042_STATUS_REG) & I8042_STATUS_IN_DATA) && kbdTimeout--) + while ((in8(I8042_STS_REG) & STATUS_IBF) && kbd_timeout--) udelay(1); - return kbdTimeout != -1; + return kbd_timeout != -1; } -static int wait_until_kbd_output_full(void) +static int kbd_output_full(void) { - int kbdTimeout = KBD_TIMEOUT * 1000; + int kbd_timeout = KBD_TIMEOUT * 1000; - while (((in8(I8042_STATUS_REG) & 0x01) == 0) && kbdTimeout--) + while (((in8(I8042_STS_REG) & STATUS_OBF) == 0) && kbd_timeout--) udelay(1); - return kbdTimeout != -1; + return kbd_timeout != -1; } static void kbd_led_set(void) { kbd_input_empty(); - out8(I8042_DATA_REG, 0xed); /* SET LED command */ + out8(I8042_DATA_REG, CMD_SET_KBD_LED); kbd_input_empty(); - out8(I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ + out8(I8042_DATA_REG, (kbd_flags & 0x7)); } static void kbd_normal(unsigned char scan_code) @@ -315,7 +318,7 @@ static void kbd_normal(unsigned char scan_code) /* if caps lock convert upper to lower */ if (((kbd_flags & CAPS) == CAPS) && - (chr >= 'a' && chr <= 'z')) { + (chr >= 'a' && chr <= 'z')) { chr -= 'a' - 'A'; } kbd_input = chr; @@ -349,7 +352,7 @@ static void kbd_num(unsigned char scan_code) if ((kbd_flags & BRK) == NORMAL) { kbd_flags ^= NUM; kbd_state = (kbd_flags & NUM) ? AS : NM; - kbd_led_set(); /* update keyboard LED */ + kbd_led_set(); } } @@ -368,7 +371,7 @@ static void kbd_caps(unsigned char scan_code) { if ((kbd_flags & BRK) == NORMAL) { kbd_flags ^= CAPS; - kbd_led_set(); /* update keyboard LED */ + kbd_led_set(); } } @@ -376,7 +379,7 @@ static void kbd_scroll(unsigned char scan_code) { if ((kbd_flags & BRK) == NORMAL) { kbd_flags ^= STP; - kbd_led_set(); /* update keyboard LED */ + kbd_led_set(); if (kbd_flags & STP) kbd_input = 0x13; else @@ -399,8 +402,8 @@ static void kbd_conv_char(unsigned char scan_code) 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 */ + kbd_flags ^= BRK; /* reset the break flag */ + kbd_flags ^= E1; /* bitwise EXOR with E1 flag */ } return; } @@ -445,55 +448,57 @@ static void kbd_conv_char(unsigned char scan_code) kbd_scroll(scan_code); break; } + return; } -/******************************************************************************/ - static int kbd_reset(void) { /* KB Reset */ if (kbd_input_empty() == 0) return -1; - out8(I8042_DATA_REG, 0xff); + out8(I8042_DATA_REG, CMD_RESET_KBD); - if (wait_until_kbd_output_full() == 0) + if (kbd_output_full() == 0) return -1; - if (in8(I8042_DATA_REG) != 0xfa) /* ACK */ + if (in8(I8042_DATA_REG) != KBD_ACK) return -1; - if (wait_until_kbd_output_full() == 0) + if (kbd_output_full() == 0) return -1; - if (in8(I8042_DATA_REG) != 0xaa) /* Test Pass*/ + if (in8(I8042_DATA_REG) != KBD_POR) return -1; if (kbd_input_empty() == 0) return -1; /* Set KBC mode */ - out8(I8042_COMMAND_REG, 0x60); + out8(I8042_CMD_REG, CMD_WR_CONFIG); if (kbd_input_empty() == 0) return -1; - out8(I8042_DATA_REG, 0x45); + out8(I8042_DATA_REG, + CONFIG_AT_TRANS | CONFIG_SET_BIST | CONFIG_KIRQ_EN); if (kbd_input_empty() == 0) return -1; /* Enable Keyboard */ - out8(I8042_COMMAND_REG, 0xae); + out8(I8042_CMD_REG, CMD_KBD_EN); if (kbd_input_empty() == 0) return -1; - out8(I8042_COMMAND_REG, 0x60); + out8(I8042_CMD_REG, CMD_WR_CONFIG); if (kbd_input_empty() == 0) return -1; - out8(I8042_DATA_REG, 0xf4); + out8(I8042_DATA_REG, + CONFIG_AT_TRANS | CONFIG_MCLK_DIS | + CONFIG_KCLK_DIS | CONFIG_SET_BIST); if (kbd_input_empty() == 0) return -1; @@ -502,7 +507,7 @@ static int kbd_reset(void) static int kbd_controller_present(void) { - return in8(I8042_STATUS_REG) != 0xff; + return in8(I8042_STS_REG) != 0xff; } /* @@ -520,18 +525,18 @@ void i8042_flush(void) int timeout; /* - * The delay is to give the keyboard controller some time to fill the - * next byte. + * The delay is to give the keyboard controller some time + * to fill the next byte. */ while (1) { - timeout = 100; /* wait for no longer than 100us */ - while (timeout > 0 && !(in8(I8042_STATUS_REG) & 0x01)) { + timeout = 100; /* wait for no longer than 100us */ + while (timeout > 0 && !(in8(I8042_STS_REG) & STATUS_OBF)) { udelay(1); timeout--; } - /* Try to pull next byte if not timeout. */ - if (in8(I8042_STATUS_REG) & 0x01) + /* Try to pull next byte if not timeout */ + if (in8(I8042_STS_REG) & STATUS_OBF) in8(I8042_DATA_REG); else break; @@ -544,7 +549,7 @@ int i8042_disable(void) return -1; /* Disable keyboard */ - out8(I8042_COMMAND_REG, 0xad); + out8(I8042_CMD_REG, CMD_KBD_DIS); if (kbd_input_empty() == 0) return -1; @@ -552,17 +557,16 @@ int i8042_disable(void) return 0; } -/******************************************************************************* - * - * i8042_kbd_init - reset keyboard and init state flags - */ +/* i8042_kbd_init - reset keyboard and init state flags */ int i8042_kbd_init(void) { int keymap, try; char *penv; - if (!kbd_controller_present() || board_i8042_skip()) + if (!kbd_controller_present() || board_i8042_skip()) { + debug("i8042 keyboard controller is not present\n"); return -1; + } /* Init keyboard device (default US layout) */ keymap = KBD_US; @@ -578,32 +582,33 @@ int i8042_kbd_init(void) kbd_flags = NORMAL; kbd_state = 0; kbd_led_set(); + return 0; } } + return -1; } - -/******************************************************************************* - * +/* * i8042_tstc - test if keyboard input is available - * option: cursor blinking if called in a loop + * + * 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 (--blinkCount == 0) { + if (--blink_count == 0) { cursor_state ^= 1; console_cursor(cursor_state); - blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; + blink_count = CONFIG_SYS_CONSOLE_BLINK_COUNT; udelay(10); } #endif - if ((in8(I8042_STATUS_REG) & 0x01) == 0) { + if ((in8(I8042_STS_REG) & STATUS_OBF) == 0) { return 0; } else { scan_code = in8(I8042_DATA_REG); @@ -615,14 +620,14 @@ int i8042_tstc(struct stdio_dev *dev) if (kbd_input != -1) return 1; } + return 0; } - -/******************************************************************************* - * +/* * i8042_getc - wait till keyboard input is available - * option: turn on/off cursor while waiting + * + * option: turn on/off cursor while waiting */ int i8042_getc(struct stdio_dev *dev) { @@ -630,21 +635,22 @@ int i8042_getc(struct stdio_dev *dev) unsigned char scan_code; while (kbd_input == -1) { - while ((in8(I8042_STATUS_REG) & 0x01) == 0) { + while ((in8(I8042_STS_REG) & STATUS_OBF) == 0) { #ifdef CONFIG_CONSOLE_CURSOR - if (--blinkCount == 0) { + if (--blink_count == 0) { cursor_state ^= 1; console_cursor(cursor_state); - blinkCount = CONFIG_SYS_CONSOLE_BLINK_COUNT; + 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); + kbd_conv_char(scan_code); } ret_chr = kbd_input; kbd_input = -1; + return ret_chr; } -- cgit v1.1 From 7d96166b1b1a261ddd4247befd62b35b2f482bae Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:06 -0700 Subject: x86: i8042: Correctly initialize the controller The existing i8042 keyboard controller driver has some issues. First of all, it does not issue a self-test command (0xaa) to the controller at the very beginning. Without this, the controller does not respond to any command at all. Secondly, it initializes the configuration byte register to turn on the keyboard's interrupt, as U-Boot does not normally allow interrupts to be processed. Finally, at the end of the initialization routine, it wrongly sets the controller to disable all interfaces including both keyboard and mouse. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/input/i8042.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index e8f59df..9b5fa32 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -454,51 +454,50 @@ static void kbd_conv_char(unsigned char scan_code) static int kbd_reset(void) { - /* KB Reset */ + u8 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; + /* 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; + /* set AT translation and disable irq */ if (kbd_input_empty() == 0) return -1; - - /* Set KBC mode */ - out8(I8042_CMD_REG, CMD_WR_CONFIG); - - if (kbd_input_empty() == 0) + out8(I8042_CMD_REG, CMD_RD_CONFIG); + if (kbd_output_full() == 0) return -1; - - out8(I8042_DATA_REG, - CONFIG_AT_TRANS | CONFIG_SET_BIST | CONFIG_KIRQ_EN); - + config = in8(I8042_DATA_REG); + config |= CONFIG_AT_TRANS; + config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN); if (kbd_input_empty() == 0) return -1; - - /* Enable Keyboard */ - out8(I8042_CMD_REG, CMD_KBD_EN); + out8(I8042_CMD_REG, CMD_WR_CONFIG); if (kbd_input_empty() == 0) return -1; + out8(I8042_DATA_REG, config); - out8(I8042_CMD_REG, CMD_WR_CONFIG); + /* enable keyboard */ if (kbd_input_empty() == 0) return -1; - - out8(I8042_DATA_REG, - CONFIG_AT_TRANS | CONFIG_MCLK_DIS | - CONFIG_KCLK_DIS | CONFIG_SET_BIST); + out8(I8042_CMD_REG, CMD_KBD_EN); if (kbd_input_empty() == 0) return -1; -- cgit v1.1 From 8ceb2429c97cc037bd2a6f27f4645d02a78e7aa5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:07 -0700 Subject: video: cfb_console: Allow VGA device to work without i8042 keyboard So far if CONFIG_VGA_AS_SINGLE_DEVICE is not defined, the VGA device will try to initialize a keyboard device (for x86, it is i8042). But if i8042 controller initialization fails (eg: there is no keyboard connected to the PS/2 port), drv_video_init() just simply returns. This kills the opportunity of using a usb keyboard later with the vga console, as the vga initialization part is actually ok, only keyboard part fails. Change the code logic to allow this. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Acked-by: Anatolij Gustschin --- drivers/video/cfb_console.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 30e0317..aa7ca86 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -2247,16 +2247,17 @@ __weak int board_video_skip(void) int drv_video_init(void) { - int skip_dev_init; struct stdio_dev console_dev; bool have_keyboard; + bool __maybe_unused keyboard_ok = false; /* Check if video initialization should be skipped */ if (board_video_skip()) return 0; /* Init video chip - returns with framebuffer cleared */ - skip_dev_init = (video_init() == -1); + if (video_init() == -1) + return 0; if (board_cfb_skip()) return 0; @@ -2272,11 +2273,9 @@ int drv_video_init(void) if (have_keyboard) { debug("KBD: Keyboard init ...\n"); #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE) - skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1); + keyboard_ok = !(VIDEO_KBD_INIT_FCT == -1); #endif } - if (skip_dev_init) - return 0; /* Init vga device */ memset(&console_dev, 0, sizeof(console_dev)); @@ -2287,7 +2286,7 @@ int drv_video_init(void) console_dev.puts = video_puts; /* 'puts' function */ #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE) - if (have_keyboard) { + if (have_keyboard && keyboard_ok) { /* Also init console device */ console_dev.flags |= DEV_FLAGS_INPUT; console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */ -- cgit v1.1 From 3242998e24b899540790077f8bbde447f4c039c6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:00:09 -0700 Subject: video: ct69000: Remove unused codes Remove unused CONFIG_USE_CPCIDVI wrapped codes. Signed-off-by: Bin Meng Acked-by: Simon Glass Acked-by: Anatolij Gustschin --- drivers/video/ct69000.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/video/ct69000.c b/drivers/video/ct69000.c index 168b9ba..22b3441 100644 --- a/drivers/video/ct69000.c +++ b/drivers/video/ct69000.c @@ -256,9 +256,6 @@ struct ctfb_chips_properties { static const struct ctfb_chips_properties chips[] = { {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220}, -#ifdef CONFIG_USE_CPCIDVI - {PCI_DEVICE_ID_CT_69030, 0x400000, 1, 4, -2, 3, 257, 100, 220}, -#endif {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220}, /* NOT TESTED */ {0, 0, 0, 0, 0, 0, 0, 0, 0} /* Terminator */ }; @@ -944,9 +941,6 @@ SetDrawingEngine (int bits_per_pixel) */ static struct pci_device_id supported[] = { {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000}, -#ifdef CONFIG_USE_CPCIDVI - {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69030}, -#endif {} }; @@ -1111,22 +1105,7 @@ video_hw_init (void) pGD->cprBase = pci_mem_base; /* Dummy */ /* set up Hardware */ -#ifdef CONFIG_USE_CPCIDVI - if (device_id == PCI_DEVICE_ID_CT_69030) { - ctWrite (CT_MSR_W_O, 0x0b); - ctWrite (0x3cd, 0x13); - ctWrite_i (CT_FP_O, 0x02, 0x00); - ctWrite_i (CT_FP_O, 0x05, 0x00); - ctWrite_i (CT_FP_O, 0x06, 0x00); - ctWrite (0x3c2, 0x0b); - ctWrite_i (CT_FP_O, 0x02, 0x10); - ctWrite_i (CT_FP_O, 0x01, 0x09); - } else { - ctWrite (CT_MSR_W_O, 0x01); - } -#else ctWrite (CT_MSR_W_O, 0x01); -#endif /* set the extended Registers */ ctLoadRegs (CT_XR_O, xreg); -- cgit v1.1 From 1887ed3ad6509a4ce411b7981dd27515e0c44bb7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:14:01 -0700 Subject: dm: pci: Optimize pci_uclass_post_bind() If there is no pci device listed in the device tree, don't bother scanning the device tree. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/pci/pci-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 2d12344..b25298f 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -632,6 +632,13 @@ error: static int pci_uclass_post_bind(struct udevice *bus) { /* + * If there is no pci device listed in the device tree, + * don't bother scanning the device tree. + */ + if (bus->of_offset == -1) + return 0; + + /* * Scan the device tree for devices. This does not probe the PCI bus, * as this is not permitted while binding. It just finds devices * mentioned in the device tree. -- cgit v1.1 From cdeb2ba99cb333f7729cd5784ea2de00e265f22f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 24 Aug 2015 01:14:02 -0700 Subject: dm: core: Fix code reentrancy issue in device_probe_child() The device might have already been probed during the call to device_probe() on its parent device (e.g. PCI bridge devices). In its parent device's probe routine, it might probe all of its child devices via device_probe() thus the codes reenter device_probe_child(). To support code reentrancy, test these allocated memory against NULL to avoid memory leak, and return to the caller if dev->flags has DM_FLAG_ACTIVATED set after device_probe() returns, so that we don't mess up the device. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/core/device.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/core/device.c b/drivers/core/device.c index e23a872..a31e25f 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -226,17 +226,17 @@ int device_probe_child(struct udevice *dev, void *parent_priv) drv = dev->driver; assert(drv); - /* Allocate private data if requested */ - if (drv->priv_auto_alloc_size) { + /* Allocate private data if requested and not reentered */ + if (drv->priv_auto_alloc_size && !dev->priv) { dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags); if (!dev->priv) { ret = -ENOMEM; goto fail; } } - /* Allocate private data if requested */ + /* Allocate private data if requested and not reentered */ size = dev->uclass->uc_drv->per_device_auto_alloc_size; - if (size) { + if (size && !dev->uclass_priv) { dev->uclass_priv = calloc(1, size); if (!dev->uclass_priv) { ret = -ENOMEM; @@ -251,7 +251,7 @@ int device_probe_child(struct udevice *dev, void *parent_priv) size = dev->parent->uclass->uc_drv-> per_child_auto_alloc_size; } - if (size) { + if (size && !dev->parent_priv) { dev->parent_priv = alloc_priv(size, drv->flags); if (!dev->parent_priv) { ret = -ENOMEM; @@ -264,6 +264,15 @@ int device_probe_child(struct udevice *dev, void *parent_priv) ret = device_probe(dev->parent); if (ret) goto fail; + + /* + * The device might have already been probed during + * the call to device_probe() on its parent device + * (e.g. PCI bridge devices). Test the flags again + * so that we don't mess up the device. + */ + if (dev->flags & DM_FLAG_ACTIVATED) + return 0; } seq = uclass_resolve_seq(dev); -- cgit v1.1